[
  {
    "path": ".gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "README.md",
    "content": "# Bem vindo ao Curso NodeBR\n\n<img src=\"./src/nodebr.jpeg\" alt=\"capa curso nodebr\" title=\"Bem vindo ao Curso NodeBR\"  />\n\nInscrições: [https://treinamento.nodebr.org/](https://treinamento.nodebr.org/)\n\n## SOBRE O TREINAMENTO\n\nVarrendo a internet, encontramos diversos treinamentos sobre  **Node.js**  e  **Javascript**. Mas na maioria das vezes estes conteúdos  **são focados na mesma coisa**! A grande maioria fala sobre a Stack  **MEAN**  (MongoDB, Express.js, Angular.js e Node.js), programação para Web ou apenas  **simples CRUDs**  (as operações básicas de sistemas: Cadastrar, Listar, Atualizar e Remover), coisas que para **estudos**  funcionam muito bem, mas a  **realidade**  no dia a dia de desenvolvimento de  **aplicações**  focado em  **produção**  é um pouco **diferente**.\n\nEste treinamento foi  **desenvolvido**  sob medida  **baseado**  em uma pesquisa sobre o que a  **comunidade brasileira mais necessita**, suas principais  **dificuldades**  e  **desafios**. Neste curso você aprenderá desde o básico de Javascript, ciclo de vida, manipulação de listas ao desenvolvimento real de aplicações em ambiente de produção. Na prática você também aprenderá conceitos sobre desenvolvimento orientado a testes, autenticação, autorização, documentação de serviços e gerenciamento de variáveis de ambiente (environments) de aplicações.\n\n## INSTRUTOR\n\n### [Erick Wendel](https://twitter.com/erickwendel_)\n\nErick Wendel is a Speaker, Software Consultant and community Co-organizer on Brazil. Named by Microsoft as Most Valuable Professional, and by Google as Google Developer Expert a specialist in Node.js, and Javascript Applications. He is  Software Independent Architect where help companies to make better and cheaper applications using Serverless, Container based applications, and Hybrid Cloud solutions. He has experience speaking and teaching on the biggest conferences in Brazil and Americas, working as voluntary Leader of NodeBR, Javascript São Paulo and Nerdzão Communities.\n\nTwitter:  [@erickwendel_](https://twitter.com/erickwendel_)  \nLinkedin:  [br.linkedin.com/in/erickwendel](http://br.linkedin.com/in/erickwendel)  \nGithub:  [github.com/erickwendel](https://github.com/erickwendel)  \nFacebook:  [fb.com/page.erickwendel](https://fb.com/page.erickwendel)\nWebsite:  [erickwendel.com](http://erickwendel.com/)\n\n## CONTEÚDO\n\n### Módulo 0  Introdução ao Curso\n\n- Introdução ao Curso e Objetivos\n- Tópicos abordados - O que aprenderei ?\n- Instalação e Configuração\n- Introdução ao Node.js\n- Conhecendo o gerenciador de pacotes NPM\n- Começando um projeto Node.js\n\n### Módulo 1  Sincronia de Funções Javascript\n\n- Introdução ao Capitulo\n- Entendendo o ciclo de vida de aplicações Javascript\n- Trabalhando com Callbacks\n- Introdução a Promises\n- Refatorando Callbacks para Promises\n- Introdução a resolução de Promises com async/await\n- Resolução de promises com Async/Await\n- Introdução à manipulação de eventos com EventEmitter\n- Trabalhando com Eventos com a classe EventEmitter\n\n### Módulo 2  Manipulação de Listas\n\n- Introdução ao Capitulo\n- Manipulando listas com For/ForIn/ForOf\n- Criando nosso proprio Array.Map\n- Criando nosso proprio Array.Filter\n- Criando nosso proprio Array.Reduce\n\n### Módulo 3  Introdução a desenvolvimento de testes automatizados\n\n- Introdução a desenvolvimento de testes automatizados em Javascript\n- Ambiente e configuração do ciclo de testes\n\n### Módulo 4  Node.js além da Web - Criando ferramentas de linha de comando\n\n- Introdução ao Capítulo\n- Manipulando arquivos - CREATE\n- Manipulando arquivos - READ\n- Manipulando arquivos - UPDATE\n- Manipulando arquivos - DELETE\n- Criando ferramentas de linha de comando com Commander\n\n### Módulo 5  Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Criando projetos multi-banco de dados\n- Trabalhando com o padrão Strategy para Multi DataSources\n- Design Patterns - Strategy\n- Demonstração multi datasources com strategy design pattern\n\n### Módulo 6  Introdução ao Postgres e Bancos Relacionais\n\n- Introdução ao Postgres e Bancos Relacionais\n- Postgres - Operadores e conexão\n- Conhecendo o Sequelize\n- Cadastrando Heróis - CREATE\n- Listando Heróis - READ\n- Atualizando Heróis - UPDATE\n- Removendo Heróis - DELETE\n\n### Módulo 7  MongoDB e Bancos Não-Relacionais (NoSQL)\n\n- Introdução ao MongoDB e Bancos Não-Relacionais (NoSQL)\n- Operadores e conexão\n- Conhecendo o Mongoose\n- Cadastrando Heróis - CREATE\n- Listando Heróis - READ\n- Atualizando Heróis - UPDATE\n- Removendo Heróis - DELETE\n\n### Módulo 8  Refatorando nosso projeto para bancos de dados multi-schemas\n\n- Refatorando a estratégia de MongoDB para multi-schemas\n- Refatorando a estratégia de Postgres para multi-schemas\n\n### Módulo 9  Node.js e Web Services - Criando serviços profissionais com Hapi.js\n\n- Introdução ao Capítulo\n- Conhecendo o Módulo HTTP\n- Introdução ao Hapi.js\n- Criando de estrutura para criação de APIs com Hapi.js\n- Entendendo o padrão RestFul para desenvolvimento de APIs\n- Cadastrando Heróis - POST\n- Listando Heróis - GET\n- Atualizando Heróis - PATCH / PUT\n- Removendo Heróis - DELETE\n- Código fonte do capítulo\n\n### Módulo 10  Documentação de Serviços com Swagger\n\n- Adicionando Swagger ao nosso Serviço\n\n### Módulo 11  Autenticação com Json Web Token\n\n- Introdução ao Capitulo\n- Como funciona o Json Web Token?\n- Configurando o JWT - plugins, testes e rota de login\n- Adicionando Hapi-JWT ao nosso Serviço de herois\n- Criando o modulo de autenticação de usuarios e hash de senha com bcrypt\n\n### Módulo 12  Publicação de serviços na Web\n\n- Introdução ao Capitulo\n- Trabalhando com multi-environments (development, production)\n- Publicação de nossos serviços gratuitamente com Heroku & Heroku toolbelt\n- MongoDB online e gratuito com Mongo Lab\n- Postgres Gratuito no Heroku\n- Trabalhando com PM2 para gerência de apps\n- Expondo cobertura de código com istanbul\n\n### Módulo 13  Próximos passos\n\n- O que aprender?\n\n## Certificado\n\nO melhor é que você ainda ganha este lindo certificado ao fim do treinamento! Vai ficar de fora? \n\n<img src=\"./src/certificado.png\" alt=\"certificado do curso\" title=\"Certificado de conclusão\"  />\n"
  },
  {
    "path": "module-00 - intro/1. npm/scripts.sh",
    "content": "instalação\n\nnpm\nhttp://npmjs.com/\n\n\n\n"
  },
  {
    "path": "module-00 - intro/2.nodejs/app/index.js",
    "content": "class HeroiCRUD {\n    constructor() {\n        this.herois = []\n    }\n\n    cadastrar(heroi) {\n        this.herois.push(heroi)\n    }\n\n    listar() {\n        return this.herois;\n    }\n\n    obterHeroiPorId(id) {\n        for (let posicao = 0; posicao < this.herois.length; ++posicao) {\n            const heroi = this.herois[posicao];\n            if (heroi.id !== id) continue;\n\n            return {\n                heroi,\n                posicao\n            };\n            break;\n        }\n\n        throw new Error('Heroi não encontrado!')\n    }\n\n    atualizar(id, novoHeroi) {\n        const {\n            heroi,\n            posicao\n        } = this.obterHeroiPorId(id);\n\n        this.herois[posicao] = Object.assign({}, heroi, novoHeroi)\n\n    }\n\n    remover(id) {\n        const {\n            posicao\n        } = this.obterHeroiPorId(id)\n\n        this.herois.pop(posicao)\n    }\n}\n\n(function main() {\n    try {\n        const heroiCrud = new HeroiCRUD()\n\n        // cadastrar\n        heroiCrud.cadastrar({\n            id: 1,\n            name: 'Erick'\n        })\n        heroiCrud.cadastrar({\n            id: 2,\n            name: 'Wendel'\n        })\n        heroiCrud.cadastrar({\n            id: 3,\n            name: 'Silva'\n        })\n        console.log('listar', heroiCrud.listar())\n\n        //atualizar\n        heroiCrud.atualizar(1, {\n            name: 'Flash'\n        })\n        const {\n            heroi\n        } = heroiCrud.obterHeroiPorId(1)\n        console.log('heroi atualizado', heroi)\n\n        // remover\n        heroiCrud.remover(2)\n        console.log('removido', heroiCrud.listar())\n    } catch (error) {\n        console.error('Erro!', error.message)\n    }\n})()"
  },
  {
    "path": "module-00 - intro/2.nodejs/app/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "module-00 - intro/2.nodejs/scripts.sh",
    "content": "---- \nnpm init \nnpm init -y\n\nnpm install\nnpm install -g modulo\nnpm install --save modulo\nnpm install --save-dev modulo\n\nnode -e \"1+1\" -p\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/1.callbacks/app/index.js",
    "content": "function obterPessoa(id, callback) {\n  setTimeout(() => {\n    return callback(null, {\n      nome: 'Erick',\n      id: 2,\n    });\n  }, 500);\n}\n\nfunction obterEndereco(pessoaId, callback) {\n  setTimeout(() => {\n    return callback(null, {\n      endereco: 'Av paulista, 22',\n      id: 3,\n    });\n  });\n}\n\nfunction obterTelefone(pessoaId, callback) {\n  setTimeout(() => {\n    return callback(null, {\n      telefone: '11969803388',\n      id: 22,\n    });\n  });\n}\n\n(function main() {\n  obterPessoa(2, (error1, result1) => {\n    obterEndereco(result1.id, (error2, result2) => {\n      obterTelefone(result1.id, (error3, result3) => {\n        console.log(`\n         Nome: ${result1.nome},\n         Telefone: ${result3.telefone},\n         Endereco: ${result2.endereco}\n        `);\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/1.callbacks/app/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/2.promise/app/index.js",
    "content": "function obterPessoa(id, callback) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      return resolve({\n        nome: 'Erick',\n        id: 2,\n      });\n    }, 500);\n  });\n}\n\nfunction obterEndereco(pessoaId) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      return resolve({\n        endereco: 'Av paulista, 22',\n        id: 3,\n      });\n    });\n  });\n}\n\nfunction obterTelefone(pessoaId) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      return resolve({\n        telefone: '11969803388',\n        id: 22,\n      });\n    });\n  });\n}\n\n(function main() {\n  Promise.resolve()\n    .then(_ => obterPessoa(2))\n    .then(pessoa => {\n      return obterTelefone(pessoa.id).then(({ telefone }) => {\n        return Object.assign({}, pessoa, { telefone });\n      });\n    })\n    .then(pessoa => {\n      return obterEndereco(pessoa.id).then(({ endereco }) => {\n        return Object.assign({}, pessoa, { endereco });\n      });\n    })\n    .then(pessoa => {\n      console.log(`\n      Nome: ${pessoa.nome},\n      Telefone: ${pessoa.telefone},\n      Endereco: ${pessoa.endereco}\n     `);\n    })\n    .catch(error => {\n      console.error('Deu ruim', error);\n    });\n})();\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/2.promise/app/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/3. async-await/app/index.js",
    "content": "function obterPessoa(id, callback) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      return resolve({\n        nome: 'Erick',\n        id: 2,\n      });\n    }, 500);\n  });\n}\n\nfunction obterEndereco(pessoaId) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      return resolve({\n        endereco: 'Av paulista, 22',\n        id: 3,\n      });\n    });\n  });\n}\n\nfunction obterTelefone(pessoaId) {\n  return new Promise((resolve, reject) => {\n    setTimeout(() => {\n      return resolve({\n        telefone: '11969803388',\n        id: 22,\n      });\n    });\n  });\n}\n\n(async function main() {\n  const pessoa = await obterPessoa(2);\n  const { telefone } = await obterTelefone(pessoa.id);\n  const { endereco } = await obterEndereco(pessoa.id);\n  console.log(`\n      Nome: ${pessoa.nome},\n      Telefone: ${telefone},\n      Endereco: ${endereco}\n     `);\n})();\n\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/3. async-await/app/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/4. event-emitter/app/index.js",
    "content": "const EventEmitter = require('events');\n\nclass MyEmitter extends EventEmitter {}\n\nconst myEmitter = new MyEmitter();\nmyEmitter.on('event', () => {\n  console.log('an event occurred!');\n});\nmyEmitter.emit('event');\n\nconst stdin = process.openStdin();\n\nstdin.addListener('data', function(d) {\n  // note:  d is an object, and when converted to a string it will\n  // end with a linefeed.  so we (rather crudely) account for that\n  // with toString() and then trim()\n  console.log('you entered: [' + d.toString().trim() + ']');\n});\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/4. event-emitter/app/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/5. observable/1.simple/index.js",
    "content": "class NotImplementedException extends Error {\n    constructor(message) {\n        this.message = message || \"Error, this method has to be implemented\"\n    }\n}\n\nclass ISubject {\n\n    subscribe(observer) {\n        throw new NotImplementedException()\n    }\n    unsubscribe(observer) {\n        throw new NotImplementedException()\n    }\n    notify() {\n        throw new NotImplementedException()\n    }\n}\n\n\nclass Observer {\n    constructor(name) {\n        this.observerName = name\n        this.update = this._update\n    }\n\n    _update(newValue, oldValue) {\n        console.log(`${this.observerName}, the value ${oldValue} was changed to ${newValue}`)\n    }\n}\n\n\nclass Subject extends ISubject {\n\n    constructor() {\n        super()\n        this.observers = []\n        const inventory = {\n            set: (target, propertyKey, newValue) => {\n                this.notify(newValue, target[propertyKey])\n                target[propertyKey] = newValue\n                return true\n            }\n        }\n        this._item = new Proxy({\n            count: 0,\n        }, inventory)\n    }\n\n    next(value) {\n        this._item.count = value;\n    }\n\n    notify(newValue, oldValue) {\n        this.observers.forEach(observer => observer.update(newValue, oldValue))\n    }\n\n    unsubscribe(observer) {\n        const index = this.observers.indexOf(observer)\n        console.log(`x${this.observers[index].observerName} will not notified anymore`)\n        this.observers.splice(index, 1)\n    }\n\n    subscribe(observable) {\n        this.observers.push(observable)\n    }\n}\n// behavioral pattern\n/**\n * We can say that observer is \n * something (objects in case of OOPS) which is looking upon (observing) \n * other object(s). Observer pattern is popularly known to be based on \n * \"The Hollywood Principle\" which says- \"Don’t call us, we will call you.\" \n * Pub-Sub (Publisher-Subscriber) is yet another popular nickname given to \n * Observer pattern.\n\n The online electronic store is going to be the subject.\n  Whenever the subject would have any addition in its inventory, \n  the observers (customers/users) who have subscribed to store notifications\n   would be notified through email\n */\n(async function main() {\n    const subject = new Subject()\n    // Observer1 takes a subscription to the store\n    const observer1 = new Observer(\"Erick\")\n    subject.subscribe(observer1)\n\n    // Observer2 also subscribes to the store\n    const observer2 = new Observer(\"Camilla\")\n    subject.subscribe(observer2)\n    subject.next(1);\n\n    // Observer1 unsubscribes \n    subject.unsubscribe(observer1)\n\n    // Observer3 subscribes to notifications.\n    subject.subscribe(new Observer(\"Amanda\"))\n    subject.next(2);\n\n})()"
  },
  {
    "path": "module-01 - sincronia de funcoes/5. observable/2. rxjs app/index.js",
    "content": "const Rx = require('rxjs');\nconst { switchMap, map, reduce, filter, from } = require('rxjs/operators');\nconst fs = require('fs');\n\nconst watch = dir =>\n  Rx.Observable.create(observer => {\n    fs.watch(dir, (eventType, filename) => {\n      return observer.next({\n        eventType,\n        filename: `${dir}/${filename.toString()}`,\n      });\n    });\n  });\n\nconst read = filename => Rx.bindNodeCallback(fs.readFile)(filename);\n\nwatch('./temp')\n  .pipe(\n    map(item => {\n      console.log(item);\n      return item;\n    }),\n  )\n  .pipe(switchMap(e => read(e.filename)), map(JSON.parse))\n  .pipe(switchMap(e => Rx.from(e)))\n  .subscribe(\n    e =>\n      console.log(`\n    Nome: ${e.nome},\n    Idade: ${e.idade}\n    `),\n    error => console.error('deu ruim', error),\n  );\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/5. observable/2. rxjs app/package.json",
    "content": "{\n  \"name\": \"app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"rxjs\": \"^6.2.0\"\n  }\n}\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/5. observable/2. rxjs app/temp/teste.1.json",
    "content": "[\n  {\n    \"nome\": \"Erick\",\n    \"idade\": 22\n  },\n  {\n    \"nome\": \"Wendel\",\n    \"idade\": 25\n  }\n]\n"
  },
  {
    "path": "module-01 - sincronia de funcoes/5. observable/2. rxjs app/teste.json",
    "content": "[\n  {\n    \"nome\": \"Maria\",\n    \"idade\": 22\n  },\n  {\n    \"nome\": \"Laisa\",\n    \"idade\": 23\n  }\n]\n"
  },
  {
    "path": "module-02 - manipulacao de listas/1.for-forin-forof.js",
    "content": "const { obterPessoas } = require('./service');\n\n//\n(async main => {\n  const result = await obterPessoas('a');\n  const names = [];\n  // for (let i = 0; i <= result.results.length - 1; i++) {\n  //   const pessoa = result.results[i];\n  //   names.push(pessoa.name);\n  // }\n  // console.log('names', names);\n\n  // for (let i in result.results) {\n  //   const pessoa = result.results[i];\n  //   names.push(pessoa.name);\n  // }\n\n  // console.log('names', names);\n\n  for (pessoa of result.results) {\n    names.push(pessoa.name);\n  }\n  console.log('names', names);\n})();\n"
  },
  {
    "path": "module-02 - manipulacao de listas/2.map.js",
    "content": "const { obterPessoas } = require('./service');\n\n//Criando nosso próprio Map\nArray.prototype.meuMap = function(callback) {\n  const novoArrayMapeado = [];\n  for (let indice = 0; indice <= this.length - 1; indice++)\n    novoArrayMapeado.push(callback(this[indice], indice));\n\n  return novoArrayMapeado;\n};\n\n//\n(async main => {\n  const result = await obterPessoas('a');\n  // map tradicional\n  //   const names = result.results.map((item, indice) => {\n  //     // má prática!\n  //     // item.name = 'aEW';\n  //     // return item.name;\n\n  //     // se quiser modificar o valor e retornar todo objeto\n  //     // return {\n  //     //   ...item,\n  //     //   name: 'aEW',\n  //     // };\n\n  //     return item.name;\n  //   });\n\n  const names = result.results.meuMap(\n    (item, index) => `[${index}]${item.name}`,\n  );\n  console.log(names);\n  // array original não deverá para ser alterado\n  // console.log(result.results[0].name, result.results[1].name);\n})();\n"
  },
  {
    "path": "module-02 - manipulacao de listas/3.filter.js",
    "content": "const { obterPessoas } = require('./service');\n\n// nosso proprio filter\nArray.prototype.meuFilter = function(callback) {\n  const itensFiltrados = [];\n  for (let indice = 0; indice <= this.length - 1; indice++) {\n    const result = callback(this[indice], indice, this);\n    if (!result) continue;\n\n    itensFiltrados.push(this[indice]);\n  }\n  return itensFiltrados;\n};\n\n(async main => {\n  const result = await obterPessoas('a');\n  const results = result.results;\n  //   const familiaLars = results.filter((item, indice, lista) => {\n  //     return item.name.toLowerCase().indexOf(`lars`) !== -1;\n  //   });\n  const familiaLars = results.meuFilter((item, indice, lista) => {\n    return item.name.toLowerCase().indexOf(`lars`) !== -1;\n  });\n  const names = familiaLars.map(item => item.name);\n  console.log(names);\n})();\n"
  },
  {
    "path": "module-02 - manipulacao de listas/4.reduce.js",
    "content": "const { obterPessoas } = require('./service');\n\nArray.prototype.meuReduce = function(callback, valorInicial) {\n  let valorFinal = typeof valorInicial !== undefined ? valorInicial : this[0];\n\n  for (let indice = 0; indice < this.length; indice++) {\n    valorFinal = callback(valorFinal, this[indice], this);\n  }\n  return valorFinal;\n};\n\n/** */\n\n//verificar o peso de todas as pessoas para informar à nave\n(async main => {\n  const { results } = await obterPessoas('a');\n  const pesos = results.map(item => parseInt(item.height));\n  //   const total = pesos.reduce(\n  //     (anterior, proximo, listaOriginal) => anterior + proximo,\n  //     0,\n  //   );\n\n  //   const total = pesos.meuReduce(\n  //     (anterior, proximo, listaOriginal) => anterior + proximo,\n  //     0,\n  //   );\n  const total = [['Erick', 'Wendel'], ['Nerdzão', 'NodeBR']]\n    .meuReduce((anterior, proximo) => anterior.concat(proximo), [])\n    .join(',');\n  console.log('total', total);\n})();\n"
  },
  {
    "path": "module-02 - manipulacao de listas/README.md",
    "content": "# Manipulação de listas\n\n**UPDATE 10/06/2020**\nA API do Swapi.co saiu do ar, use a http://swapi.dev/\n\n- Obter informações da API do Starwars\n- Obter pessoas pelo nome ([https://swapi.dev/api/people/?search=r2&format=json](https://swapi.dev/api/people/?search=r2&format=json))\n\n## Instalação\n\n- Consumir API via `axios`\n- `npm init -y`\n- `npm i axios`\n- Criar o arquivo `service.js` para fazer a intermediação entre a API e nossa aplicação\n\n## Rodando\n\n- `npm i`\n- `node 1.for-forin-forof.js` para visualizar exemplos com `for`, `forIn` e `forOf`\n- `node 2.map.js` para visualizar exemplos de `map` e como criar sua própria função `map`\n- `node 3.filter.js` para visualizar exemplos de `filter` e como criar sua própria função `filter`\n- `node 4.reduce.js` para visualizar exemplos de `reduce` e como criar sua própria função `reduce`\n"
  },
  {
    "path": "module-02 - manipulacao de listas/package.json",
    "content": "{\n  \"name\": \"module-02-lists\",\n  \"version\": \"1.0.0\",\n  \"description\": \"- Obter informações da API do Starwars - Obter pessoas pelo nome ([https://swapi.co/api/people/?search=r2&format=json](https://swapi.co/api/people/?search=r2&format=json))\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"axios\": \"^0.18.0\"\n  }\n}\n"
  },
  {
    "path": "module-02 - manipulacao de listas/service.js",
    "content": "const axios = require('axios');\nconst URL = `https://swapi.dev/api/people`;\n\nasync function obterPessoas(nome) {\n  const url = `${URL}/?search=${nome}&format=json`;\n  const response = await axios.get(url);\n  return response.data;\n}\n\nmodule.exports = {\n  obterPessoas,\n};\n"
  },
  {
    "path": "module-03 - Introdução a testes automatizados/README.md",
    "content": "# Modulo 3 - Introdução a desenvolvimento de testes automatizados\n\n## Instalação (do zero)\n\n- `npm i --save-dev mocha`\n- `npm i axios`\n\n## Objetivo\n\n- Iniciar instalação e tomar prática de testes em todas aplicações\n- Testar se o mapeamento aconteceu com sucesso\n- Mock de requisições externas HTTP\n\n## Comentarios\n\n- Usamos o `nock` para Mockar requisições HTTP\n- Requisições de terceiros, não podemos validar se está de pé, mas devemos validar caso os resultados venham conforme o esperado\n- Com o `nock` qualquer requisição usando aquela `requisição` será `fakeado` e usaremos o valor de uma variavel definida por nós como resposta padrão\n- Com ele podemos validar também possiveís erros com a função `replyWithError('DEU RUIM');`\n\n## Rodando\n\n- `npm i`\n- `npm t`\n"
  },
  {
    "path": "module-03 - Introdução a testes automatizados/package.json",
    "content": "{\n  \"name\": \"module03-tests\",\n  \"version\": \"1.0.0\",\n  \"description\": \"exemplos de cenários de teste\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"axios\": \"^0.18.0\",\n    \"nock\": \"^9.6.1\"\n  },\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"scripts\": {\n    \"test\": \"mocha -w --reporter nyan\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "module-03 - Introdução a testes automatizados/service.js",
    "content": "const axios = require('axios');\nconst URL = `https://swapi.co/api/people`;\n\nasync function obterPessoas(nome) {\n  const url = `${URL}/?search=${nome}&format=json`;\n  const response = await axios.get(url);\n  return response.data.results.map(mapearPessoas);\n}\n\nfunction mapearPessoas(item) {\n  return {\n    nome: item.name,\n    peso: item.height,\n  };\n}\nmodule.exports = {\n  obterPessoas,\n};\n"
  },
  {
    "path": "module-03 - Introdução a testes automatizados/test.js",
    "content": "const { deepEqual } = require('assert');\nconst { obterPessoas } = require('./service');\n\n// mock de requisiçoes HTTP\nconst nock = require('nock');\n\ndescribe('Swar Wars Tests', function() {\n  this.timeout(3000);\n  this.beforeEach(() => {\n    const response = {\n      count: 1,\n      next: null,\n      previous: null,\n      results: [\n        {\n          name: 'R2-D2',\n          height: '96',\n          mass: '32',\n          hair_color: 'n/a',\n          skin_color: 'white, blue',\n          eye_color: 'red',\n          birth_year: '33BBY',\n          gender: 'n/a',\n          homeworld: 'https://swapi.co/api/planets/8/',\n\n          vehicles: [],\n          starships: [],\n          created: '2014-12-10T15:11:50.376000Z',\n          edited: '2014-12-20T21:17:50.311000Z',\n          url: 'https://swapi.co/api/people/3/',\n        },\n      ],\n    };\n    // toda vez que bater nessa API vai retornar esse valor\n    // quando rolar algum resultado diferente o nock vai reclamar\n    // requisições externas não são problemas nossos! Mas temos que validar caso\n    // esteja tudo nos conformes, trazer as informações conforme o esperado\n    nock('https://swapi.co/api/people')\n      .get(`/?search=r2-d2&format=json`)\n      .reply(200, response);\n  });\n\n  it('deve buscar r2d2 com o formato correto', async () => {\n    const expected = [{ nome: 'R2-D2', peso: '96' }];\n    const nomeBase = `r2-d2`;\n    const resultado = await obterPessoas(nomeBase);\n    deepEqual(expected, resultado);\n  });\n\n  it('deve buscar r2d2 com o formato correto', async () => {\n    const expected = [{ nome: 'R2-D2', peso: '96' }];\n    const nomeBase = `r2-d2`;\n    const resultado = await obterPessoas(nomeBase);\n    deepEqual(expected, resultado);\n  });\n});\n"
  },
  {
    "path": "module-04 - ferramentas de linha de comando/cli.js",
    "content": "const commander = require('commander');\nconst Heroi = require('./heroi');\nconst Database = require('./database');\n\n(async () => {\n  /**\n   * node cli.js --help\n   */\n  commander\n    .version('v1')\n    .option('-n, --nome [value]', 'adicionar nome')\n    .option('-p, --poder [value]', 'adicionar poder')\n    //CRUD\n    .option('-c, --cadastrar', 'cadastrar Heroi')\n    .option('-r, --listar [value]', 'listar herois pelo id')\n    .option('-u, --atualizar [value]', 'atualizar heroi pelo id')\n    .option('-d, --remover [value]', 'remover heroi pelo id')\n    .parse(process.argv);\n\n  const heroi = new Heroi(commander);\n  try {\n    /**\n     * node cli.js --cadastrar params...\n     * node cli.js -c -n Hulk -p Forca\n     */\n    if (commander.cadastrar) {\n      await Database.cadastrar(heroi);\n      console.log('item cadastrado com sucesso!');\n      return;\n    }\n\n    /**\n     * node cli.js --listar\n     * node cli.js -r\n     * node cli.js -r 1\n     */\n    if (commander.listar) {\n      const id = commander.listar;\n      const result = await Database.listar(id);\n      console.log(result);\n      return;\n    }\n\n    /**\n     * node cli.js --atualizar\n     * node cli.js -u 1 -n papa\n     * node cli.js -u 1 -n thor -p trovao\n     */\n    if (commander.atualizar) {\n      const id = commander.atualizar;\n      console.log('id', id);\n      await Database.atualizar(id, heroi);\n      console.log('item atualizado com sucesso!');\n      return;\n    }\n    /**\n     * node cli.js --remover\n     * node cli.js -d 1\n     */\n    if (commander.remover) {\n      const id = commander.remover;\n      await Database.remover(id);\n      console.log('item removido com sucesso!');\n      return;\n    }\n  } catch (error) {\n    console.error('DEU RUIM', error);\n    return;\n  }\n})();\n"
  },
  {
    "path": "module-04 - ferramentas de linha de comando/database.js",
    "content": "/* \n*/\n\nconst { writeFile, readFile } = require('fs');\nconst { promisify } = require('util');\nconst [writeFileAsync, readFileAsync] = [\n  promisify(writeFile),\n  promisify(readFile),\n];\n\nclass Database {\n  constructor() {\n    this.FILENAME = 'heroes.json';\n  }\n\n  async obterArquivo() {\n    const arquivo = await readFileAsync(this.FILENAME);\n    return JSON.parse(arquivo.toString());\n  }\n\n  async escreverArquivo(dados) {\n    await writeFileAsync(this.FILENAME, JSON.stringify(dados));\n    return true;\n  }\n\n  async cadastrar(heroi) {\n    const dados = await this.obterArquivo();\n    //workaround para simular um id\n    const id = heroi.id <= 2 ? heroi.id : Date.now();\n    const heroiComId = {\n      ...heroi,\n      id,\n    };\n\n    return await this.escreverArquivo([...dados, heroiComId]);\n  }\n\n  async listar(id) {\n    const dados = await this.obterArquivo();\n    // se nao passar o id, traz tudo\n    return dados.filter(item => (id ? item.id == id : true));\n  }\n\n  async atualizar(id, atualizacoes) {\n    const dados = await this.obterArquivo();\n    const indice = dados.findIndex(item => item.id === parseInt(id));\n    if (indice === -1) {\n      throw Error('heroi não existe!');\n    }\n\n    const atual = dados[indice];\n    dados.splice(indice, 1);\n\n    //workaround para remover valores undefined do objeto\n    const objAtualizado = JSON.parse(JSON.stringify(atualizacoes));\n    const dadoAtualizado = Object.assign({}, atual, objAtualizado);\n\n    return await this.escreverArquivo([...dados, dadoAtualizado]);\n  }\n\n  async remover(id) {\n    if (!id) {\n      await this.escreverArquivo([]);\n      return true;\n    }\n\n    const dados = await this.obterArquivo();\n\n    const indice = dados.findIndex(item => item.id === parseInt(id));\n    if (indice === -1) {\n      throw Error('heroi não existe!');\n    }\n    const atual = dados[indice];\n    dados.splice(indice, 1);\n    await this.escreverArquivo(dados);\n    return true;\n  }\n}\n\nmodule.exports = new Database();\n"
  },
  {
    "path": "module-04 - ferramentas de linha de comando/heroes.json",
    "content": "[{\"nome\":\"Flash\",\"poder\":\"speed\",\"id\":1},{\"nome\":\"Flash\",\"poder\":\"speed\",\"id\":1},{\"nome\":\"Batman\",\"poder\":\"ricão\",\"id\":2}]"
  },
  {
    "path": "module-04 - ferramentas de linha de comando/heroi.js",
    "content": "class Heroi {\n  constructor({ id, nome, poder }) {\n    this.nome = nome;\n    this.poder = poder;\n    this.id = id || Date.now();\n  }\n}\nmodule.exports = Heroi;\n"
  },
  {
    "path": "module-04 - ferramentas de linha de comando/package.json",
    "content": "{\n  \"name\": \"module04-arquivos\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"database.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w --reporter nyan\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"commander\": \"^2.18.0\"\n  }\n}\n"
  },
  {
    "path": "module-04 - ferramentas de linha de comando/test.js",
    "content": "const { deepEqual, ok } = require('assert');\nconst Database = require('./database');\nconst DEFAULT_ITEM_CADASTRAR = { nome: 'Flash', poder: 'speed', id: 1 };\nconst DEFAULT_ITEM_ATUALIZAR = {\n  nome: 'Lanterna Verde',\n  poder: 'Anel do poder',\n  id: 2,\n};\n\ndescribe('Suite de manipulação de herois', () => {\n  before(async () => {\n    await Database.remover();\n    await Database.cadastrar(DEFAULT_ITEM_CADASTRAR);\n    await Database.cadastrar(DEFAULT_ITEM_ATUALIZAR);\n  });\n\n  it('deve cadastrar um heroi', async () => {\n    const expected = DEFAULT_ITEM_CADASTRAR;\n    await Database.cadastrar(DEFAULT_ITEM_CADASTRAR);\n\n    const [realResult] = await Database.listar(expected.id);\n    deepEqual(realResult, expected);\n  });\n\n  it('deve listar um heroi pelo id', async () => {\n    const expected = DEFAULT_ITEM_CADASTRAR;\n    const result = await Database.listar(1);\n    deepEqual(result[0], expected);\n  });\n\n  it('deve atualizar um heroi pelo id', async () => {\n    const expected = {\n      ...DEFAULT_ITEM_ATUALIZAR,\n      nome: 'Batman',\n      poder: 'ricão',\n    };\n    await Database.atualizar(expected.id, {\n      nome: expected.nome,\n      poder: expected.poder,\n    });\n\n    const [realResult] = await Database.listar(expected.id);\n    deepEqual(realResult, expected);\n  });\n});\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/README.md",
    "content": "docker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\""
  },
  {
    "path": "module-05 - nosso projeto multi-database/index.js",
    "content": "const mongoS = require('./src/db/strategies/mongoDbStrategy')\nconst postgS = require('./src/db/strategies/postgresStrategy')\nconst Context = require('./src/db/strategies/base/contextStrategy');\n\nconst contextM = new Context( new mongoS())\nconsole.log(contextM.create())\n\nconst contextP = new Context( new postgS())\nconsole.log(contextP.create())"
  },
  {
    "path": "module-05 - nosso projeto multi-database/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w *.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/scripts/mongodb.sh",
    "content": "use herois-db\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-05 - nosso projeto multi-database/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/src/db/strategies/mongoDbStrategy.js",
    "content": "const IDb = require('./base/interfaceDb');\nclass MongoDBStrategy extends IDb {\n  constructor() {\n    super();\n  }\n  create(item) {\n    return 'MongoDB';\n  }\n}\n\nmodule.exports = MongoDBStrategy;\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/src/db/strategies/postgresStrategy.js",
    "content": "const IDb = require('./base/interfaceDb');\nclass PostgresStrategy extends IDb {\n  constructor() {\n    super();\n  }\n  create(item) {\n    return 'Postgres';\n  }\n}\n\nmodule.exports = PostgresStrategy;\n"
  },
  {
    "path": "module-05 - nosso projeto multi-database/src/example1.js",
    "content": "basclass NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\n\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_DB=herois \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n\n\n\n\ndocker run -it \\\n -p 5432:5432 \\\n --link postgres:postgres \\\n postgres psql -h $HOST -p $PORT -U $USER $DATABASE\n\n```\n\n- Go to `http://localhost:8080/?pgsql=postgres&username=postgres&db=heroes&ns=public`"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/index.js",
    "content": ""
  },
  {
    "path": "module-06 - postgres e modelos relacionais/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w *.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('./src/db/strategies/postgresSQLStrategy');\nconst Context = require('./src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nconst context = new Context(new PostgresStrategy());\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/src/db/strategies/mongoDbStrategy.js",
    "content": "const IDb = require('./base/interfaceDb');\nclass MongoDBStrategy extends IDb {\n  constructor() {\n    super();\n  }\n  create(item) {\n    return 'MongoDB';\n  }\n}\n\nmodule.exports = MongoDBStrategy;\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/src/db/strategies/postgresSQLStrategy.js",
    "content": "const IDb = require('./base/interfaceDb');\nconst Sequelize = require('sequelize');\nclass PostgreSQLConnection {\n  static connect() {}\n}\nclass PostgreSQLStrategy extends IDb {\n  constructor() {\n    super();\n    this._herois = null;\n    this._sequelize = null;\n    this._connect();\n  }\n\n  defineModel() {\n    this._herois = this._sequelize.define(\n      'herois',\n      {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n      {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n      },\n    );\n  }\n\n  _connect() {\n    this._sequelize = new Sequelize(\n      'herois', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false\n    \n        // dialectOptions: {\n        //   ssl: true,\n        },\n    );\n\n    this.defineModel();\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._sequelize.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._herois.create(item, { raw: true });\n  }\n\n  read(item) {\n    return this._herois.findAll({ where: item, raw: true });\n  }\n\n  update(id, item) {\n    return this._herois.update(item, { where: { id } });\n  }\n  delete(id) {\n    const query = id ? { id } : {};\n    return this._herois.destroy({ where: query });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;\n"
  },
  {
    "path": "module-06 - postgres e modelos relacionais/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\n// context.read();\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/index.js",
    "content": ""
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/server.js",
    "content": ""
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/src/db/strategies/mongoDbStrategy.js",
    "content": "const ICrud = require('./base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    constructor() {\n        super()\n        this._herois = null\n        this._driver = null\n    }\n    async isConnected() {\n        const state = STATUS[this._driver.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._driver.readyState]\n\n    }\n    defineModel() {\n        const heroiSchema = new Mongoose.Schema({\n            nome: {\n                type: String,\n                required: true\n            },\n            poder: {\n                type: String,\n                required: true\n            },\n            insertedAt: {\n                type: Date,\n                default: new Date()\n            }\n        })\n        \n        //mocha workaround\n        this._herois = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)\n    }\n    connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n\n\n        this._driver = Mongoose.connection\n        this._driver.once('open', () => console.log('database rodando!!'))\n        this.defineModel()\n\n    }\n\n    async create(item) {\n        return this._herois.create(item)\n    }\n    async read(item = {}) {\n        return this._herois.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._herois.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._herois.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/src/db/strategies/postgresSQLStrategy.js",
    "content": "const IDb = require('./base/interfaceDb');\nconst Sequelize = require('sequelize');\nclass PostgreSQLConnection {\n  static connect() {}\n}\nclass PostgreSQLStrategy extends IDb {\n  constructor() {\n    super();\n    this._herois = null;\n    this._sequelize = null;\n    \n  }\n\n async defineModel() {\n    this._herois = this._sequelize.define(\n      'herois',\n      {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n      {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n        \n      },\n    );\n    await this._herois.sync()\n  }\n\n async connect() {\n    this._sequelize = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n        },\n    );\n\n    await this.defineModel();\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._sequelize.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._herois.create(item, { raw: true });\n  }\n\n  read(item) {\n    return this._herois.findAll({ where: item, raw: true });\n  }\n\n  update(id, item) {\n    return this._herois.update(item, { where: { id } });\n  }\n  delete(id) {\n    const query = id ? { id } : {};\n    return this._herois.destroy({ where: query });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('./../src/db/strategies/mongoDbStrategy')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nconst context = new Context(new MongoDb())\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        await context.connect()\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-07 - mongodb e bancos nao-relacionais/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgresSQLStrategy');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nconst context = new Context(new PostgresStrategy());\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    await context.connect()\n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.0 - organização de bases/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.0 - organização de bases/index.js",
    "content": ""
  },
  {
    "path": "module-08.0 - organização de bases/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.0 - organização de bases/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-08.0 - organização de bases/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.0 - organização de bases/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.0 - organização de bases/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.0 - organização de bases/server.js",
    "content": ""
  },
  {
    "path": "module-08.0 - organização de bases/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.0 - organização de bases/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.0 - organização de bases/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    \n     // 1o \n    constructor(connection, schema) {\n        super()\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n    // 3o\n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.0 - organização de bases/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.0 - organização de bases/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  //1o\n\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n  //2o\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.0 - organização de bases/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.0 - organização de bases/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.0 - organização de bases/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('./../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.0 - organização de bases/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\n// 1o criar pasta postgres\n// 2o criar schema heroiSchema\n// 3o alterar classe postgres\n  // constructor\n  // defineModel\n  // isConnected\n  // connection\n  // alterar _herois para _schema\n\n// 4o alterar teste\n  //adicionar connect\n  // adicionar defineModel\n  // adicionar context\n// testar\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst app = new Hapi.Server({\n    port: 4000\n})\nfunction mapRoutes (instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    \n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"hapi\": \"^17.7.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n   \n    \n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\ndescribe.only('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n})"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.1 - hapi - estrutura e listar/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha -w tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"hapi\": \"^17.7.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    \n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\ndescribe.only('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                nome: 'Flash',\n                poder: 'Velocidade'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n})"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('./../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.2 - hapi - cadastrar/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.3 - hapi - joi/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.3 - hapi - joi/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.3 - hapi - joi/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.3 - hapi - joi/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.3 - hapi - joi/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"hapi\": \"^17.7.0\",\n    \"joi\": \"^14.1.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-08.3 - hapi - joi/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.3 - hapi - joi/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.3 - hapi - joi/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.3 - hapi - joi/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.3 - hapi - joi/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.3 - hapi - joi/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.3 - hapi - joi/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.3 - hapi - joi/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.3 - hapi - joi/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.3 - hapi - joi/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.3 - hapi - joi/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.3 - hapi - joi/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.3 - hapi - joi/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                      },\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.3 - hapi - joi/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\ndescribe('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                nome: 'Flash',\n                poder: 'Velocidade'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n\n    })\n\n})"
  },
  {
    "path": "module-08.3 - hapi - joi/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.3 - hapi - joi/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.4 - hapi - atualizar/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.4 - hapi - atualizar/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.4 - hapi - atualizar/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.4 - hapi - atualizar/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"hapi\": \"^17.7.0\",\n    \"joi\": \"^14.1.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.4 - hapi - atualizar/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.4 - hapi - atualizar/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                      },\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                      },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.4 - hapi - atualizar/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\ndescribe.only('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        \n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n\n})\n\n"
  },
  {
    "path": "module-08.4 - hapi - atualizar/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.4 - hapi - atualizar/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.5 - hapi - remover/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.5 - hapi - remover/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.5 - hapi - remover/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.5 - hapi - remover/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.5 - hapi - remover/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"hapi\": \"^17.7.0\",\n    \"joi\": \"^14.1.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\"\n  }\n}\n"
  },
  {
    "path": "module-08.5 - hapi - remover/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.5 - hapi - remover/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.5 - hapi - remover/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.5 - hapi - remover/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.5 - hapi - remover/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.5 - hapi - remover/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.5 - hapi - remover/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.5 - hapi - remover/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.5 - hapi - remover/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.5 - hapi - remover/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.5 - hapi - remover/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.5 - hapi - remover/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.5 - hapi - remover/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                      },\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                      },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.5 - hapi - remover/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\ndescribe('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        \n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result =  await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}` \n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})\n\n"
  },
  {
    "path": "module-08.5 - hapi - remover/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.5 - hapi - remover/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.6 - hapi - swagger/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.6 - hapi - swagger/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n    await app.register([\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.6 - hapi - swagger/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.6 - hapi - swagger/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"hapi\": \"^17.7.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.6 - hapi - swagger/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.6 - hapi - swagger/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois'\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.6 - hapi - swagger/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\ndescribe('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        \n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result =  await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}` \n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})\n\n"
  },
  {
    "path": "module-08.6 - hapi - swagger/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.6 - hapi - swagger/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.7 - hapi - jwt/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.7 - hapi - jwt/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst AuthRoutes = require('./src/routes/authRoutes')\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\nconst Jwt = require('jsonwebtoken')\nconst HapiJwt = require('hapi-auth-jwt2')\nconst MINHA_CHAVE_SECRETA = 'ESSA_E_TRETA'\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n    await app.register([\n        HapiJwt,\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.auth.strategy('jwt', 'jwt', {\n        key: MINHA_CHAVE_SECRETA,\n        // options: {\n        //     expiresIn: 30\n        // },\n        validate: (dado, request) => {\n            return {\n                isValid: true\n            }\n        }\n    })\n\n\n    app.auth.default('jwt')\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods()),\n        ...mapRoutes(new AuthRoutes(MINHA_CHAVE_SECRETA), AuthRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.7 - hapi - jwt/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.7 - hapi - jwt/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"boom\": \"^7.2.2\",\n    \"hapi\": \"^17.7.0\",\n    \"hapi-auth-jwt2\": \"^8.1.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.7 - hapi - jwt/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/routes/authRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nconst Boom = require('boom')\n\nconst USER = {\n    username: 'xuxadasilva',\n    password: '123'\n}\nconst Jwt = require('jsonwebtoken')\n\nclass AuthRoutes extends BaseRoute {\n    constructor(key) {\n        super()\n        this.secret = key\n    }\n\n    login() {\n        return {\n            path: '/login',\n            method: 'POST',\n            config: {\n                auth: false,\n                tags: ['api'],\n                description: 'fazer login',\n                notes: 'retorna o token',\n                validate: {\n                    payload: {\n                        username: Joi.string().required(),\n                        password: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const {\n                    username,\n                    password\n                } = request.payload\n                if (\n                    username.toLowerCase() !== USER.username ||\n                    password !== USER.password\n                )\n                    return Boom.unauthorized()\n                    \n                return {\n                    token: Jwt.sign({\n                        username: username\n                    }, this.secret)\n                }\n            }\n        }\n    }\n}\nmodule.exports = AuthRoutes"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.7 - hapi - jwt/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois',\n                validate: {\n                }\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.7 - hapi - jwt/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\ndescribe('API Heroes test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        \n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois'\n        })\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result =  await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}` \n        })\n        assert.deepEqual(result.statusCode, 200) \n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})\n\n"
  },
  {
    "path": "module-08.7 - hapi - jwt/tests/auth.test.js",
    "content": "const assert = require('assert')\nconst api = require('../api')\nlet app = {}\n\n\ndescribe.only('Auth test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n    })\n    it('deve obter um token', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'Xuxadasilva',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(JSON.parse(result.payload).token.length > 10)\n    })\n\n    it('deve retornar não autorizado ao tentar obter um token com login errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'erickwendel',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n})"
  },
  {
    "path": "module-08.7 - hapi - jwt/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.7 - hapi - jwt/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst AuthRoutes = require('./src/routes/authRoutes')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\nconst HeroRoutes = require('./src/routes/heroRoutes')\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\nconst Jwt = require('jsonwebtoken')\nconst HapiJwt = require('hapi-auth-jwt2')\nconst MINHA_CHAVE_SECRETA = 'ESSA_E_TRETA'\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n    await app.register([\n        HapiJwt,\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.auth.strategy('jwt', 'jwt', {\n        key: MINHA_CHAVE_SECRETA,\n        // options: {\n        //     expiresIn: 30\n        // },\n        validate: (dado, request) => {\n            return {\n                isValid: true\n            }\n        }\n    })\n\n\n    app.auth.default('jwt')\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods()),\n        ...mapRoutes(new AuthRoutes(MINHA_CHAVE_SECRETA), AuthRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"boom\": \"^7.2.2\",\n    \"hapi\": \"^17.7.0\",\n    \"hapi-auth-jwt2\": \"^8.1.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n \nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize  = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item) {\n    return this._db.update(item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n    schema: {\n        id: {\n          type: Sequelize.INTEGER,\n          required: true,\n          primaryKey: true,\n          autoIncrement: true,\n        },\n        nome: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n        poder: {\n          type: Sequelize.STRING,\n          required: true,\n        },\n      },\n    options: {\n        //opcoes para base existente\n        tableName: 'TB_HEROIS',\n        freezeTableName: false,\n        timestamps: false,\n\n      }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/routes/authRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nconst Boom = require('boom')\n\nconst USER = {\n    username: 'xuxadasilva',\n    password: '123'\n}\nconst Jwt = require('jsonwebtoken')\n\nclass AuthRoutes extends BaseRoute {\n    constructor(key) {\n        super()\n        this.secret = key\n    }\n\n    login() {\n        return {\n            path: '/login',\n            method: 'POST',\n            config: {\n                auth: false,\n                tags: ['api'],\n                description: 'fazer login',\n                notes: 'retorna o token',\n                validate: {\n                    payload: {\n                        username: Joi.string().required(),\n                        password: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const {\n                    username,\n                    password\n                } = request.payload\n                if (\n                    username.toLowerCase() !== USER.username ||\n                    password !== USER.password\n                )\n                    return Boom.unauthorized()\n                    \n                return {\n                    token: Jwt.sign({\n                        username: username\n                    }, this.secret)\n                }\n            }\n        }\n    }\n}\nmodule.exports = AuthRoutes"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois',\n                validate: {\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown()\n                }\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\nlet MOCK_TOKEN = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Inh1eGFkYXNpbHZhIiwiaWF0IjoxNTQyNzI4MzQ0fQ.JvBOZa7yXds4ktQ7HvNRYO6-s1mbU7AKTJP9G2ghje4\"\nconst headers = {\n    Authorization: MOCK_TOKEN\n}\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        headers,\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\n\ndescribe('API Heroes test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n    it('não deve listar herois sem um token', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois', \n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n            headers\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            headers,\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/tests/auth.test.js",
    "content": "const assert = require('assert')\nconst api = require('../api')\nlet app = {}\n \n\ndescribe('Auth test suite', function ()  {\n    this.beforeAll(async () => {\n        app = await api\n    })\n    it('deve obter um token', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'Xuxadasilva',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 200)\n        assert.ok(JSON.parse(result.payload).token.length > 10)\n    })\n    \n    it('deve retornar não autorizado ao tentar obter um token com login errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'erickwendel',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode \n        \n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n})\n\n"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.8 - hapi - jwt-herois/tests/postgresStrategy.test.js",
    "content": "const { equal, deepEqual, ok } = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = { nome: 'Gaviao Negro', poder: 'flexas' };\nconst MOCK_HEROI_ATUALIZAR = { nome: 'Mulher Gavião', poder: 'grito' };\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function() {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n  \n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});\n"
  },
  {
    "path": "module-08.9 - hapi - user-validation/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```"
  },
  {
    "path": "module-08.9 - hapi - user-validation/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-08.9 - hapi - user-validation/api.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\n\nconst HeroRoutes = require('./src/routes/heroRoutes')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\n\nconst PostgresDB = require('./src/db/strategies/postgres/postgresSQLStrategy')\nconst AuthRoutes = require('./src/routes/authRoutes')\nconst UserSchema = require('./src/db/strategies/postgres/schemas/userSchema')\n\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\nconst Jwt = require('jsonwebtoken')\nconst HapiJwt = require('hapi-auth-jwt2')\nconst MINHA_CHAVE_SECRETA = 'ESSA_E_TRETA'\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connectionPostgres = await PostgresDB.connect()\n    const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n    const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    await app.register([\n        HapiJwt,\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.auth.strategy('jwt', 'jwt', {\n        key: MINHA_CHAVE_SECRETA,\n        // options: {\n        //     expiresIn: 30\n        // },\n        validate: (dado, request) => {\n            return {\n                isValid: true\n            }\n        }\n    })\n\n\n    app.auth.default('jwt')\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods()),\n        ...mapRoutes(new AuthRoutes(MINHA_CHAVE_SECRETA, postgresModel), AuthRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-08.9 - hapi - user-validation/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-08.9 - hapi - user-validation/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"bcrypt\": \"^3.0.2\",\n    \"boom\": \"^7.2.2\",\n    \"hapi\": \"^17.7.0\",\n    \"hapi-auth-jwt2\": \"^8.1.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "module-08.9 - hapi - user-validation/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-08.9 - hapi - user-validation/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-08.9 - hapi - user-validation/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_USUARIOS;\nCREATE TABLE TB_USUARIOS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     USERNAME  TEXT    NOT NULL UNIQUE,\n     PASSWORD TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_USUARIOS\n    (USERNAME, PASSWORD)\nVALUES\n    ('xuxadasilva', '$2b$10$8I99eSf.DcubdihXUXO6weT9iriDG0UIm13d5Ji1TCB1kq88LwZdy');\n\n---\nDROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-08.9 - hapi - user-validation/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item, upsert) {\n    return this._database.update(id, item, upsert);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n     // 1o \n    static connect() {\n        Mongoose.connect('mongodb://erickwendel:minhasenhasecreta@localhost:27017/herois', {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, { nome: 1, poder: 1, insertedAt: 1})\n    }\n    async update(id, item) {\n        return this._collection.updateOne({_id: id}, { $set: item})\n    }\n    \n    async delete(id) {\n        return this._collection.deleteOne({_id: id})\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n\nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize = new Sequelize(\n      'heroes', //database\n      'erickwendel', // user\n      'minhasenhasecreta', //senha\n      {\n        host: 'localhost',\n        dialect: 'postgres',\n        // case sensitive\n        quoteIdentifiers: false,\n        // deprecation warning\n        operatorsAliases: false,\n        //disable logging\n        logging: false\n        // dialectOptions: {\n        //   ssl: true,\n      },\n    );\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item, upsert = false) {\n    const fn = upsert ? 'upsert' : 'update'\n    return this._db[fn](item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n  name: 'herois',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    nome: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n    poder: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_HEROIS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/db/strategies/postgres/schemas/userSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst UserSchema = {\n  name: 'users',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    username: {\n      type: Sequelize.STRING,\n      unique: true,\n      required: true,\n    },\n    password: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_USUARIOS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = UserSchema"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/helpers/passwordHelper.js",
    "content": "const Bcrypt = require('bcrypt')\nconst {\n    promisify\n} = require('util')\nconst hashAsync = promisify(Bcrypt.hash)\nconst compareAsync = promisify(Bcrypt.compare)\nconst SALT = 3\n\nclass Password {\n\n    static hashPassword(pass) {\n        return hashAsync(pass, SALT)\n    }\n    static comparePassword(pass, hash) {\n        return compareAsync(pass, hash)\n    }\n}\nmodule.exports = Password"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/routes/authRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nconst Boom = require('boom')\nconst PasswordHelper = require('./../helpers/passwordHelper')\nconst USER = {\n    username: 'xuxadasilva',\n    password: '123'\n}\nconst Jwt = require('jsonwebtoken')\n\nclass AuthRoutes extends BaseRoute {\n    constructor(key, db) {\n        super()\n        this.secret = key\n        this.db = db\n    }\n\n    login() {\n\n        return {\n            path: '/login',\n            method: 'POST',\n            config: {\n                auth: false,\n                tags: ['api'],\n                description: 'fazer login',\n                notes: 'retorna o token',\n                validate: {\n                    payload: {\n                        username: Joi.string().required(),\n                        password: Joi.string().required()\n                    }\n                }\n            },\n            handler: async (request, headers) => {\n                const {\n                    username,\n                    password\n                } = request.payload\n\n                const [user] = await this.db.read({\n                    username: username.toLowerCase()\n                })\n\n                if (!user) {\n                    return Boom.unauthorized('O usuario informado nao existe')\n                }\n\n                const match = await PasswordHelper.comparePassword(password, user.password)\n\n                if (!match) {\n                    return Boom.unauthorized('O usuario e senha invalidos!')\n                }\n\n                // if (\n                //     username.toLowerCase() !== USER.username ||\n                //     password !== USER.password\n                // )\n                //     return Boom.unauthorized()\n\n                return {\n                    token: Jwt.sign({\n                        username: username\n                    }, this.secret)\n                }\n            }\n        }\n    }\n}\nmodule.exports = AuthRoutes"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-08.9 - hapi - user-validation/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois',\n                validate: {\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown()\n                }\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-08.9 - hapi - user-validation/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\nlet MOCK_TOKEN = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Inh1eGFkYXNpbHZhIiwiaWF0IjoxNTQyNzI4MzQ0fQ.JvBOZa7yXds4ktQ7HvNRYO6-s1mbU7AKTJP9G2ghje4\"\nconst headers = {\n    Authorization: MOCK_TOKEN\n}\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        headers,\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\n\ndescribe('API Heroes test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n    it('não deve listar herois sem um token', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois', \n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n            headers\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            headers,\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})"
  },
  {
    "path": "module-08.9 - hapi - user-validation/tests/auth.test.js",
    "content": "//1o criar test \n//2o criar passwordHelper\n//3o gerar senha e guardar\n//4o criar model de usuario\n//5o adicionar chamada em api.js\n//6o adicionar no construtor de auth receber o model\n//7o criar logica na route\n//8o adicionar upsert no context e postgresStrategy\n//9o adicionar no arquivo postgres.sql o script para criar a tabela\n\nconst assert = require('assert')\nconst api = require('../api')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\nconst PostgresDB = require('./../src/db/strategies/postgres/postgresSQLStrategy')\nconst UserSchema = require('./../src/db/strategies/postgres/schemas/userSchema')\n\nlet app = {}\nconst USER = {\n    username: 'xuxadasilva',\n    password: '321123'\n}\n\nconst USER_DB = {\n    ...USER,\n    password: '$2b$04$SdlyEJsy.o5UgsgVr5csJ.ralZVyPviGH80BOb0zJCTSis30RB8Ba'\n}\n\n\ndescribe('Auth test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n\n        const connectionPostgres = await PostgresDB.connect()\n        const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n        const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n        await postgresModel.update(null, USER_DB, true)\n    })\n    it('deve obter um token', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: USER\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(JSON.parse(result.payload).token.length > 10)\n    })\n\n    it('deve retornar não autorizado ao tentar obter um token com login errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'erickwendel',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n})"
  },
  {
    "path": "module-08.9 - hapi - user-validation/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-08.9 - hapi - user-validation/tests/passwordHelper.test.js",
    "content": "const assert = require('assert');\nconst PasswordHelper = require('../src/helpers/passwordHelper');\n\nconst SENHA = 'erick@32123';\nconst HASH = '$2b$04$nJuOS9YZH9FpsKTOSh2IPOZUW9IF83bo54FE2L/rO/Xzrl.pS/qV2'\n\n\n\ndescribe('UserHelper test suite', function () {\n    it('deve gerar um hash a partir de uma senha', async () => {\n        const result = await PasswordHelper.hashPassword(SENHA);\n\n        // const result = await PasswordHelper.hashPassword('321123');\n        // console.log('result', result)\n        assert.ok(result.length > 10);\n    });\n    it('deve comparar uma senha e seu hash', async () => {\n        const result = PasswordHelper.comparePassword(SENHA, HASH)\n        assert.ok(result)\n    })\n\n});"
  },
  {
    "path": "module-08.9 - hapi - user-validation/tests/postgresStrategy.test.js",
    "content": "const {\n  equal,\n  deepEqual,\n  ok\n} = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = {\n  nome: 'Gaviao Negro',\n  poder: 'flexas'\n};\nconst MOCK_HEROI_ATUALIZAR = {\n  nome: 'Mulher Gavião',\n  poder: 'grito'\n};\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function () {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n\n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});"
  },
  {
    "path": "module-09 - enviroment/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\nsleep 3;\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```\n"
  },
  {
    "path": "module-09 - enviroment/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-09 - enviroment/api.js",
    "content": "/**\n * 1o create config files\n * 2o find variables\n * 3o alter postgres to URI\n * 4o install dotenv\n * 5o replace variables\n */\nconst {\n    join\n} = require('path')\nconst {\n    config\n} = require('dotenv')\n\nconst {\n    ok\n} = require('assert')\n\nconst env = process.env.NODE_ENV || \"dev\"\nok(env === \"prod\" || env === \"dev\", \"environment inválida! Ou prod ou dev\")\n\nconst configPath = join('./config', `.env.${env}`)\n\nconfig({\n    path: configPath\n})\n\n\nconst Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\n\nconst HeroRoutes = require('./src/routes/heroRoutes')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\n\nconst PostgresDB = require('./src/db/strategies/postgres/postgresSQLStrategy')\nconst AuthRoutes = require('./src/routes/authRoutes')\nconst UserSchema = require('./src/db/strategies/postgres/schemas/userSchema')\n\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\nconst HapiJwt = require('hapi-auth-jwt2')\nconst MINHA_CHAVE_SECRETA = process.env.JWT_KEY\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: process.env.PORT\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connectionPostgres = await PostgresDB.connect()\n    const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n    const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    await app.register([\n        HapiJwt,\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.auth.strategy('jwt', 'jwt', {\n        key: MINHA_CHAVE_SECRETA,\n        // options: {\n        //     expiresIn: 30\n        // },\n        validate: (dado, request) => {\n            return {\n                isValid: true\n            }\n        }\n    })\n\n\n    app.auth.default('jwt')\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods()),\n        ...mapRoutes(new AuthRoutes(MINHA_CHAVE_SECRETA, postgresModel), AuthRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-09 - enviroment/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-09 - enviroment/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"mocha tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"bcrypt\": \"^3.0.2\",\n    \"boom\": \"^7.2.2\",\n    \"dotenv\": \"^6.2.0\",\n    \"hapi\": \"^17.7.0\",\n    \"hapi-auth-jwt2\": \"^8.1.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}\n"
  },
  {
    "path": "module-09 - enviroment/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-09 - enviroment/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-09 - enviroment/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_USUARIOS;\nCREATE TABLE TB_USUARIOS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     USERNAME  TEXT    NOT NULL UNIQUE,\n     PASSWORD TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_USUARIOS\n    (USERNAME, PASSWORD)\nVALUES\n    ('xuxadasilva', '$2b$10$8I99eSf.DcubdihXUXO6weT9iriDG0UIm13d5Ji1TCB1kq88LwZdy');\n\n---\nDROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-09 - enviroment/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item, upsert) {\n    return this._database.update(id, item, upsert);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n    // 1o \n    static connect() {\n        Mongoose.connect(process.env.MONGO_URL, {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, {\n            nome: 1,\n            poder: 1,\n            insertedAt: 1\n        })\n    }\n    async update(id, item) {\n        return this._collection.updateOne({\n            _id: id\n        }, {\n            $set: item\n        })\n    }\n\n    async delete(id) {\n        return this._collection.deleteOne({\n            _id: id\n        })\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n\nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize = new Sequelize(process.env.POSTGRES_URL, {\n      quoteIdentifiers: false,\n      // deprecation warning\n      operatorsAliases: false,\n      //disable logging\n      logging: false\n\n    })\n\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item, upsert = false) {\n    const fn = upsert ? 'upsert' : 'update'\n    return this._db[fn](item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n  name: 'herois',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    nome: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n    poder: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_HEROIS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-09 - enviroment/src/db/strategies/postgres/schemas/userSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst UserSchema = {\n  name: 'users',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    username: {\n      type: Sequelize.STRING,\n      unique: true,\n      required: true,\n    },\n    password: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_USUARIOS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = UserSchema"
  },
  {
    "path": "module-09 - enviroment/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-09 - enviroment/src/helpers/passwordHelper.js",
    "content": "const Bcrypt = require('bcrypt')\nconst {\n    promisify\n} = require('util')\nconst hashAsync = promisify(Bcrypt.hash)\nconst compareAsync = promisify(Bcrypt.compare)\nconst SALT = parseInt(process.env.PWD_SALT)\n\nclass Password {\n\n    static hashPassword(pass) {\n        return hashAsync(pass, SALT)\n    }\n    static comparePassword(pass, hash) {\n        return compareAsync(pass, hash)\n    }\n}\nmodule.exports = Password"
  },
  {
    "path": "module-09 - enviroment/src/routes/authRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nconst Boom = require('boom')\nconst PasswordHelper = require('./../helpers/passwordHelper')\nconst USER = {\n    username: 'xuxadasilva',\n    password: '123'\n}\nconst Jwt = require('jsonwebtoken')\n\nclass AuthRoutes extends BaseRoute {\n    constructor(key, db) {\n        super()\n        this.secret = key\n        this.db = db\n    }\n\n    login() {\n\n        return {\n            path: '/login',\n            method: 'POST',\n            config: {\n                auth: false,\n                tags: ['api'],\n                description: 'fazer login',\n                notes: 'retorna o token',\n                validate: {\n                    payload: {\n                        username: Joi.string().required(),\n                        password: Joi.string().required()\n                    }\n                }\n            },\n            handler: async (request, headers) => {\n                const {\n                    username,\n                    password\n                } = request.payload\n\n                const [user] = await this.db.read({\n                    username: username.toLowerCase()\n                })\n\n                if (!user) {\n                    return Boom.unauthorized('O usuario informado nao existe')\n                }\n\n                const match = await PasswordHelper.comparePassword(password, user.password)\n\n                if (!match) {\n                    return Boom.unauthorized('O usuario e senha invalidos!')\n                }\n\n                // if (\n                //     username.toLowerCase() !== USER.username ||\n                //     password !== USER.password\n                // )\n                //     return Boom.unauthorized()\n\n                return {\n                    token: Jwt.sign({\n                        username: username\n                    }, this.secret)\n                }\n            }\n        }\n    }\n}\nmodule.exports = AuthRoutes"
  },
  {
    "path": "module-09 - enviroment/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-09 - enviroment/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois',\n                validate: {\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown()\n                }\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-09 - enviroment/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\nlet MOCK_TOKEN = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Inh1eGFkYXNpbHZhIiwiaWF0IjoxNTQyNzI4MzQ0fQ.JvBOZa7yXds4ktQ7HvNRYO6-s1mbU7AKTJP9G2ghje4\"\nconst headers = {\n    Authorization: MOCK_TOKEN\n}\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        headers,\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\n\ndescribe('API Heroes test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n    it('não deve listar herois sem um token', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois', \n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n            headers\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            headers,\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})"
  },
  {
    "path": "module-09 - enviroment/tests/auth.test.js",
    "content": "//1o criar test \n//2o criar passwordHelper\n//3o gerar senha e guardar\n//4o criar model de usuario\n//5o adicionar chamada em api.js\n//6o adicionar no construtor de auth receber o model\n//7o criar logica na route\n//8o adicionar upsert no context e postgresStrategy\n//9o adicionar no arquivo postgres.sql o script para criar a tabela\n\nconst assert = require('assert')\nconst api = require('../api')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\nconst PostgresDB = require('./../src/db/strategies/postgres/postgresSQLStrategy')\nconst UserSchema = require('./../src/db/strategies/postgres/schemas/userSchema')\n\nlet app = {}\nconst USER = {\n    username: 'xuxadasilva',\n    password: '321123'\n}\n\nconst USER_DB = {\n    ...USER,\n    password: '$2b$04$SdlyEJsy.o5UgsgVr5csJ.ralZVyPviGH80BOb0zJCTSis30RB8Ba'\n}\n\n\ndescribe('Auth test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n\n        const connectionPostgres = await PostgresDB.connect()\n        const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n        const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n        await postgresModel.update(null, USER_DB, true)\n    })\n    it('deve obter um token', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: USER\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(JSON.parse(result.payload).token.length > 10)\n    })\n\n    it('deve retornar não autorizado ao tentar obter um token com login errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'erickwendel',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n})"
  },
  {
    "path": "module-09 - enviroment/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const { nome, poder } = await context.create(MOCK_HEROI_CADASTRAR)\n        \n        assert.deepEqual({ nome, poder }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{ nome, poder}] = await context.read({ nome: MOCK_HEROI_CADASTRAR.nome})\n        const result = {\n            nome, poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-09 - enviroment/tests/passwordHelper.test.js",
    "content": "const assert = require('assert');\nconst PasswordHelper = require('../src/helpers/passwordHelper');\n\nconst SENHA = 'erick@32123';\nconst HASH = '$2b$04$nJuOS9YZH9FpsKTOSh2IPOZUW9IF83bo54FE2L/rO/Xzrl.pS/qV2'\n\n\n\ndescribe('UserHelper test suite', function () {\n    it('deve gerar um hash a partir de uma senha', async () => {\n        const result = await PasswordHelper.hashPassword(SENHA);\n\n        // const result = await PasswordHelper.hashPassword('321123');\n        // console.log('result', result)\n        assert.ok(result.length > 10);\n    });\n    it('deve comparar uma senha e seu hash', async () => {\n        const result = PasswordHelper.comparePassword(SENHA, HASH)\n        assert.ok(result)\n    })\n\n});"
  },
  {
    "path": "module-09 - enviroment/tests/postgresStrategy.test.js",
    "content": "const {\n  equal,\n  deepEqual,\n  ok\n} = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = {\n  nome: 'Gaviao Negro',\n  poder: 'flexas'\n};\nconst MOCK_HEROI_ATUALIZAR = {\n  nome: 'Mulher Gavião',\n  poder: 'grito'\n};\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function () {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n\n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});"
  },
  {
    "path": "module-10 - production-mongodb-postgres/.gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "module-10 - production-mongodb-postgres/Procfile",
    "content": "web: npm run prod"
  },
  {
    "path": "module-10 - production-mongodb-postgres/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\n\nsleep 5;\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```\n"
  },
  {
    "path": "module-10 - production-mongodb-postgres/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-10 - production-mongodb-postgres/api.js",
    "content": "/**\n * 1o Add procfile\n * 2o up to heroku\n * \n * \n * 2o add mlab\n * 3o run NODE_ENV=prod npm t\n * \n * 4o add postgres\n * 5o add process.env.SSL_DB\n * 6o add sequelize ssl\n * 7o modify npm t --timeout 10000\n * 8o upto heroku\n * \n * 9o install pm2\n * 10 up to heroku\n * 11 add pm2 to pre-install\n * 12 up to heroku\n */\nconst {\n    join\n} = require('path')\nconst {\n    config\n} = require('dotenv')\n\nconst {\n    ok\n} = require('assert')\n\nconst env = process.env.NODE_ENV || \"dev\"\nok(env === \"prod\" || env === \"dev\", \"environment inválida! Ou prod ou dev\")\n\nconst configPath = join('./config', `.env.${env}`)\n\nconfig({\n    path: configPath\n})\n\n\nconst Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\n\nconst HeroRoutes = require('./src/routes/heroRoutes')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\n\nconst PostgresDB = require('./src/db/strategies/postgres/postgresSQLStrategy')\nconst AuthRoutes = require('./src/routes/authRoutes')\nconst UserSchema = require('./src/db/strategies/postgres/schemas/userSchema')\n\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\nconst HapiJwt = require('hapi-auth-jwt2')\nconst MINHA_CHAVE_SECRETA = process.env.JWT_KEY\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: process.env.PORT\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connectionPostgres = await PostgresDB.connect()\n    const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n    const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    await app.register([\n        HapiJwt,\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.auth.strategy('jwt', 'jwt', {\n        key: MINHA_CHAVE_SECRETA,\n        // options: {\n        //     expiresIn: 30\n        // },\n        validate: (dado, request) => {\n            return {\n                isValid: true\n            }\n        }\n    })\n\n\n    app.auth.default('jwt')\n\n\n    app.route([\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods()),\n        ...mapRoutes(new AuthRoutes(MINHA_CHAVE_SECRETA, postgresModel), AuthRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-10 - production-mongodb-postgres/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-10 - production-mongodb-postgres/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"preinstall\": \"npm i -g pm2\",\n    \"prod\": \"cross-env NODE_ENV=prod pm2-runtime api.js\",\n    \"start\": \"nodemon api.js\",\n    \"test\": \"mocha --timeout 10000 tests/*.test.js\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\"\n  },\n  \"dependencies\": {\n    \"bcrypt\": \"^3.0.2\",\n    \"boom\": \"^7.2.2\",\n    \"cross-env\": \"^5.2.0\",\n    \"dotenv\": \"^6.2.0\",\n    \"hapi\": \"^17.7.0\",\n    \"hapi-auth-jwt2\": \"^8.1.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}"
  },
  {
    "path": "module-10 - production-mongodb-postgres/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-10 - production-mongodb-postgres/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-10 - production-mongodb-postgres/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_USUARIOS;\nCREATE TABLE TB_USUARIOS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     USERNAME  TEXT    NOT NULL UNIQUE,\n     PASSWORD TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_USUARIOS\n    (USERNAME, PASSWORD)\nVALUES\n    ('xuxadasilva', '$2b$10$8I99eSf.DcubdihXUXO6weT9iriDG0UIm13d5Ji1TCB1kq88LwZdy');\n\n---\nDROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-10 - production-mongodb-postgres/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item, upsert) {\n    return this._database.update(id, item, upsert);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n    // 1o \n    static connect() {\n        Mongoose.connect(process.env.MONGO_URL, {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, {\n            nome: 1,\n            poder: 1,\n            insertedAt: 1\n        })\n    }\n    async update(id, item) {\n        return this._collection.updateOne({\n            _id: id\n        }, {\n            $set: item\n        })\n    }\n\n    async delete(id) {\n        return this._collection.deleteOne({\n            _id: id\n        })\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n\nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize = new Sequelize(process.env.POSTGRES_URL, {\n      quoteIdentifiers: false,\n      ssl: process.env.SSL_DB,\n      dialectOptions: {\n        ssl: process.env.SSL_DB,\n\n      },\n      // deprecation warning\n      operatorsAliases: false,\n      //disable logging\n      logging: false\n\n    })\n\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item, upsert = false) {\n    const fn = upsert ? 'upsert' : 'update'\n    return this._db[fn](item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n  name: 'herois',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    nome: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n    poder: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_HEROIS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/db/strategies/postgres/schemas/userSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst UserSchema = {\n  name: 'users',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    username: {\n      type: Sequelize.STRING,\n      unique: true,\n      required: true,\n    },\n    password: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_USUARIOS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = UserSchema"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/helpers/passwordHelper.js",
    "content": "const Bcrypt = require('bcrypt')\nconst {\n    promisify\n} = require('util')\nconst hashAsync = promisify(Bcrypt.hash)\nconst compareAsync = promisify(Bcrypt.compare)\nconst SALT = parseInt(process.env.PWD_SALT)\n\nclass Password {\n\n    static hashPassword(pass) {\n        return hashAsync(pass, SALT)\n    }\n    static comparePassword(pass, hash) {\n        return compareAsync(pass, hash)\n    }\n}\nmodule.exports = Password"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/routes/authRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nconst Boom = require('boom')\nconst PasswordHelper = require('./../helpers/passwordHelper')\nconst USER = {\n    username: 'xuxadasilva',\n    password: '123'\n}\nconst Jwt = require('jsonwebtoken')\n\nclass AuthRoutes extends BaseRoute {\n    constructor(key, db) {\n        super()\n        this.secret = key\n        this.db = db\n    }\n\n    login() {\n\n        return {\n            path: '/login',\n            method: 'POST',\n            config: {\n                auth: false,\n                tags: ['api'],\n                description: 'fazer login',\n                notes: 'retorna o token',\n                validate: {\n                    payload: {\n                        username: Joi.string().required(),\n                        password: Joi.string().required()\n                    }\n                }\n            },\n            handler: async (request, headers) => {\n                const {\n                    username,\n                    password\n                } = request.payload\n\n                const [user] = await this.db.read({\n                    username: username.toLowerCase()\n                })\n\n                if (!user) {\n                    return Boom.unauthorized('O usuario informado nao existe')\n                }\n\n                const match = await PasswordHelper.comparePassword(password, user.password)\n\n                if (!match) {\n                    return Boom.unauthorized('O usuario e senha invalidos!')\n                }\n\n                // if (\n                //     username.toLowerCase() !== USER.username ||\n                //     password !== USER.password\n                // )\n                //     return Boom.unauthorized()\n\n                return {\n                    token: Jwt.sign({\n                        username: username\n                    }, this.secret)\n                }\n            }\n        }\n    }\n}\nmodule.exports = AuthRoutes"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-10 - production-mongodb-postgres/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois',\n                validate: {\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown()\n                }\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-10 - production-mongodb-postgres/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\nlet MOCK_TOKEN = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Inh1eGFkYXNpbHZhIiwiaWF0IjoxNTQyNzI4MzQ0fQ.JvBOZa7yXds4ktQ7HvNRYO6-s1mbU7AKTJP9G2ghje4\"\nconst headers = {\n    Authorization: MOCK_TOKEN\n}\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        headers,\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\n\ndescribe('API Heroes test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n    it('não deve listar herois sem um token', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n            headers\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            headers,\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})"
  },
  {
    "path": "module-10 - production-mongodb-postgres/tests/auth.test.js",
    "content": "//1o criar test \n//2o criar passwordHelper\n//3o gerar senha e guardar\n//4o criar model de usuario\n//5o adicionar chamada em api.js\n//6o adicionar no construtor de auth receber o model\n//7o criar logica na route\n//8o adicionar upsert no context e postgresStrategy\n//9o adicionar no arquivo postgres.sql o script para criar a tabela\n\nconst assert = require('assert')\nconst api = require('../api')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\nconst PostgresDB = require('./../src/db/strategies/postgres/postgresSQLStrategy')\nconst UserSchema = require('./../src/db/strategies/postgres/schemas/userSchema')\n\nlet app = {}\nconst USER = {\n    username: 'xuxadasilva',\n    password: '321123'\n}\n\nconst USER_DB = {\n    ...USER,\n    password: '$2b$04$SdlyEJsy.o5UgsgVr5csJ.ralZVyPviGH80BOb0zJCTSis30RB8Ba'\n}\n\n\ndescribe('Auth test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n\n        const connectionPostgres = await PostgresDB.connect()\n        const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n        const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n        await postgresModel.update(null, USER_DB, true)\n    })\n    it('deve obter um token', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: USER\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(JSON.parse(result.payload).token.length > 10)\n    })\n\n    it('deve retornar não autorizado ao tentar obter um token com login errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'erickwendel',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n})"
  },
  {
    "path": "module-10 - production-mongodb-postgres/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const {\n            nome,\n            poder\n        } = await context.create(MOCK_HEROI_CADASTRAR)\n\n        assert.deepEqual({\n            nome,\n            poder\n        }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{\n            nome,\n            poder\n        }] = await context.read({\n            nome: MOCK_HEROI_CADASTRAR.nome\n        })\n        const result = {\n            nome,\n            poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-10 - production-mongodb-postgres/tests/passwordHelper.test.js",
    "content": "const assert = require('assert');\nconst PasswordHelper = require('../src/helpers/passwordHelper');\n\nconst SENHA = 'erick@32123';\nconst HASH = '$2b$04$nJuOS9YZH9FpsKTOSh2IPOZUW9IF83bo54FE2L/rO/Xzrl.pS/qV2'\n\n\n\ndescribe('UserHelper test suite', function () {\n    it('deve gerar um hash a partir de uma senha', async () => {\n        const result = await PasswordHelper.hashPassword(SENHA);\n\n        // const result = await PasswordHelper.hashPassword('321123');\n        // console.log('result', result)\n        assert.ok(result.length > 10);\n    });\n    it('deve comparar uma senha e seu hash', async () => {\n        const result = PasswordHelper.comparePassword(SENHA, HASH)\n        assert.ok(result)\n    })\n\n});"
  },
  {
    "path": "module-10 - production-mongodb-postgres/tests/postgresStrategy.test.js",
    "content": "const {\n  equal,\n  deepEqual,\n  ok\n} = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = {\n  nome: 'Gaviao Negro',\n  poder: 'flexas'\n};\nconst MOCK_HEROI_ATUALIZAR = {\n  nome: 'Mulher Gavião',\n  poder: 'grito'\n};\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function () {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n\n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});"
  },
  {
    "path": "module-11 - istanbul/.gitignore",
    "content": "node_modules\n.nyc_output \ncoverage\nhtml-test"
  },
  {
    "path": "module-11 - istanbul/Procfile",
    "content": "web: npm run prod"
  },
  {
    "path": "module-11 - istanbul/README.md",
    "content": "# Módulo 5 - Bancos de Dados - Nosso projeto Multi-banco de dados\n\n- Trabalhando com o padrão Strategy para Multi DataSources\n\n## Instalando docker para usar o MongoDB e Postgres\n\n```shell\ndocker run \\\n    --name postgres \\\n    -e POSTGRES_USER=erickwendel \\\n    -e POSTGRES_PASSWORD=minhasenhasecreta \\\n    -e POSTGRES_DB=heroes \\\n    -p 5432:5432 \\\n    -d \\\n    postgres\n\ndocker run \\\n    --name adminer \\\n    -p 8080:8080 \\\n    --link postgres:postgres \\\n    -d \\\n    adminer\n\n## ---- MONGODB\ndocker run \\\n    --name mongodb \\\n    -p 27017:27017 \\\n    -e MONGO_INITDB_ROOT_USERNAME=admin \\\n    -e MONGO_INITDB_ROOT_PASSWORD=senhaadmin \\\n    -d \\\n    mongo:4\n\ndocker run \\\n    --name mongoclient \\\n    -p 3000:3000 \\\n    --link mongodb:mongodb \\\n    -d \\\n    mongoclient/mongoclient\n\n\nsleep 5;\n\ndocker exec -it mongodb \\\n    mongo --host localhost -u admin -p senhaadmin --authenticationDatabase admin \\\n    --eval \"db.getSiblingDB('herois').createUser({user: 'erickwendel', pwd: 'minhasenhasecreta', roles: [{role: 'readWrite', db: 'herois'}]})\"\n```\n"
  },
  {
    "path": "module-11 - istanbul/api-example.js",
    "content": "const Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongoDbStrategy')\nconst mongoDb = new Context(new MongoDB())\n\nconst app = new Hapi.Server({\n    port: 4000\n})\n\nasync function main() {\n    mongoDb.connect()\n\n    app.route({\n        path: '/herois',\n        method: 'GET',\n        handler: (request, headers) => {\n            return mongoDb.read()\n        }\n    })\n\n    await app.start()\n    console.log('server running at', app.info.port)\n}\nmain()"
  },
  {
    "path": "module-11 - istanbul/api.js",
    "content": "/**\n * 1o Add procfile\n * 2o up to heroku\n * 2o add mlab\n * 3o run NODE_ENV=prod npm t\n * 4o add postgres\n * 5o add process.env.SSL_DB\n * 6o add sequelize ssl\n * 7o modify npm t --timeout 10000\n * 8o upto heroku\n * 9o install pm2\n * 10 up to heroku\n * 11 add pm2 to pre-install\n * 12 up to heroku\n */\nconst {\n    join\n} = require('path')\nconst {\n    config\n} = require('dotenv')\n\nconst {\n    ok\n} = require('assert')\n\nconst env = process.env.NODE_ENV || \"dev\"\nok(env === \"prod\" || env === \"dev\", \"environment inválida! Ou prod ou dev\")\n\nconst configPath = join('./config', `.env.${env}`)\n\nconfig({\n    path: configPath\n})\n\n\nconst Hapi = require('hapi')\nconst Context = require('./src/db/strategies/base/contextStrategy')\nconst MongoDB = require('./src/db/strategies/mongodb/mongoDbStrategy')\n\nconst HeroRoutes = require('./src/routes/heroRoutes')\nconst HeroSchema = require('./src/db/strategies/mongodb/schemas/heroSchema')\n\nconst PostgresDB = require('./src/db/strategies/postgres/postgresSQLStrategy')\nconst AuthRoutes = require('./src/routes/authRoutes')\nconst UserSchema = require('./src/db/strategies/postgres/schemas/userSchema')\n\nconst UtilRoutes = require('./src/routes/utilRoutes')\n\nconst HapiSwagger = require('hapi-swagger')\nconst Inert = require('inert')\nconst Vision = require('vision')\nconst HapiJwt = require('hapi-auth-jwt2')\nconst MINHA_CHAVE_SECRETA = process.env.JWT_KEY\n\nconst swaggerConfig = {\n    info: {\n        title: '#CursoNodeBR - API Herois',\n        version: 'v1.0'\n    },\n    lang: 'pt'\n\n}\n\nconst app = new Hapi.Server({\n    port: process.env.PORT,\n    routes: {\n        cors: true\n    }\n})\n\nfunction mapRoutes(instance, methods) {\n    return methods.map(method => instance[method]())\n}\n\nasync function main() {\n    const connectionPostgres = await PostgresDB.connect()\n    const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n    const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n\n    const connection = MongoDB.connect()\n    const mongoDb = new Context(new MongoDB(connection, HeroSchema))\n\n\n    await app.register([\n        HapiJwt,\n        Inert,\n        Vision,\n        {\n            plugin: HapiSwagger,\n            options: swaggerConfig\n        }\n    ])\n    app.auth.strategy('jwt', 'jwt', {\n        key: MINHA_CHAVE_SECRETA,\n        // options: {\n        //     expiresIn: 30\n        // },\n        validate: (dado, request) => {\n            return {\n                isValid: true\n            }\n        }\n    })\n\n\n    app.auth.default('jwt')\n\n\n    app.route([\n        ...mapRoutes(new UtilRoutes(), UtilRoutes.methods()),\n        ...mapRoutes(new HeroRoutes(mongoDb), HeroRoutes.methods()),\n        ...mapRoutes(new AuthRoutes(MINHA_CHAVE_SECRETA, postgresModel), AuthRoutes.methods())\n    ])\n\n    await app.start()\n    console.log('server running at', app.info.port)\n\n    return app;\n}\nmodule.exports = main()"
  },
  {
    "path": "module-11 - istanbul/mongodb-example.js",
    "content": "// npm i mongoose\nconst Mongoose = require('mongoose')\nMongoose.connect('mongodb://erickwendel:minhaoutrasenhasecreta@localhost:27017/herois', {\n  useNewUrlParser: true\n}, (error) => {\n  if (!error) return;\n  console.error('error to connect on mongodb', error)\n})\n\nconst connection = Mongoose.connection\nconnection.once('open', () => console.log('db is running!'))\n\nconst heroiSchema = new Mongoose.Schema({\n  nome: {\n    type: String,\n    required: true\n  },\n  poder: {\n    type: String,\n    required: true\n  },\n  nascimento: {\n    type: Date,\n    required: true\n  },\n})\nconst model = Mongoose.model('herois', heroiSchema)\nasync function main() {\n  const result = await model.create({\n    nome: 'Batman',\n    poder: 'Dinheiro',\n    nascimento: new Date(1970, 01, 01)\n  })\n  console.log('result', result)\n\n  const items = await model.find()\n  console.log('items', items)\n\n}\nmain()"
  },
  {
    "path": "module-11 - istanbul/package.json",
    "content": "{\n  \"name\": \"modulo05-multidatabase\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"preinstall\": \"npm i -g pm2\",\n    \"postinstall\": \"cross-env NODE_ENV=prod npm test\",\n    \"prod\": \"cross-env NODE_ENV=prod pm2-runtime api.js\",\n    \"start\": \"nodemon api.js\",\n    \"test\": \"nyc --reporter=html mocha --timeout 10000 tests/*.test.js --exit\"\n  },\n  \"author\": \"erickwendel\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"mocha\": \"^5.2.0\",\n    \"nyc\": \"^13.1.0\"\n  },\n  \"dependencies\": {\n    \"bcrypt\": \"^3.0.2\",\n    \"boom\": \"^7.2.2\",\n    \"cross-env\": \"^5.2.0\",\n    \"dotenv\": \"^6.2.0\",\n    \"hapi\": \"^17.7.0\",\n    \"hapi-auth-jwt2\": \"^8.1.0\",\n    \"hapi-swagger\": \"^9.1.3\",\n    \"inert\": \"^5.1.2\",\n    \"joi\": \"^14.1.0\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mongoose\": \"^5.3.11\",\n    \"pg\": \"^7.4.3\",\n    \"pg-hstore\": \"^2.3.2\",\n    \"sequelize\": \"^4.38.0\",\n    \"vision\": \"^5.4.3\"\n  }\n}"
  },
  {
    "path": "module-11 - istanbul/postgres-example.js",
    "content": "// npm i pg\n// npm install --save sequelize pg-hstore pg\n\n// const { Client } = require('pg');\n// const client = new Client({\n//   database: 'degfe1gjfh80m8',\n//   host: 'ec2-54-163-246-5.compute-1.amazonaws.com',\n//   port: 5432,\n//   password: 'fea27e438e77e507f6a31e6d8bcc4d8642c88c78b2c7dcc0ec6351d513f43ca8',\n//   user: 'vwgytcowhvcjug',\n//   ssl: true,\n// });\n// (async () => {\n//   const r = await client.connect();\n//   console.log('conectado!');\n//   const res = await client.query('SELECT * FROM TB_HEROIS');\n\n//   console.log(res.rows); // Hello world!\n//   await client.end();\n// })();\n\nconst Sequelize = require('sequelize');\nconst sequelize = new Sequelize(\n  'herois', //database\n  'erickwendel', // user\n  'minhasenhasecreta', //senha\n  {\n    host: 'localhost',\n    dialect: 'postgres',\n    // case sensitive\n    quoteIdentifiers: false,\n    // deprecation warning\n    operatorsAliases: false\n\n    // dialectOptions: {\n    //   ssl: true,\n    // },\n  },\n);\n\n(async () => {\n  const Herois = sequelize.define(\n    'herois',\n    {\n      id: {\n        type: Sequelize.INTEGER,\n        required: true,\n        primaryKey: true,\n        autoIncrement: true,\n      },\n      nome: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n      poder: {\n        type: Sequelize.STRING,\n        required: true,\n      },\n    },\n    {\n      //opcoes para base existente\n      tableName: 'TB_HEROIS',\n      freezeTableName: false,\n      timestamps: false,\n\n\n    },\n  );\n\n  // force: true will drop the table if it already exists\n  await Herois.sync();\n  // Table created\n  const result = await Herois.create({\n    nome: 'John',\n    poder: 'Hancock',\n  });\n  console.log(\n    'result',\n    await Herois.findAll({ raw: true, attributes: ['nome', 'poder', 'id'] }),\n  );\n})();\n"
  },
  {
    "path": "module-11 - istanbul/scripts/mongodb.sh",
    "content": "use herois\n\n\n// create\ndb.herois.create({ nome: 'Iron man', poder: 'Rico'})\n\n// read\ndb.herois.find({})\n\n// update\ndb.herois.update({_id: id}, {$set: {nome: 'papaleguas'}})\n\n// delete\ndb.herois.delete({_id: id})\n\n"
  },
  {
    "path": "module-11 - istanbul/scripts/postgres.sql",
    "content": "DROP TABLE IF EXISTS TB_USUARIOS;\nCREATE TABLE TB_USUARIOS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     USERNAME  TEXT    NOT NULL UNIQUE,\n     PASSWORD TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_USUARIOS\n    (USERNAME, PASSWORD)\nVALUES\n    ('xuxadasilva', '$2b$10$8I99eSf.DcubdihXUXO6weT9iriDG0UIm13d5Ji1TCB1kq88LwZdy');\n\n---\nDROP TABLE IF EXISTS TB_HEROIS;\nCREATE TABLE TB_HEROIS (\n     ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY    NOT NULL,\n     NOME  TEXT    NOT NULL,\n     PODER TEXT    NOT NULL\n);\n-- create\nINSERT INTO TB_HEROIS\n    (NOME, PODER)\nVALUES\n    ('Flash', 'Velocidade'),\n    ('Batman', 'Dinheiro'),\n    ('Aquaman', 'Marinho');\n-- read\nSELECT *\nFROM TB_HEROIS;\n-- update\nUPDATE TB_HEROIS \nSET NOME = 'Goku', PODER= 'Deus'\nWHERE ID = 1;\n--delete\nDELETE FROM TB_HEROIS WHERE ID = 2;"
  },
  {
    "path": "module-11 - istanbul/server.js",
    "content": "const http = require('http')\n\nhttp.createServer((req, res) => {\n    res.end('Hello node!')\n}).listen(4000, () => {\n    console.log('server rodando!!')\n})"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/base/contextStrategy.js",
    "content": "const IDb = require('./interfaceDb');\nclass ContextStrategy extends IDb {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  isConnected() {\n    return this._database.isConnected();\n  }\n  connect() {\n    return this._database.connect()\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item, upsert) {\n    return this._database.update(id, item, upsert);\n  }\n  delete(id) {\n    return this._database.delete(id);\n  }\n}\n\nmodule.exports = ContextStrategy;"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/base/interfaceDb.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass IDb {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n  isConnected(id) {\n    throw new NotImplementedException();\n  }\n}\n\nmodule.exports = IDb;\n"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/mongodb/mongoDbStrategy.js",
    "content": "const ICrud = require('../base/interfaceDb')\nconst Mongoose = require('mongoose')\nconst STATUS = {\n    0: 'Disconectado',\n    1: 'Conectado',\n    2: 'Conectando',\n    3: 'Disconectando',\n}\nclass MongoDB extends ICrud {\n    // 3o\n    constructor(connection, schema) {\n        super()\n        // 4o\n        this._connection = connection;\n        this._collection = schema;\n    }\n    // 2o\n    async isConnected() {\n        const state = STATUS[this._connection.readyState]\n        if (state === 'Conectado') return state;\n\n        if (state !== 'Conectando') return state\n\n        await new Promise(resolve => setTimeout(resolve, 1000))\n\n        return STATUS[this._connection.readyState]\n\n    }\n    // 1o \n    static connect() {\n        Mongoose.connect(process.env.MONGO_URL, {\n            useNewUrlParser: true\n        }, function (error) {\n            if (!error) return;\n            console.log('Falha na conexão!', error)\n        })\n        const connection = Mongoose.connection\n        connection.once('open', () => console.log('database rodando!!'))\n        return connection;\n    }\n\n    async create(item) {\n        return this._collection.create(item)\n    }\n    async read(item = {}) {\n        return this._collection.find(item, {\n            nome: 1,\n            poder: 1,\n            insertedAt: 1\n        })\n    }\n    async update(id, item) {\n        return this._collection.updateOne({\n            _id: id\n        }, {\n            $set: item\n        })\n    }\n\n    async delete(id) {\n        return this._collection.deleteOne({\n            _id: id\n        })\n    }\n}\n\nmodule.exports = MongoDB"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/mongodb/schemas/heroSchema.js",
    "content": "const Mongoose=  require('mongoose')\nconst heroiSchema = new Mongoose.Schema({\n    nome: {\n        type: String,\n        required: true\n    },\n    poder: {\n        type: String,\n        required: true\n    },\n    insertedAt: {\n        type: Date,\n        default: new Date()\n    }\n})\n\n//mocha workaround\nmodule.exports = Mongoose.models.herois || Mongoose.model('herois', heroiSchema)"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/postgres/postgresSQLStrategy.js",
    "content": "const IDb = require('../base/interfaceDb');\nconst Sequelize = require('sequelize');\n\nclass PostgreSQLStrategy extends IDb {\n  constructor(connection, schema) {\n    super();\n    this._db = schema;\n    this._connection = connection;\n\n  }\n\n  static async defineModel(connection, schema) {\n    const model = connection.define(\n      schema.name, schema.schema, schema.options,\n    );\n    await model.sync()\n    return model\n  }\n\n  static async connect() {\n    const sequelize = new Sequelize(process.env.POSTGRES_URL, {\n      quoteIdentifiers: false,\n      ssl: process.env.SSL_DB,\n      dialectOptions: {\n        ssl: process.env.SSL_DB,\n\n      },\n      // deprecation warning\n      operatorsAliases: false,\n      //disable logging\n      logging: false\n\n    })\n\n    return sequelize\n  }\n\n  async isConnected() {\n    try {\n      // await this._connect();\n      await this._connection.authenticate();\n      return true;\n    } catch (error) {\n      console.error('fail!', error);\n      return false;\n    }\n  }\n\n  create(item) {\n    return this._db.create(item, {\n      raw: true\n    });\n  }\n\n  read(item) {\n    return this._db.findAll({\n      where: item,\n      raw: true\n    });\n  }\n\n  update(id, item, upsert = false) {\n    const fn = upsert ? 'upsert' : 'update'\n    return this._db[fn](item, {\n      where: {\n        id\n      }\n    });\n  }\n  delete(id) {\n    const query = id ? {\n      id\n    } : {};\n    return this._db.destroy({\n      where: query\n    });\n  }\n}\n\nmodule.exports = PostgreSQLStrategy;"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/postgres/schemas/heroiSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst HeroiSchema = {\n  name: 'herois',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    nome: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n    poder: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_HEROIS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = HeroiSchema"
  },
  {
    "path": "module-11 - istanbul/src/db/strategies/postgres/schemas/userSchema.js",
    "content": "const Sequelize = require('sequelize')\nconst UserSchema = {\n  name: 'users',\n  schema: {\n    id: {\n      type: Sequelize.INTEGER,\n      required: true,\n      primaryKey: true,\n      autoIncrement: true,\n    },\n    username: {\n      type: Sequelize.STRING,\n      unique: true,\n      required: true,\n    },\n    password: {\n      type: Sequelize.STRING,\n      required: true,\n    },\n  },\n  options: {\n    //opcoes para base existente\n    tableName: 'TB_USUARIOS',\n    freezeTableName: false,\n    timestamps: false,\n\n  }\n}\n\nmodule.exports = UserSchema"
  },
  {
    "path": "module-11 - istanbul/src/example1.js",
    "content": "class NotImplementedException extends Error {\n  constructor() {\n    super('Not Implemented Exception');\n  }\n}\n//interface\nclass ICrud {\n  create(item) {\n    throw new NotImplementedException();\n  }\n  read(item) {\n    throw new NotImplementedException();\n  }\n  update(id, item) {\n    throw new NotImplementedException();\n  }\n  delete(id) {\n    throw new NotImplementedException();\n  }\n}\n\nclass MongoDBStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('MongoDBStrategy');\n  }\n}\nclass PostgreSQLStrategy extends ICrud {\n  constructor() {\n    super();\n  }\n  create(item) {\n    console.log('PostgreSQLStrategy');\n  }\n}\n\nclass ContextoStrategy extends ICrud {\n  constructor(database) {\n    super();\n    this._database = database;\n  }\n  create(item) {\n    return this._database.create(item);\n  }\n  read(item) {\n    return this._database.read(item);\n  }\n  update(id, item) {\n    return this._database.update(id, item);\n  }\n  delete(id) {\n    return this._database.delete(id, item);\n  }\n}\n\nconst contextMongo = new ContextoStrategy(new MongoDBStrategy());\ncontextMongo.create();\nconst context = new ContextoStrategy(new PostgreSQLStrategy());\ncontext.create();\n\ncontext.read();\n"
  },
  {
    "path": "module-11 - istanbul/src/helpers/passwordHelper.js",
    "content": "const Bcrypt = require('bcrypt')\nconst {\n    promisify\n} = require('util')\nconst hashAsync = promisify(Bcrypt.hash)\nconst compareAsync = promisify(Bcrypt.compare)\nconst SALT = parseInt(process.env.PWD_SALT)\n\nclass Password {\n\n    static hashPassword(pass) {\n        return hashAsync(pass, SALT)\n    }\n    static comparePassword(pass, hash) {\n        return compareAsync(pass, hash)\n    }\n}\nmodule.exports = Password"
  },
  {
    "path": "module-11 - istanbul/src/routes/authRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\nconst Boom = require('boom')\nconst PasswordHelper = require('./../helpers/passwordHelper')\nconst USER = {\n    username: 'xuxadasilva',\n    password: '123'\n}\nconst Jwt = require('jsonwebtoken')\n\nclass AuthRoutes extends BaseRoute {\n    constructor(key, db) {\n        super()\n        this.secret = key\n        this.db = db\n    }\n\n    login() {\n\n        return {\n            path: '/login',\n            method: 'POST',\n            config: {\n                auth: false,\n                tags: ['api'],\n                description: 'fazer login',\n                notes: 'retorna o token',\n                validate: {\n                    payload: {\n                        username: Joi.string().required(),\n                        password: Joi.string().required()\n                    }\n                }\n            },\n            handler: async (request, headers) => {\n                const {\n                    username,\n                    password\n                } = request.payload\n\n                const [user] = await this.db.read({\n                    username: username.toLowerCase()\n                })\n\n                if (!user) {\n                    return Boom.unauthorized('O usuario informado nao existe')\n                }\n\n                const match = await PasswordHelper.comparePassword(password, user.password)\n\n                if (!match) {\n                    return Boom.unauthorized('O usuario e senha invalidos!')\n                }\n\n                // if (\n                //     username.toLowerCase() !== USER.username ||\n                //     password !== USER.password\n                // )\n                //     return Boom.unauthorized()\n\n                return {\n                    token: Jwt.sign({\n                        username: username\n                    }, this.secret)\n                }\n            }\n        }\n    }\n}\nmodule.exports = AuthRoutes"
  },
  {
    "path": "module-11 - istanbul/src/routes/base/baseRoute.js",
    "content": "class BaseRoute {\n    static methods() {\n        return Object.getOwnPropertyNames(this.prototype)\n            .filter(method => method !== 'constructor' && !method.startsWith('_'))\n    }\n}\n\nmodule.exports = BaseRoute"
  },
  {
    "path": "module-11 - istanbul/src/routes/heroRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst Joi = require('joi')\n\nclass HeroRoutes extends BaseRoute {\n    constructor(db) {\n        super()\n        this.db = db\n    }\n\n    list() {\n        return {\n            path: '/herois',\n            method: 'GET',\n            config: {\n                tags: ['api'],\n                description: 'listar herois',\n                notes: 'retorna a base inteira de herois',\n                validate: {\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown()\n                }\n            },\n            handler: (request, headers) => {\n                return this.db.read()\n            }\n        }\n    }\n    create() {\n        return {\n            path: '/herois',\n            method: 'POST',\n            config: {\n                tags: ['api'],\n                description: 'cadastrar herois',\n                notes: 'Cadastra um heroi por nome e poder',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    payload: {\n                        nome: Joi.string().max(100).required(),\n                        poder: Joi.string().max(30).required()\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload\n                return this.db.create(payload)\n            }\n        }\n    }\n    update() {\n        return {\n            path: '/herois/{id}',\n            method: 'PATCH',\n            config: {\n                tags: ['api'],\n                description: 'atualizar herois',\n                notes: 'atualiza um heroi por ID',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    },\n                    payload: {\n                        nome: Joi.string().max(100),\n                        poder: Joi.string().max(30)\n                    }\n                },\n\n            },\n            handler: (request, headers) => {\n                const payload = request.payload;\n                const id = request.params.id;\n                return this.db.update(id, payload)\n            }\n        }\n    }\n    delete() {\n        return {\n            path: '/herois/{id}',\n            method: 'DELETE',\n            config: {\n                tags: ['api'],\n                description: 'remover herois',\n                notes: 'remove um heroi por id',\n                validate: {\n                    failAction: (request, h, err) => {\n                        throw err;\n                    },\n                    headers: Joi.object({\n                        authorization: Joi.string().required()\n                    }).unknown(),\n                    params: {\n                        id: Joi.string().required()\n                    }\n                }\n            },\n            handler: (request, headers) => {\n                const id = request.params.id;\n                return this.db.delete(id)\n            }\n        }\n    }\n\n}\n\nmodule.exports = HeroRoutes"
  },
  {
    "path": "module-11 - istanbul/src/routes/utilRoutes.js",
    "content": "const BaseRoute = require('./base/baseRoute')\nconst {\n    join\n} = require('path')\n/*\n    1o add nyc\n    2o npm t\n    3o create utilRoutes\n    4o register on api\n    5o run on navigator\n    6o add .gitignore\n    7o add --exit to npm t\n    8o add postinstall\n*/\nclass UtilRoutes extends BaseRoute {\n    coverage() {\n        return {\n            path: '/coverage/{param*}',\n            method: 'GET',\n            config: {\n                auth: false,\n            },\n            handler: {\n                directory: {\n                    path: join(__dirname, '../../coverage'),\n                    redirectToSlash: true,\n                    index: true,\n                },\n            },\n        }\n    }\n}\n\nmodule.exports = UtilRoutes"
  },
  {
    "path": "module-11 - istanbul/tests/apiHeroes.test.js",
    "content": "const assert = require('assert')\nconst api = require('./../api')\nlet app = {}\nlet MOCK_ID = \"\"\nlet MOCK_TOKEN = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Inh1eGFkYXNpbHZhIiwiaWF0IjoxNTQyNzI4MzQ0fQ.JvBOZa7yXds4ktQ7HvNRYO6-s1mbU7AKTJP9G2ghje4\"\nconst headers = {\n    Authorization: MOCK_TOKEN\n}\n\nfunction cadastrar() {\n    return app.inject({\n        method: 'POST',\n        url: '/herois',\n        headers,\n        payload: {\n            nome: 'Flash',\n            poder: 'Velocidade'\n        }\n    });\n}\n\n\ndescribe('API Heroes test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n        const result = await cadastrar()\n        MOCK_ID = JSON.parse(result.payload)._id\n    })\n    it('não deve listar herois sem um token', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n    it('listar /heroes', async () => {\n        const result = await app.inject({\n            method: 'GET',\n            url: '/herois',\n            headers\n        })\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(Array.isArray(JSON.parse(result.payload)))\n    })\n\n    it('cadastrar /herois', async () => {\n        const result = await cadastrar()\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nome, \"Flash\")\n\n    })\n\n    it('não deve cadastrar com payload errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/herois',\n            headers,\n            payload: {\n                NAME: 'Flash'\n            }\n        })\n        const payload = JSON.parse(result.payload)\n        assert.deepEqual(result.statusCode, 400)\n        assert.ok(payload.message.search('\"nome\" is required') !== -1)\n    })\n    it('atualizar /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'PATCH',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n            payload: {\n                nome: 'Canário Negro',\n                poder: 'Grito'\n            }\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).nModified, 1)\n\n    })\n    it('remover /herois/{id}', async () => {\n        const result = await app.inject({\n            method: 'DELETE',\n            url: `/herois/${MOCK_ID}`,\n            headers,\n        })\n        assert.deepEqual(result.statusCode, 200)\n        assert.deepEqual(JSON.parse(result.payload).n, 1)\n    })\n})"
  },
  {
    "path": "module-11 - istanbul/tests/auth.test.js",
    "content": "//1o criar test \n//2o criar passwordHelper\n//3o gerar senha e guardar\n//4o criar model de usuario\n//5o adicionar chamada em api.js\n//6o adicionar no construtor de auth receber o model\n//7o criar logica na route\n//8o adicionar upsert no context e postgresStrategy\n//9o adicionar no arquivo postgres.sql o script para criar a tabela\n\nconst assert = require('assert')\nconst api = require('../api')\nconst Context = require('./../src/db/strategies/base/contextStrategy')\nconst PostgresDB = require('./../src/db/strategies/postgres/postgresSQLStrategy')\nconst UserSchema = require('./../src/db/strategies/postgres/schemas/userSchema')\n\nlet app = {}\nconst USER = {\n    username: 'xuxadasilva',\n    password: '321123'\n}\n\nconst USER_DB = {\n    ...USER,\n    password: '$2b$04$SdlyEJsy.o5UgsgVr5csJ.ralZVyPviGH80BOb0zJCTSis30RB8Ba'\n}\n\n\ndescribe('Auth test suite', function () {\n    this.beforeAll(async () => {\n        app = await api\n\n        const connectionPostgres = await PostgresDB.connect()\n        const model = await PostgresDB.defineModel(connectionPostgres, UserSchema)\n        const postgresModel = new Context(new PostgresDB(connectionPostgres, model));\n        await postgresModel.update(null, USER_DB, true)\n    })\n    it('deve obter um token', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: USER\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 200)\n        assert.ok(JSON.parse(result.payload).token.length > 10)\n    })\n\n    it('deve retornar não autorizado ao tentar obter um token com login errado', async () => {\n        const result = await app.inject({\n            method: 'POST',\n            url: '/login',\n            payload: {\n                username: 'erickwendel',\n                password: '123'\n            }\n        });\n        const statusCode = result.statusCode\n\n        assert.deepEqual(statusCode, 401)\n        assert.deepEqual(JSON.parse(result.payload).error, \"Unauthorized\")\n    })\n})"
  },
  {
    "path": "module-11 - istanbul/tests/mongodbStrategy.test.js",
    "content": "const assert = require('assert')\nconst MongoDb = require('../src/db/strategies/mongodb/mongoDbStrategy')\nconst HeroSchema = require('../src/db/strategies/mongodb/schemas/heroSchema')\nconst Context = require('../src/db/strategies/base/contextStrategy')\n\n// 1o alterar criar pasta mongodb\n// 2o mover mongodbStrategy para mongodb\n// 3o modificar classe do mongodbStrategy\n// 4o modificar criar schema em mongodb/schemas\n// 6o modificar teste fazendo conexão direto do MongoDB\n// 5o modificar teste passando para o MongoDB\n\nconst MOCK_HEROI_CADASTRAR = {\n    nome: 'Gaviao Negro',\n    poder: 'flexas'\n};\n\nconst MOCK_HEROI_ATUALIZAR = {\n    nome: 'Mulher Maravilha',\n    poder: 'força'\n};\nlet MOCK_HEROI_ATUALIZAR_ID = '';\nlet context = {}\n\ndescribe('MongoDB Suite de testes', function () {\n    this.beforeAll(async () => {\n        const connection = MongoDb.connect()\n        context = new Context(new MongoDb(connection, HeroSchema))\n\n        const result = await context.create(MOCK_HEROI_ATUALIZAR)\n        MOCK_HEROI_ATUALIZAR_ID = result._id\n    })\n    it('verificar conexao', async () => {\n        const result = await context.isConnected()\n        const expected = 'Conectado'\n\n        assert.deepEqual(result, expected)\n    })\n    it('cadastrar', async () => {\n        const {\n            nome,\n            poder\n        } = await context.create(MOCK_HEROI_CADASTRAR)\n\n        assert.deepEqual({\n            nome,\n            poder\n        }, MOCK_HEROI_CADASTRAR)\n    })\n\n    it('listar', async () => {\n        const [{\n            nome,\n            poder\n        }] = await context.read({\n            nome: MOCK_HEROI_CADASTRAR.nome\n        })\n        const result = {\n            nome,\n            poder\n        }\n        assert.deepEqual(result, MOCK_HEROI_CADASTRAR)\n    })\n    it('atualizar', async () => {\n        const result = await context.update(MOCK_HEROI_ATUALIZAR_ID, {\n            poder: 'Laço'\n        })\n        assert.deepEqual(result.nModified, 1)\n    })\n    it('remover', async () => {\n        const result = await context.delete(MOCK_HEROI_ATUALIZAR_ID)\n        assert.deepEqual(result.n, 1)\n    })\n})"
  },
  {
    "path": "module-11 - istanbul/tests/passwordHelper.test.js",
    "content": "const assert = require('assert');\nconst PasswordHelper = require('../src/helpers/passwordHelper');\n\nconst SENHA = 'erick@32123';\nconst HASH = '$2b$04$nJuOS9YZH9FpsKTOSh2IPOZUW9IF83bo54FE2L/rO/Xzrl.pS/qV2'\n\n\n\ndescribe('UserHelper test suite', function () {\n    it('deve gerar um hash a partir de uma senha', async () => {\n        const result = await PasswordHelper.hashPassword(SENHA);\n\n        // const result = await PasswordHelper.hashPassword('321123');\n        // console.log('result', result)\n        assert.ok(result.length > 10);\n    });\n    it('deve comparar uma senha e seu hash', async () => {\n        const result = PasswordHelper.comparePassword(SENHA, HASH)\n        assert.ok(result)\n    })\n\n});"
  },
  {
    "path": "module-11 - istanbul/tests/postgresStrategy.test.js",
    "content": "const {\n  equal,\n  deepEqual,\n  ok\n} = require('assert');\nconst PostgresStrategy = require('../src/db/strategies/postgres/postgresSQLStrategy');\nconst HeroiSchema = require('../src/db/strategies/postgres/schemas/heroiSchema');\nconst Context = require('../src/db/strategies/base/contextStrategy');\nconst MOCK_HEROI_CADASTRAR = {\n  nome: 'Gaviao Negro',\n  poder: 'flexas'\n};\nconst MOCK_HEROI_ATUALIZAR = {\n  nome: 'Mulher Gavião',\n  poder: 'grito'\n};\n\nlet context = {}\n\ndescribe('PostgreSQL Strategy', function () {\n  this.timeout(Infinity);\n  before(async () => {\n    const connection = await PostgresStrategy.connect()\n    const model = await PostgresStrategy.defineModel(connection, HeroiSchema)\n    context = new Context(new PostgresStrategy(connection, model));\n\n    await context.delete();\n    await context.create(MOCK_HEROI_CADASTRAR);\n    await context.create(MOCK_HEROI_ATUALIZAR);\n  });\n\n  it('PostgresSQL connection', async () => {\n    const result = await context.isConnected();\n    equal(result, true);\n  });\n\n  it('cadastrar', async () => {\n    const result = await context.create(MOCK_HEROI_CADASTRAR);\n    delete result.dataValues.id;\n    deepEqual(result.dataValues, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('listar', async () => {\n    const [result] = await context.read(MOCK_HEROI_CADASTRAR);\n    delete result.id;\n    deepEqual(result, MOCK_HEROI_CADASTRAR);\n  });\n\n  it('atualizar', async () => {\n    const [result] = await context.read({});\n\n    const novoItem = {\n      ...MOCK_HEROI_CADASTRAR,\n      nome: 'Mulher Maravilha',\n    };\n    const [update] = await context.update(result.id, novoItem);\n\n    deepEqual(update, 1);\n  });\n\n  it('remover', async () => {\n    const [item] = await context.read({});\n    const result = await context.delete(item.id);\n    deepEqual(result, 1);\n  });\n});"
  }
]