├── .gitignore ├── LICENSE ├── README.md ├── api ├── .vscode │ └── settings.json ├── app │ ├── api │ │ ├── acoes.js │ │ ├── index.js │ │ ├── portfolio.js │ │ └── user.js │ ├── infra │ │ ├── acoes-dao.js │ │ ├── async-wrap.js │ │ ├── auth.js │ │ ├── index.js │ │ ├── portfolio-dao.js │ │ └── user-dao.js │ └── routes │ │ ├── acoes.js │ │ ├── index.js │ │ ├── portfolio.js │ │ └── user.js ├── config │ ├── database.js │ └── express.js ├── data.db ├── package-lock.json ├── package.json └── server.js └── byte-bank-broker ├── .angulardoc.json ├── .browserslistrc ├── .editorconfig ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── angular.json ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── src ├── app │ ├── acoes │ │ ├── acoes-routing.module.ts │ │ ├── acoes.component.css │ │ ├── acoes.component.html │ │ ├── acoes.component.spec.ts │ │ ├── acoes.component.ts │ │ ├── acoes.module.ts │ │ └── card-acoes │ │ │ ├── card-acoes.component.css │ │ │ ├── card-acoes.component.html │ │ │ ├── card-acoes.component.spec.ts │ │ │ └── card-acoes.component.ts │ ├── app-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── authorization │ │ ├── authorization.guard.spec.ts │ │ ├── authorization.guard.ts │ │ ├── authorization.interceptor.spec.ts │ │ ├── authorization.interceptor.ts │ │ ├── authorization.module.ts │ │ ├── authorization.service.spec.ts │ │ ├── authorization.service.ts │ │ └── model │ │ │ ├── user-login.ts │ │ │ └── user.ts │ ├── core │ │ └── core.module.ts │ ├── home │ │ ├── home-routing.module.ts │ │ ├── home.component.css │ │ ├── home.component.html │ │ ├── home.component.spec.ts │ │ ├── home.component.ts │ │ └── home.module.ts │ ├── login │ │ ├── login-routing.module.ts │ │ ├── login.component.css │ │ ├── login.component.html │ │ ├── login.component.spec.ts │ │ ├── login.component.ts │ │ └── login.module.ts │ ├── messages │ │ ├── messages.module.ts │ │ ├── messages.service.spec.ts │ │ └── messages.service.ts │ ├── no-data │ │ ├── no-data.component.css │ │ ├── no-data.component.html │ │ ├── no-data.component.spec.ts │ │ ├── no-data.component.ts │ │ └── no-data.module.ts │ ├── portfolio │ │ ├── model │ │ │ └── portfolio.ts │ │ ├── portfolio-form │ │ │ ├── portfolio-form.component.css │ │ │ ├── portfolio-form.component.html │ │ │ ├── portfolio-form.component.spec.ts │ │ │ └── portfolio-form.component.ts │ │ ├── portfolio-list │ │ │ ├── portfolio-list.component.css │ │ │ ├── portfolio-list.component.html │ │ │ ├── portfolio-list.component.spec.ts │ │ │ └── portfolio-list.component.ts │ │ ├── portfolio-routing.module.ts │ │ ├── portfolio.module.ts │ │ ├── portfolio.service.spec.ts │ │ └── portfolio.service.ts │ └── shared │ │ └── shared.module.ts ├── assets │ ├── .gitkeep │ └── bytebank.png ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css └── test.ts ├── tsconfig.app.json ├── tsconfig.base.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alvaro Camillo Neto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # alura_angular_rxjs_1 2 | Curso 3 | -------------------------------------------------------------------------------- /api/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#fbed80", 4 | "activityBar.activeBorder": "#06b9a5", 5 | "activityBar.background": "#fbed80", 6 | "activityBar.foreground": "#15202b", 7 | "activityBar.inactiveForeground": "#15202b99", 8 | "activityBarBadge.background": "#06b9a5", 9 | "activityBarBadge.foreground": "#15202b", 10 | "statusBar.background": "#f9e64f", 11 | "statusBar.border": "#f9e64f", 12 | "statusBar.foreground": "#15202b", 13 | "statusBarItem.hoverBackground": "#f7df1e", 14 | "titleBar.activeBackground": "#f9e64f", 15 | "titleBar.activeForeground": "#15202b", 16 | "titleBar.border": "#f9e64f", 17 | "titleBar.inactiveBackground": "#f9e64f99", 18 | "titleBar.inactiveForeground": "#15202b99" 19 | }, 20 | "peacock.color": "#f9e64f" 21 | } -------------------------------------------------------------------------------- /api/app/api/acoes.js: -------------------------------------------------------------------------------- 1 | const { AcoesDao } = require("../infra"); 2 | 3 | const api = {}; 4 | 5 | api.add = async (req, res) => { 6 | const { codigo, descricao, preco } = req.body; 7 | console.log(req.body); 8 | const AcoesDao = new AcoesDao(req.db); 9 | 10 | const acoesid = await AcoesDao.add(codigo, descricao, preco); 11 | const acoes = await AcoesDao.findById(acoesid); 12 | console.log(`Ação adicionada`, acoes); 13 | res.json(acoes); 14 | }; 15 | 16 | api.list = async (req, res) => { 17 | let { valor } = req.query; 18 | valor = valor || ""; 19 | console.log(`Busca ação por ${valor}`); 20 | const acoes = await new AcoesDao(req.db).listAll(valor); 21 | const result = { payload: acoes }; 22 | res.json(result); 23 | }; 24 | 25 | api.findById = async (req, res) => { 26 | const { acoesID } = req.params; 27 | console.log("####################################"); 28 | console.log(`Buscando acoes pelo ID ${acoesID}`); 29 | const acoes = await new AcoesDao(req.db).findById(acoesID); 30 | if (acoes) { 31 | res.json(acoes); 32 | } else { 33 | res.status(404).json({ message: "acoes does not exist" }); 34 | } 35 | }; 36 | 37 | module.exports = api; 38 | -------------------------------------------------------------------------------- /api/app/api/index.js: -------------------------------------------------------------------------------- 1 | const acoesAPI = require("./acoes"); 2 | const userAPI = require("./user"); 3 | const portfolioAPI = require("./portfolio"); 4 | 5 | module.exports = { acoesAPI, userAPI, portfolioAPI }; 6 | -------------------------------------------------------------------------------- /api/app/api/portfolio.js: -------------------------------------------------------------------------------- 1 | const { PortfolioDao, UserDao } = require("../infra"); 2 | 3 | const api = {}; 4 | 5 | const userCanDelete = (user) => (portfolio) => portfolio.user_id == user.id; 6 | 7 | api.add = async (req, res) => { 8 | console.log("####################################"); 9 | console.log("Received JSON data", req.body); 10 | const portfolio = req.body; 11 | const id = await new PortfolioDao(req.db).add(portfolio, req.user.id); 12 | res.json(id); 13 | }; 14 | 15 | api.list = async (req, res) => { 16 | console.log("####################################"); 17 | console.log(`Listing portfolios`); 18 | const portfolios = await new PortfolioDao(req.db).listAllFromUser( 19 | req.user.id 20 | ); 21 | const result = { 22 | items: [...portfolios], 23 | hasNext: false, 24 | }; 25 | res.json(result); 26 | }; 27 | 28 | api.findById = async (req, res) => { 29 | const { portfolioId } = req.params; 30 | console.log("####################################"); 31 | console.log(`Finding PortFolio for ID ${portfolioId}`); 32 | const portfolio = await new PortfolioDao(req.db).findById( 33 | req.user.id, 34 | portfolioId 35 | ); 36 | if (portfolio) { 37 | res.json(portfolio); 38 | } else { 39 | res.status(404).json({ message: "Portfolio does not exist" }); 40 | } 41 | }; 42 | 43 | api.put = async (req, res) => { 44 | console.log("####################################"); 45 | console.log("Received JSON data", req.body); 46 | const { portfolioId } = req.params; 47 | const portfolio = req.body; 48 | const id = await new PortfolioDao(req.db).add( 49 | portfolio, 50 | req.user.id, 51 | portfolioId 52 | ); 53 | 54 | const portfolioRet = await new PortfolioDao(req.db).findById(req.user.id, id); 55 | if (portfolioRet) { 56 | res.json(portfolioRet); 57 | } else { 58 | res.status(404).json({ message: "Portfolio does not exist" }); 59 | } 60 | }; 61 | 62 | api.remove = async (req, res) => { 63 | const user = req.user; 64 | const { portfolioId } = req.params; 65 | console.log("####################################"); 66 | console.log(`Remove PortFolio for ID ${portfolioId} of user ${user.id}`); 67 | const dao = new PortfolioDao(req.db); 68 | const portfolio = await dao.findById(user.id, portfolioId); 69 | if (!portfolio) { 70 | const message = "PortfolioId does not exist"; 71 | console.log(message); 72 | return res.status(404).json({ message }); 73 | } 74 | 75 | if (userCanDelete(user)(portfolio)) { 76 | await dao.remove(portfolioId); 77 | console.log(`Portfolio ${portfolioId} deleted!`); 78 | res.status(200).end(); 79 | } else { 80 | console.log(` 81 | Forbiden operation. User ${user.id} 82 | can delete portfolio from user ${portfolio.user_id} 83 | `); 84 | res.status(403).json({ message: "Forbidden" }); 85 | } 86 | }; 87 | 88 | module.exports = api; 89 | -------------------------------------------------------------------------------- /api/app/api/user.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const { UserDao } = require('../infra'); 3 | 4 | const api = {} 5 | 6 | api.login = async (req, res) => { 7 | const { userName, password } = req.body; 8 | console.log('####################################'); 9 | 10 | const user = await new UserDao(req.db).findByNameAndPassword(userName, password); 11 | console.log(user); 12 | if(user) { 13 | console.log(`User ${userName} authenticated`); 14 | console.log('Authentication Token added to response'); 15 | const token = jwt.sign(user, req.app.get('secret'), { 16 | expiresIn: 86400 // seconds, 24h 17 | }); 18 | res.set('x-access-token', token); 19 | return res.json(user); 20 | } else { 21 | console.log(`Authentication failed for user ${userName}`); 22 | console.log('No token generated'); 23 | res.status(401).json({ message: `Authentication failed for user ${userName}`}); 24 | } 25 | }; 26 | 27 | api.register = async (req, res) => { 28 | const user = req.body; 29 | const userId = await new UserDao(req.db).add(user); 30 | res.status(204).end(); 31 | }; 32 | 33 | api.checkUserNameTaken = async (req, res) => { 34 | const { userName } = req.params; 35 | const user = await new UserDao(req.db).findByName(userName); 36 | res.json(!!user); 37 | }; 38 | 39 | module.exports = api; -------------------------------------------------------------------------------- /api/app/infra/acoes-dao.js: -------------------------------------------------------------------------------- 1 | const acoesConverter = (row) => ({ 2 | id: row.acoes_id, 3 | codigo: row.acoes_codigo, 4 | descricao: row.acoes_descricao, 5 | preco: parseFloat((Math.random() * (100 - 1) + 1).toFixed(2)), 6 | }); 7 | 8 | class AcoesDao { 9 | constructor(db) { 10 | this._db = db; 11 | } 12 | 13 | add(codigo, descricao, preco) { 14 | return new Promise((resolve, reject) => { 15 | this._db.run( 16 | ` 17 | INSERT INTO acoes ( 18 | acoes_codigo, 19 | acoes_descricao, 20 | acoes_preco 21 | ) values (?,?,?) 22 | `, 23 | [codigo, descricao, preco], 24 | function (err) { 25 | if (err) { 26 | console.log(err); 27 | return reject("Can`t add acoes"); 28 | } 29 | resolve(this.lastID); 30 | } 31 | ); 32 | }); 33 | } 34 | 35 | listAll(value) { 36 | return new Promise((resolve, reject) => { 37 | this._db.all( 38 | ` 39 | SELECT 40 | acoes_id,acoes_codigo,acoes_descricao,acoes_preco 41 | FROM acoes 42 | WHERE acoes_codigo LIKE $codigo 43 | UNION 44 | SELECT 45 | acoes_id,acoes_codigo,acoes_descricao,acoes_preco 46 | FROM acoes 47 | WHERE acoes_descricao LIKE $codigo 48 | `, 49 | { $codigo: `%${value}%` }, 50 | (err, rows) => { 51 | if (err) { 52 | console.log("++++ERRO+++"); 53 | console.log(err); 54 | return reject("Can`t load acoes"); 55 | } 56 | const acoes = rows.map(acoesConverter); 57 | return resolve(acoes); 58 | } 59 | ); 60 | }); 61 | } 62 | 63 | findById(id) { 64 | return new Promise((resolve, reject) => { 65 | this._db.get( 66 | ` 67 | SELECT 68 | acoes_id,acoes_codigo,acoes_descricao,acoes_preco 69 | FROM acoes 70 | WHERE acoes_id = ? 71 | `, 72 | [id], 73 | (err, row) => { 74 | console.log(row); 75 | if (err) { 76 | console.log(err); 77 | return reject("Can`t load acoes"); 78 | } 79 | return resolve(acoesConverter(row)); 80 | } 81 | ); 82 | }); 83 | } 84 | } 85 | 86 | module.exports = AcoesDao; 87 | -------------------------------------------------------------------------------- /api/app/infra/async-wrap.js: -------------------------------------------------------------------------------- 1 | module.exports = fn => 2 | (req, res, next) => 3 | fn(req, res, next).catch(next); 4 | -------------------------------------------------------------------------------- /api/app/infra/auth.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken') 2 | , { promisify } = require('util'); 3 | 4 | const verify = promisify(jwt.verify); 5 | 6 | module.exports = async (req, res, next) => { 7 | const token = req.headers['x-access-token']; 8 | if (token) { 9 | try { 10 | const decoded = await verify(token, req.app.get('secret')); 11 | console.log(`Valid token received: ${token}`); 12 | req.user = decoded; 13 | next(); 14 | } catch (err) { 15 | console.log(err); 16 | console.log(`Invalid token: ${token}`); 17 | return res.sendStatus(401); 18 | } 19 | } else { 20 | console.log('Toke is missing!'); 21 | return res.sendStatus(401); 22 | } 23 | } -------------------------------------------------------------------------------- /api/app/infra/index.js: -------------------------------------------------------------------------------- 1 | const AcoesDao = require("./acoes-dao"); 2 | const PortfolioDao = require("./portfolio-dao"); 3 | const UserDao = require("./user-dao"); 4 | const wrapAsync = require("./async-wrap"); 5 | const auth = require("./auth"); 6 | 7 | module.exports = { 8 | AcoesDao, 9 | UserDao, 10 | PortfolioDao, 11 | wrapAsync, 12 | auth, 13 | }; 14 | -------------------------------------------------------------------------------- /api/app/infra/portfolio-dao.js: -------------------------------------------------------------------------------- 1 | const portFolioHeader = (model, user_id) => { 2 | const { portfolio_id, portfolio_descricao } = model; 3 | return { 4 | portfolio_id, 5 | portfolio_descricao, 6 | user_id, 7 | }; 8 | }; 9 | 10 | class PortfolioDao { 11 | constructor(db) { 12 | this._db = db; 13 | } 14 | 15 | add(model, user_id, portfolio_id) { 16 | const header = portFolioHeader(model, user_id); 17 | const { items } = model; 18 | const id = portfolio_id || header.portfolio_id; 19 | if (id) { 20 | return this.updateModel(id, header, items); 21 | } else { 22 | return this.insertModel(header, items); 23 | } 24 | } 25 | 26 | remove(portfolio_id) { 27 | const deleteItems = this.deleteAllItems(portfolio_id); 28 | const deletePortFolio = this.deletePortfolio(portfolio_id); 29 | return Promise.all([deleteItems, deletePortFolio]); 30 | } 31 | 32 | updateModel(portfolio_id, header, items) { 33 | const { portfolio_descricao } = header; 34 | const self = this; 35 | return new Promise((resolve, reject) => { 36 | this._db.run( 37 | ` 38 | UPDATE portfolio 39 | SET portfolio_descricao = ? 40 | WHERE 41 | portfolio_id = ? 42 | `, 43 | [portfolio_descricao, portfolio_id], 44 | function (err) { 45 | if (err) { 46 | console.log(err); 47 | return reject("Can`t update portfolio"); 48 | } 49 | self.saveItems(portfolio_id, items).then( 50 | () => { 51 | resolve(portfolio_id); 52 | }, 53 | (err) => { 54 | console.log(err); 55 | return reject("Can`t add portfolio item"); 56 | } 57 | ); 58 | } 59 | ); 60 | }); 61 | } 62 | 63 | insertModel(header, items) { 64 | const { portfolio_descricao, user_id } = header; 65 | const self = this; 66 | return new Promise((resolve, reject) => { 67 | this._db.run( 68 | ` 69 | INSERT INTO portfolio ( 70 | portfolio_descricao, 71 | user_id, 72 | portfolio_create_date 73 | ) values (?,?,?) 74 | `, 75 | [portfolio_descricao, user_id, new Date()], 76 | function (err) { 77 | if (err) { 78 | console.log(err); 79 | return reject("Can`t add portfolio"); 80 | } 81 | self.saveItems(this.lastID, items).then( 82 | () => { 83 | resolve(this.lastID); 84 | }, 85 | (err) => { 86 | console.log(err); 87 | return reject("Can`t add portfolio item"); 88 | } 89 | ); 90 | } 91 | ); 92 | }); 93 | } 94 | 95 | saveItems(portfolio_id, items) { 96 | const itemsPromise = items 97 | ? items.map((item) => this.insertItem(portfolio_id, item)) 98 | : [Promise.resolve()]; 99 | return Promise.all([...itemsPromise]); 100 | } 101 | 102 | insertItem(portfolio_id, item) { 103 | const { acoes_id, item_quantidade, item_preco } = item; 104 | return new Promise((resolve, reject) => { 105 | this._db.run( 106 | ` 107 | INSERT INTO portfolio_item ( 108 | portfolio_id, 109 | acoes_id, 110 | item_quantidade, 111 | item_preco 112 | ) values (?,?,?,?) 113 | `, 114 | [portfolio_id, acoes_id, item_quantidade, item_preco], 115 | (err) => { 116 | if (err) { 117 | console.log(err); 118 | return reject("Can`t add portfolio item"); 119 | } 120 | resolve(); 121 | } 122 | ); 123 | }); 124 | } 125 | 126 | deleteAllItems(portfolio_id) { 127 | return new Promise((resolve, reject) => { 128 | this._db.run( 129 | ` 130 | DELETE FROM portfolio_item where portfolio_id = ?; 131 | `, 132 | [portfolio_id], 133 | (err) => { 134 | if (err) { 135 | console.log("Delete item"); 136 | console.log(err); 137 | return reject("Can`t add portfolio"); 138 | } 139 | resolve(); 140 | } 141 | ); 142 | }); 143 | } 144 | 145 | deletePortfolio(portfolio_id) { 146 | return new Promise((resolve, reject) => { 147 | this._db.run( 148 | ` 149 | DELETE FROM portfolio where portfolio_id = ?; 150 | `, 151 | [portfolio_id], 152 | (err) => { 153 | if (err) { 154 | console.log("Delete header"); 155 | console.log(err); 156 | return reject("Can`t delete portfolio"); 157 | } 158 | resolve(); 159 | } 160 | ); 161 | }); 162 | } 163 | 164 | listAllFromUser(user_id) { 165 | return new Promise((resolve, reject) => { 166 | this._db.all( 167 | ` 168 | SELECT 169 | portfolio_id, 170 | portfolio_descricao, 171 | user_id 172 | FROM portfolio 173 | WHERE 174 | user_id = ? 175 | `, 176 | [user_id], 177 | (err, rows) => { 178 | if (err) { 179 | console.log("++++ERRO+++"); 180 | console.log(err); 181 | return reject("Can`t load portfolio"); 182 | } 183 | return resolve(rows); 184 | } 185 | ); 186 | }); 187 | } 188 | 189 | findById(user_id, portfolio_id) { 190 | return new Promise((resolve, reject) => { 191 | this._db.all( 192 | ` 193 | SELECT 194 | portfolio.portfolio_id, 195 | portfolio_descricao, 196 | user_id, 197 | item_id, 198 | item_quantidade, 199 | item_preco, 200 | acoes_id 201 | FROM portfolio 202 | LEFT JOIN portfolio_item ON 203 | portfolio.portfolio_id = portfolio_item.portfolio_id 204 | WHERE 205 | user_id = ? AND 206 | portfolio.portfolio_id = ? 207 | ORDER BY 208 | item_id 209 | `, 210 | [user_id, portfolio_id], 211 | (err, rows) => { 212 | if (err) { 213 | console.log("++++ERRO+++"); 214 | console.log(err); 215 | return reject("Can`t load portfolio"); 216 | } 217 | const [first] = rows; 218 | if (first) { 219 | const header = { 220 | portfolio_id, 221 | portfolio_descricao: first.portfolio_descricao, 222 | user_id, 223 | }; 224 | const items = rows.map((row) => ({ 225 | item_quantidade: row.item_quantidade, 226 | item_preco: row.item_preco, 227 | acoes_id: row.acoes_id, 228 | })); 229 | return resolve({ ...header, items }); 230 | } 231 | return resolve({}); 232 | } 233 | ); 234 | }); 235 | } 236 | } 237 | 238 | module.exports = PortfolioDao; 239 | -------------------------------------------------------------------------------- /api/app/infra/user-dao.js: -------------------------------------------------------------------------------- 1 | const userConverter = row => ({ 2 | id: row.user_id, 3 | name: row.user_name, 4 | email: row.user_email 5 | }); 6 | 7 | class UserDao { 8 | 9 | constructor(db) { 10 | this._db = db; 11 | } 12 | 13 | findByNameAndPassword(userName, password) { 14 | return new Promise((resolve, reject) => this._db.get( 15 | `SELECT * FROM user WHERE user_name = ? AND user_password = ?`, 16 | [userName, password], 17 | (err, row) => { 18 | if (err) { 19 | console.log(err); 20 | return reject('Can`t find user'); 21 | } 22 | 23 | if(row) resolve(userConverter(row)); 24 | resolve(null); 25 | } 26 | )); 27 | } 28 | 29 | findByName(userName) { 30 | 31 | return new Promise((resolve, reject) => this._db.get( 32 | `SELECT * FROM user WHERE user_name = ?`, 33 | [userName], 34 | (err, row) => { 35 | if (err) { 36 | console.log(err); 37 | return reject('Can`t find user'); 38 | } 39 | 40 | if(row) resolve(userConverter(row)); 41 | resolve(null); 42 | } 43 | )); 44 | 45 | } 46 | 47 | add(user) { 48 | return new Promise((resolve, reject) => { 49 | 50 | this._db.run(` 51 | INSERT INTO user ( 52 | user_name, 53 | user_full_name, 54 | user_email, 55 | user_password, 56 | user_join_date 57 | ) values (?,?,?,?,?) 58 | `, 59 | [ 60 | user.userName, 61 | user.fullName, 62 | user.email, 63 | user.password, 64 | new Date() 65 | ], 66 | function (err) { 67 | if (err) { 68 | console.log(err); 69 | return reject('Can`t register new user'); 70 | } 71 | console.log(`User ${user.userName} registered!`) 72 | resolve(); 73 | }); 74 | }); 75 | } 76 | 77 | } 78 | module.exports = UserDao; -------------------------------------------------------------------------------- /api/app/routes/acoes.js: -------------------------------------------------------------------------------- 1 | const { acoesAPI } = require("../api"); 2 | 3 | const { wrapAsync, auth } = require("../infra"); 4 | 5 | module.exports = (app) => { 6 | app 7 | .route("/acoes") 8 | .get(wrapAsync(acoesAPI.list)) 9 | .post(auth, wrapAsync(acoesAPI.add)); 10 | 11 | app.route("/acoes/:acoesID").get(wrapAsync(acoesAPI.findById)); 12 | }; 13 | -------------------------------------------------------------------------------- /api/app/routes/index.js: -------------------------------------------------------------------------------- 1 | const acoesRoutes = require("./acoes"); 2 | const portfolioRoutes = require("./portfolio"); 3 | const userRoutes = require("./user"); 4 | 5 | module.exports = { acoesRoutes, portfolioRoutes, userRoutes }; 6 | -------------------------------------------------------------------------------- /api/app/routes/portfolio.js: -------------------------------------------------------------------------------- 1 | const { portfolioAPI } = require("../api"); 2 | 3 | const { wrapAsync, auth } = require("../infra"); 4 | 5 | module.exports = (app) => { 6 | app 7 | .route("/portfolios") 8 | .post(auth, wrapAsync(portfolioAPI.add)) 9 | .get(auth, wrapAsync(portfolioAPI.list)); 10 | 11 | app 12 | .route("/portfolios/:portfolioId") 13 | .put(auth, wrapAsync(portfolioAPI.put)) 14 | .delete(auth, wrapAsync(portfolioAPI.remove)) 15 | .get(auth, wrapAsync(portfolioAPI.findById)); 16 | }; 17 | -------------------------------------------------------------------------------- /api/app/routes/user.js: -------------------------------------------------------------------------------- 1 | const { userAPI } = require("../api"); 2 | 3 | const { wrapAsync } = require("../infra"); 4 | 5 | module.exports = (app) => { 6 | app.route("/user/login").post(wrapAsync(userAPI.login)); 7 | 8 | app.route("/user/signup").post(wrapAsync(userAPI.register)); 9 | 10 | app 11 | .route("/user/exists/:userName") 12 | .get(wrapAsync(userAPI.checkUserNameTaken)); 13 | }; 14 | -------------------------------------------------------------------------------- /api/config/database.js: -------------------------------------------------------------------------------- 1 | const sqlite3 = require("sqlite3").verbose(); 2 | const db = new sqlite3.Database("data.db"); 3 | 4 | const USER_SCHEMA = ` 5 | CREATE TABLE IF NOT EXISTS user ( 6 | user_id INTEGER PRIMARY KEY AUTOINCREMENT, 7 | user_name VARCHAR(30) NOT NULL UNIQUE, 8 | user_email VARCHAR(255) NOT NULL, 9 | user_password VARCAHR(255) NOT NULL, 10 | user_full_name VARCAHR(40) NOT NULL, 11 | user_join_date TIMESTAMP DEFAULT current_timestamp 12 | ) 13 | `; 14 | 15 | const INSERT_DEFAULT_USER_1 = ` 16 | INSERT INTO user ( 17 | user_name, 18 | user_email, 19 | user_password, 20 | user_full_name 21 | ) SELECT 'alvaro', 'alvaro@bytebank.com', '123', 'Alvaro' WHERE NOT EXISTS (SELECT * FROM user WHERE user_name = 'alvaro') 22 | `; 23 | 24 | const INSERT_DEFAULT_USER_2 = ` 25 | INSERT INTO user ( 26 | user_name, 27 | user_email, 28 | user_password, 29 | user_full_name 30 | ) SELECT 'mario', 'mario@bytebank.com', '123', 'Mario' WHERE NOT EXISTS (SELECT * FROM user WHERE user_name = 'mario') 31 | `; 32 | 33 | const PORTFOLIO_SCHEMA = ` 34 | CREATE TABLE IF NOT EXISTS portfolio ( 35 | portfolio_id INTEGER PRIMARY KEY AUTOINCREMENT, 36 | portfolio_create_date TIMESTAMP NOT NULL, 37 | portfolio_descricao TEXT DEFAULT ('') NOT NULL, 38 | user_id INTEGER, 39 | FOREIGN KEY(user_id) REFERENCES user(user_id) ON DELETE CASCADE 40 | ) 41 | `; 42 | 43 | const PORTFOLIO_ITEM_SCHEMA = ` 44 | CREATE TABLE IF NOT EXISTS portfolio_item ( 45 | item_id INTEGER PRIMARY KEY AUTOINCREMENT, 46 | item_quantidade REAL, 47 | item_preco REAL, 48 | portfolio_id INTEGER, 49 | acoes_id INTEGER, 50 | 51 | FOREIGN KEY (portfolio_id) REFERENCES portfolio (portfolio_id) ON DELETE CASCADE, 52 | FOREIGN KEY(acoes_id) REFERENCES acoes(acoes_id) ON DELETE CASCADE 53 | ); 54 | `; 55 | 56 | const acoes_SCHEMA = ` 57 | CREATE TABLE IF NOT EXISTS acoes ( 58 | acoes_id INTEGER PRIMARY KEY AUTOINCREMENT, 59 | acoes_codigo VARCHAR(10) NOT NULL UNIQUE, 60 | acoes_descricao VARCHAR(30) DEFAULT ('') NOT NULL, 61 | acoes_preco REAL 62 | ) 63 | `; 64 | 65 | const INSERT_acoes_1 = ` 66 | INSERT INTO acoes ( 67 | acoes_codigo, 68 | acoes_descricao, 69 | acoes_preco 70 | ) SELECT 'ALUR3', 'Alura ON', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'ALUR3') 71 | `; 72 | 73 | const INSERT_acoes_2 = ` 74 | INSERT INTO acoes ( 75 | acoes_codigo, 76 | acoes_descricao, 77 | acoes_preco 78 | ) SELECT 'ALUR4', 'Alura PN', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'ALUR4') 79 | `; 80 | 81 | const INSERT_acoes_3 = ` 82 | INSERT INTO acoes ( 83 | acoes_codigo, 84 | acoes_descricao, 85 | acoes_preco 86 | ) SELECT 'CAEL3', 'Caellum ON', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'CAEL3') 87 | `; 88 | 89 | const INSERT_acoes_4 = ` 90 | INSERT INTO acoes ( 91 | acoes_codigo, 92 | acoes_descricao, 93 | acoes_preco 94 | ) SELECT 'CASC3', 'Casa do codigo ON', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'CASC3') 95 | `; 96 | 97 | const INSERT_acoes_5 = ` 98 | INSERT INTO acoes ( 99 | acoes_codigo, 100 | acoes_descricao, 101 | acoes_preco 102 | ) SELECT 'JAVA3', 'JAVA ON', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'JAVA3') 103 | `; 104 | 105 | const INSERT_acoes_6 = ` 106 | INSERT INTO acoes ( 107 | acoes_codigo, 108 | acoes_descricao, 109 | acoes_preco 110 | ) SELECT 'PHPP3', 'PHP ON', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'PHPP3') 111 | `; 112 | 113 | const INSERT_acoes_7 = ` 114 | INSERT INTO acoes ( 115 | acoes_codigo, 116 | acoes_descricao, 117 | acoes_preco 118 | ) SELECT 'NETC3', 'Net Core ON', 25.10 WHERE NOT EXISTS (SELECT * FROM acoes WHERE acoes_codigo = 'NETC3') 119 | `; 120 | 121 | db.serialize(() => { 122 | db.run("PRAGMA foreign_keys=ON"); 123 | db.run(USER_SCHEMA); 124 | db.run(INSERT_DEFAULT_USER_1); 125 | db.run(INSERT_DEFAULT_USER_2); 126 | db.run(acoes_SCHEMA); 127 | db.run(INSERT_acoes_1); 128 | db.run(INSERT_acoes_2); 129 | db.run(INSERT_acoes_3); 130 | db.run(INSERT_acoes_4); 131 | db.run(INSERT_acoes_5); 132 | db.run(INSERT_acoes_6); 133 | db.run(INSERT_acoes_7); 134 | db.run(PORTFOLIO_SCHEMA); 135 | db.run(PORTFOLIO_ITEM_SCHEMA); 136 | 137 | db.each("SELECT * FROM user", (err, user) => { 138 | console.log("Users"); 139 | console.log(user); 140 | }); 141 | db.each("SELECT * FROM acoes", (err, user) => { 142 | console.log("acoes"); 143 | console.log(user); 144 | }); 145 | }); 146 | 147 | process.on("SIGINT", () => 148 | db.close(() => { 149 | console.log("Database closed"); 150 | process.exit(0); 151 | }) 152 | ); 153 | 154 | module.exports = db; 155 | -------------------------------------------------------------------------------- /api/config/express.js: -------------------------------------------------------------------------------- 1 | const express = require("express"), 2 | app = express(), 3 | bodyParser = require("body-parser"), 4 | cors = require("cors"), 5 | db = require("./database"), 6 | { acoesRoutes, portfolioRoutes, userRoutes } = require("../app/routes"); 7 | 8 | app.set("secret", "your secret phrase here"); 9 | 10 | const corsOptions = { 11 | exposedHeaders: ["x-access-token"], 12 | }; 13 | 14 | app.use(cors(corsOptions)); 15 | app.use(bodyParser.json()); 16 | 17 | app.use((req, res, next) => { 18 | req.db = db; 19 | next(); 20 | }); 21 | 22 | app.use((req, res, next) => { 23 | const token = req.headers["x-access-token"]; 24 | console.log("####################################"); 25 | if (token) { 26 | console.log("A token is send by the application"); 27 | console.log("Token value is " + token); 28 | } else { 29 | console.log("No token is send by the the application"); 30 | } 31 | console.log("####################################"); 32 | next(); 33 | }); 34 | 35 | acoesRoutes(app); 36 | portfolioRoutes(app); 37 | userRoutes(app); 38 | 39 | app.use("*", (req, res) => { 40 | res 41 | .status(404) 42 | .json({ message: `route ${req.originalUrl} does not exists!` }); 43 | }); 44 | 45 | app.use((err, req, res, next) => { 46 | console.error(err.stack); 47 | res.status(500).json({ message: "Internal server error" }); 48 | }); 49 | 50 | module.exports = app; 51 | -------------------------------------------------------------------------------- /api/data.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/api/data.db -------------------------------------------------------------------------------- /api/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bytebankbroker", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/runtime": { 8 | "version": "7.11.0", 9 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.0.tgz", 10 | "integrity": "sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw==", 11 | "requires": { 12 | "regenerator-runtime": "^0.13.4" 13 | } 14 | }, 15 | "@jimp/bmp": { 16 | "version": "0.10.3", 17 | "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.10.3.tgz", 18 | "integrity": "sha512-keMOc5woiDmONXsB/6aXLR4Z5Q+v8lFq3EY2rcj2FmstbDMhRuGbmcBxlEgOqfRjwvtf/wOtJ3Of37oAWtVfLg==", 19 | "requires": { 20 | "@babel/runtime": "^7.7.2", 21 | "@jimp/utils": "^0.10.3", 22 | "bmp-js": "^0.1.0", 23 | "core-js": "^3.4.1" 24 | } 25 | }, 26 | "@jimp/core": { 27 | "version": "0.10.3", 28 | "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.10.3.tgz", 29 | "integrity": "sha512-Gd5IpL3U2bFIO57Fh/OA3HCpWm4uW/pU01E75rI03BXfTdz3T+J7TwvyG1XaqsQ7/DSlS99GXtLQPlfFIe28UA==", 30 | "requires": { 31 | "@babel/runtime": "^7.7.2", 32 | "@jimp/utils": "^0.10.3", 33 | "any-base": "^1.1.0", 34 | "buffer": "^5.2.0", 35 | "core-js": "^3.4.1", 36 | "exif-parser": "^0.1.12", 37 | "file-type": "^9.0.0", 38 | "load-bmfont": "^1.3.1", 39 | "mkdirp": "^0.5.1", 40 | "phin": "^2.9.1", 41 | "pixelmatch": "^4.0.2", 42 | "tinycolor2": "^1.4.1" 43 | } 44 | }, 45 | "@jimp/custom": { 46 | "version": "0.10.3", 47 | "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.10.3.tgz", 48 | "integrity": "sha512-nZmSI+jwTi5IRyNLbKSXQovoeqsw+D0Jn0SxW08wYQvdkiWA8bTlDQFgQ7HVwCAKBm8oKkDB/ZEo9qvHJ+1gAQ==", 49 | "requires": { 50 | "@babel/runtime": "^7.7.2", 51 | "@jimp/core": "^0.10.3", 52 | "core-js": "^3.4.1" 53 | } 54 | }, 55 | "@jimp/gif": { 56 | "version": "0.10.3", 57 | "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.10.3.tgz", 58 | "integrity": "sha512-vjlRodSfz1CrUvvrnUuD/DsLK1GHB/yDZXHthVdZu23zYJIW7/WrIiD1IgQ5wOMV7NocfrvPn2iqUfBP81/WWA==", 59 | "requires": { 60 | "@babel/runtime": "^7.7.2", 61 | "@jimp/utils": "^0.10.3", 62 | "core-js": "^3.4.1", 63 | "omggif": "^1.0.9" 64 | } 65 | }, 66 | "@jimp/jpeg": { 67 | "version": "0.10.3", 68 | "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.10.3.tgz", 69 | "integrity": "sha512-AAANwgUZOt6f6P7LZxY9lyJ9xclqutYJlsxt3JbriXUGJgrrFAIkcKcqv1nObgmQASSAQKYaMV9KdHjMlWFKlQ==", 70 | "requires": { 71 | "@babel/runtime": "^7.7.2", 72 | "@jimp/utils": "^0.10.3", 73 | "core-js": "^3.4.1", 74 | "jpeg-js": "^0.3.4" 75 | } 76 | }, 77 | "@jimp/plugin-blit": { 78 | "version": "0.10.3", 79 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.10.3.tgz", 80 | "integrity": "sha512-5zlKlCfx4JWw9qUVC7GI4DzXyxDWyFvgZLaoGFoT00mlXlN75SarlDwc9iZ/2e2kp4bJWxz3cGgG4G/WXrbg3Q==", 81 | "requires": { 82 | "@babel/runtime": "^7.7.2", 83 | "@jimp/utils": "^0.10.3", 84 | "core-js": "^3.4.1" 85 | } 86 | }, 87 | "@jimp/plugin-blur": { 88 | "version": "0.10.3", 89 | "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.10.3.tgz", 90 | "integrity": "sha512-cTOK3rjh1Yjh23jSfA6EHCHjsPJDEGLC8K2y9gM7dnTUK1y9NNmkFS23uHpyjgsWFIoH9oRh2SpEs3INjCpZhQ==", 91 | "requires": { 92 | "@babel/runtime": "^7.7.2", 93 | "@jimp/utils": "^0.10.3", 94 | "core-js": "^3.4.1" 95 | } 96 | }, 97 | "@jimp/plugin-circle": { 98 | "version": "0.10.3", 99 | "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.10.3.tgz", 100 | "integrity": "sha512-51GAPIVelqAcfuUpaM5JWJ0iWl4vEjNXB7p4P7SX5udugK5bxXUjO6KA2qgWmdpHuCKtoNgkzWU9fNSuYp7tCA==", 101 | "requires": { 102 | "@babel/runtime": "^7.7.2", 103 | "@jimp/utils": "^0.10.3", 104 | "core-js": "^3.4.1" 105 | } 106 | }, 107 | "@jimp/plugin-color": { 108 | "version": "0.10.3", 109 | "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.10.3.tgz", 110 | "integrity": "sha512-RgeHUElmlTH7vpI4WyQrz6u59spiKfVQbsG/XUzfWGamFSixa24ZDwX/yV/Ts+eNaz7pZeIuv533qmKPvw2ujg==", 111 | "requires": { 112 | "@babel/runtime": "^7.7.2", 113 | "@jimp/utils": "^0.10.3", 114 | "core-js": "^3.4.1", 115 | "tinycolor2": "^1.4.1" 116 | } 117 | }, 118 | "@jimp/plugin-contain": { 119 | "version": "0.10.3", 120 | "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.10.3.tgz", 121 | "integrity": "sha512-bYJKW9dqzcB0Ihc6u7jSyKa3juStzbLs2LFr6fu8TzA2WkMS/R8h+ddkiO36+F9ILTWHP0CIA3HFe5OdOGcigw==", 122 | "requires": { 123 | "@babel/runtime": "^7.7.2", 124 | "@jimp/utils": "^0.10.3", 125 | "core-js": "^3.4.1" 126 | } 127 | }, 128 | "@jimp/plugin-cover": { 129 | "version": "0.10.3", 130 | "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.10.3.tgz", 131 | "integrity": "sha512-pOxu0cM0BRPzdV468n4dMocJXoMbTnARDY/EpC3ZW15SpMuc/dr1KhWQHgoQX5kVW1Wt8zgqREAJJCQ5KuPKDA==", 132 | "requires": { 133 | "@babel/runtime": "^7.7.2", 134 | "@jimp/utils": "^0.10.3", 135 | "core-js": "^3.4.1" 136 | } 137 | }, 138 | "@jimp/plugin-crop": { 139 | "version": "0.10.3", 140 | "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.10.3.tgz", 141 | "integrity": "sha512-nB7HgOjjl9PgdHr076xZ3Sr6qHYzeBYBs9qvs3tfEEUeYMNnvzgCCGtUl6eMakazZFCMk3mhKmcB9zQuHFOvkg==", 142 | "requires": { 143 | "@babel/runtime": "^7.7.2", 144 | "@jimp/utils": "^0.10.3", 145 | "core-js": "^3.4.1" 146 | } 147 | }, 148 | "@jimp/plugin-displace": { 149 | "version": "0.10.3", 150 | "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.10.3.tgz", 151 | "integrity": "sha512-8t3fVKCH5IVqI4lewe4lFFjpxxr69SQCz5/tlpDLQZsrNScNJivHdQ09zljTrVTCSgeCqQJIKgH2Q7Sk/pAZ0w==", 152 | "requires": { 153 | "@babel/runtime": "^7.7.2", 154 | "@jimp/utils": "^0.10.3", 155 | "core-js": "^3.4.1" 156 | } 157 | }, 158 | "@jimp/plugin-dither": { 159 | "version": "0.10.3", 160 | "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.10.3.tgz", 161 | "integrity": "sha512-JCX/oNSnEg1kGQ8ffZ66bEgQOLCY3Rn+lrd6v1jjLy/mn9YVZTMsxLtGCXpiCDC2wG/KTmi4862ysmP9do9dAQ==", 162 | "requires": { 163 | "@babel/runtime": "^7.7.2", 164 | "@jimp/utils": "^0.10.3", 165 | "core-js": "^3.4.1" 166 | } 167 | }, 168 | "@jimp/plugin-fisheye": { 169 | "version": "0.10.3", 170 | "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.10.3.tgz", 171 | "integrity": "sha512-RRZb1wqe+xdocGcFtj2xHU7sF7xmEZmIa6BmrfSchjyA2b32TGPWKnP3qyj7p6LWEsXn+19hRYbjfyzyebPElQ==", 172 | "requires": { 173 | "@babel/runtime": "^7.7.2", 174 | "@jimp/utils": "^0.10.3", 175 | "core-js": "^3.4.1" 176 | } 177 | }, 178 | "@jimp/plugin-flip": { 179 | "version": "0.10.3", 180 | "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.10.3.tgz", 181 | "integrity": "sha512-0epbi8XEzp0wmSjoW9IB0iMu0yNF17aZOxLdURCN3Zr+8nWPs5VNIMqSVa1Y62GSyiMDpVpKF/ITiXre+EqrPg==", 182 | "requires": { 183 | "@babel/runtime": "^7.7.2", 184 | "@jimp/utils": "^0.10.3", 185 | "core-js": "^3.4.1" 186 | } 187 | }, 188 | "@jimp/plugin-gaussian": { 189 | "version": "0.10.3", 190 | "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.10.3.tgz", 191 | "integrity": "sha512-25eHlFbHUDnMMGpgRBBeQ2AMI4wsqCg46sue0KklI+c2BaZ+dGXmJA5uT8RTOrt64/K9Wz5E+2n7eBnny4dfpQ==", 192 | "requires": { 193 | "@babel/runtime": "^7.7.2", 194 | "@jimp/utils": "^0.10.3", 195 | "core-js": "^3.4.1" 196 | } 197 | }, 198 | "@jimp/plugin-invert": { 199 | "version": "0.10.3", 200 | "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.10.3.tgz", 201 | "integrity": "sha512-effYSApWY/FbtlzqsKXlTLkgloKUiHBKjkQnqh5RL4oQxh/33j6aX+HFdDyQKtsXb8CMd4xd7wyiD2YYabTa0g==", 202 | "requires": { 203 | "@babel/runtime": "^7.7.2", 204 | "@jimp/utils": "^0.10.3", 205 | "core-js": "^3.4.1" 206 | } 207 | }, 208 | "@jimp/plugin-mask": { 209 | "version": "0.10.3", 210 | "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.10.3.tgz", 211 | "integrity": "sha512-twrg8q8TIhM9Z6Jcu9/5f+OCAPaECb0eKrrbbIajJqJ3bCUlj5zbfgIhiQIzjPJ6KjpnFPSqHQfHkU1Vvk/nVw==", 212 | "requires": { 213 | "@babel/runtime": "^7.7.2", 214 | "@jimp/utils": "^0.10.3", 215 | "core-js": "^3.4.1" 216 | } 217 | }, 218 | "@jimp/plugin-normalize": { 219 | "version": "0.10.3", 220 | "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.10.3.tgz", 221 | "integrity": "sha512-xkb5eZI/mMlbwKkDN79+1/t/+DBo8bBXZUMsT4gkFgMRKNRZ6NQPxlv1d3QpRzlocsl6UMxrHnhgnXdLAcgrXw==", 222 | "requires": { 223 | "@babel/runtime": "^7.7.2", 224 | "@jimp/utils": "^0.10.3", 225 | "core-js": "^3.4.1" 226 | } 227 | }, 228 | "@jimp/plugin-print": { 229 | "version": "0.10.3", 230 | "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.10.3.tgz", 231 | "integrity": "sha512-wjRiI6yjXsAgMe6kVjizP+RgleUCLkH256dskjoNvJzmzbEfO7xQw9g6M02VET+emnbY0CO83IkrGm2q43VRyg==", 232 | "requires": { 233 | "@babel/runtime": "^7.7.2", 234 | "@jimp/utils": "^0.10.3", 235 | "core-js": "^3.4.1", 236 | "load-bmfont": "^1.4.0" 237 | } 238 | }, 239 | "@jimp/plugin-resize": { 240 | "version": "0.10.3", 241 | "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.10.3.tgz", 242 | "integrity": "sha512-rf8YmEB1d7Sg+g4LpqF0Mp+dfXfb6JFJkwlAIWPUOR7lGsPWALavEwTW91c0etEdnp0+JB9AFpy6zqq7Lwkq6w==", 243 | "requires": { 244 | "@babel/runtime": "^7.7.2", 245 | "@jimp/utils": "^0.10.3", 246 | "core-js": "^3.4.1" 247 | } 248 | }, 249 | "@jimp/plugin-rotate": { 250 | "version": "0.10.3", 251 | "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.10.3.tgz", 252 | "integrity": "sha512-YXLlRjm18fkW9MOHUaVAxWjvgZM851ofOipytz5FyKp4KZWDLk+dZK1JNmVmK7MyVmAzZ5jsgSLhIgj+GgN0Eg==", 253 | "requires": { 254 | "@babel/runtime": "^7.7.2", 255 | "@jimp/utils": "^0.10.3", 256 | "core-js": "^3.4.1" 257 | } 258 | }, 259 | "@jimp/plugin-scale": { 260 | "version": "0.10.3", 261 | "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.10.3.tgz", 262 | "integrity": "sha512-5DXD7x7WVcX1gUgnlFXQa8F+Q3ThRYwJm+aesgrYvDOY+xzRoRSdQvhmdd4JEEue3lyX44DvBSgCIHPtGcEPaw==", 263 | "requires": { 264 | "@babel/runtime": "^7.7.2", 265 | "@jimp/utils": "^0.10.3", 266 | "core-js": "^3.4.1" 267 | } 268 | }, 269 | "@jimp/plugin-shadow": { 270 | "version": "0.10.3", 271 | "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.10.3.tgz", 272 | "integrity": "sha512-/nkFXpt2zVcdP4ETdkAUL0fSzyrC5ZFxdcphbYBodqD7fXNqChS/Un1eD4xCXWEpW8cnG9dixZgQgStjywH0Mg==", 273 | "requires": { 274 | "@babel/runtime": "^7.7.2", 275 | "@jimp/utils": "^0.10.3", 276 | "core-js": "^3.4.1" 277 | } 278 | }, 279 | "@jimp/plugin-threshold": { 280 | "version": "0.10.3", 281 | "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.10.3.tgz", 282 | "integrity": "sha512-Dzh0Yq2wXP2SOnxcbbiyA4LJ2luwrdf1MghNIt9H+NX7B+IWw/N8qA2GuSm9n4BPGSLluuhdAWJqHcTiREriVA==", 283 | "requires": { 284 | "@babel/runtime": "^7.7.2", 285 | "@jimp/utils": "^0.10.3", 286 | "core-js": "^3.4.1" 287 | } 288 | }, 289 | "@jimp/plugins": { 290 | "version": "0.10.3", 291 | "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.10.3.tgz", 292 | "integrity": "sha512-jTT3/7hOScf0EIKiAXmxwayHhryhc1wWuIe3FrchjDjr9wgIGNN2a7XwCgPl3fML17DXK1x8EzDneCdh261bkw==", 293 | "requires": { 294 | "@babel/runtime": "^7.7.2", 295 | "@jimp/plugin-blit": "^0.10.3", 296 | "@jimp/plugin-blur": "^0.10.3", 297 | "@jimp/plugin-circle": "^0.10.3", 298 | "@jimp/plugin-color": "^0.10.3", 299 | "@jimp/plugin-contain": "^0.10.3", 300 | "@jimp/plugin-cover": "^0.10.3", 301 | "@jimp/plugin-crop": "^0.10.3", 302 | "@jimp/plugin-displace": "^0.10.3", 303 | "@jimp/plugin-dither": "^0.10.3", 304 | "@jimp/plugin-fisheye": "^0.10.3", 305 | "@jimp/plugin-flip": "^0.10.3", 306 | "@jimp/plugin-gaussian": "^0.10.3", 307 | "@jimp/plugin-invert": "^0.10.3", 308 | "@jimp/plugin-mask": "^0.10.3", 309 | "@jimp/plugin-normalize": "^0.10.3", 310 | "@jimp/plugin-print": "^0.10.3", 311 | "@jimp/plugin-resize": "^0.10.3", 312 | "@jimp/plugin-rotate": "^0.10.3", 313 | "@jimp/plugin-scale": "^0.10.3", 314 | "@jimp/plugin-shadow": "^0.10.3", 315 | "@jimp/plugin-threshold": "^0.10.3", 316 | "core-js": "^3.4.1", 317 | "timm": "^1.6.1" 318 | } 319 | }, 320 | "@jimp/png": { 321 | "version": "0.10.3", 322 | "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.10.3.tgz", 323 | "integrity": "sha512-YKqk/dkl+nGZxSYIDQrqhmaP8tC3IK8H7dFPnnzFVvbhDnyYunqBZZO3SaZUKTichClRw8k/CjBhbc+hifSGWg==", 324 | "requires": { 325 | "@babel/runtime": "^7.7.2", 326 | "@jimp/utils": "^0.10.3", 327 | "core-js": "^3.4.1", 328 | "pngjs": "^3.3.3" 329 | } 330 | }, 331 | "@jimp/tiff": { 332 | "version": "0.10.3", 333 | "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.10.3.tgz", 334 | "integrity": "sha512-7EsJzZ5Y/EtinkBGuwX3Bi4S+zgbKouxjt9c82VJTRJOQgLWsE/RHqcyRCOQBhHAZ9QexYmDz34medfLKdoX0g==", 335 | "requires": { 336 | "@babel/runtime": "^7.7.2", 337 | "core-js": "^3.4.1", 338 | "utif": "^2.0.1" 339 | } 340 | }, 341 | "@jimp/types": { 342 | "version": "0.10.3", 343 | "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.10.3.tgz", 344 | "integrity": "sha512-XGmBakiHZqseSWr/puGN+CHzx0IKBSpsKlmEmsNV96HKDiP6eu8NSnwdGCEq2mmIHe0JNcg1hqg59hpwtQ7Tiw==", 345 | "requires": { 346 | "@babel/runtime": "^7.7.2", 347 | "@jimp/bmp": "^0.10.3", 348 | "@jimp/gif": "^0.10.3", 349 | "@jimp/jpeg": "^0.10.3", 350 | "@jimp/png": "^0.10.3", 351 | "@jimp/tiff": "^0.10.3", 352 | "core-js": "^3.4.1", 353 | "timm": "^1.6.1" 354 | } 355 | }, 356 | "@jimp/utils": { 357 | "version": "0.10.3", 358 | "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.10.3.tgz", 359 | "integrity": "sha512-VcSlQhkil4ReYmg1KkN+WqHyYfZ2XfZxDsKAHSfST1GEz/RQHxKZbX+KhFKtKflnL0F4e6DlNQj3vznMNXCR2w==", 360 | "requires": { 361 | "@babel/runtime": "^7.7.2", 362 | "core-js": "^3.4.1", 363 | "regenerator-runtime": "^0.13.3" 364 | } 365 | }, 366 | "abbrev": { 367 | "version": "1.1.1", 368 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 369 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 370 | }, 371 | "accepts": { 372 | "version": "1.3.7", 373 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 374 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 375 | "requires": { 376 | "mime-types": "~2.1.24", 377 | "negotiator": "0.6.2" 378 | } 379 | }, 380 | "ansi-regex": { 381 | "version": "2.1.1", 382 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 383 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 384 | }, 385 | "any-base": { 386 | "version": "1.1.0", 387 | "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", 388 | "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" 389 | }, 390 | "append-field": { 391 | "version": "1.0.0", 392 | "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", 393 | "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" 394 | }, 395 | "aproba": { 396 | "version": "1.2.0", 397 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", 398 | "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" 399 | }, 400 | "are-we-there-yet": { 401 | "version": "1.1.5", 402 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", 403 | "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", 404 | "requires": { 405 | "delegates": "^1.0.0", 406 | "readable-stream": "^2.0.6" 407 | }, 408 | "dependencies": { 409 | "isarray": { 410 | "version": "1.0.0", 411 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 412 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 413 | }, 414 | "readable-stream": { 415 | "version": "2.3.7", 416 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 417 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 418 | "requires": { 419 | "core-util-is": "~1.0.0", 420 | "inherits": "~2.0.3", 421 | "isarray": "~1.0.0", 422 | "process-nextick-args": "~2.0.0", 423 | "safe-buffer": "~5.1.1", 424 | "string_decoder": "~1.1.1", 425 | "util-deprecate": "~1.0.1" 426 | } 427 | }, 428 | "string_decoder": { 429 | "version": "1.1.1", 430 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 431 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 432 | "requires": { 433 | "safe-buffer": "~5.1.0" 434 | } 435 | } 436 | } 437 | }, 438 | "array-flatten": { 439 | "version": "1.1.1", 440 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 441 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 442 | }, 443 | "balanced-match": { 444 | "version": "1.0.0", 445 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 446 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 447 | }, 448 | "base64-js": { 449 | "version": "1.3.1", 450 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 451 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 452 | }, 453 | "bmp-js": { 454 | "version": "0.1.0", 455 | "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", 456 | "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" 457 | }, 458 | "body-parser": { 459 | "version": "1.19.0", 460 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 461 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 462 | "requires": { 463 | "bytes": "3.1.0", 464 | "content-type": "~1.0.4", 465 | "debug": "2.6.9", 466 | "depd": "~1.1.2", 467 | "http-errors": "1.7.2", 468 | "iconv-lite": "0.4.24", 469 | "on-finished": "~2.3.0", 470 | "qs": "6.7.0", 471 | "raw-body": "2.4.0", 472 | "type-is": "~1.6.17" 473 | } 474 | }, 475 | "boom": { 476 | "version": "7.3.0", 477 | "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", 478 | "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==", 479 | "requires": { 480 | "hoek": "6.x.x" 481 | } 482 | }, 483 | "brace-expansion": { 484 | "version": "1.1.11", 485 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 486 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 487 | "requires": { 488 | "balanced-match": "^1.0.0", 489 | "concat-map": "0.0.1" 490 | } 491 | }, 492 | "buffer": { 493 | "version": "5.6.0", 494 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", 495 | "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", 496 | "requires": { 497 | "base64-js": "^1.0.2", 498 | "ieee754": "^1.1.4" 499 | } 500 | }, 501 | "buffer-equal": { 502 | "version": "0.0.1", 503 | "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", 504 | "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" 505 | }, 506 | "buffer-equal-constant-time": { 507 | "version": "1.0.1", 508 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 509 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 510 | }, 511 | "buffer-from": { 512 | "version": "1.1.1", 513 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 514 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 515 | }, 516 | "busboy": { 517 | "version": "0.2.14", 518 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", 519 | "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", 520 | "requires": { 521 | "dicer": "0.2.5", 522 | "readable-stream": "1.1.x" 523 | } 524 | }, 525 | "bytes": { 526 | "version": "3.1.0", 527 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 528 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 529 | }, 530 | "chownr": { 531 | "version": "1.1.4", 532 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 533 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" 534 | }, 535 | "code-point-at": { 536 | "version": "1.1.0", 537 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 538 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 539 | }, 540 | "concat-map": { 541 | "version": "0.0.1", 542 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 543 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 544 | }, 545 | "concat-stream": { 546 | "version": "1.6.2", 547 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 548 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 549 | "requires": { 550 | "buffer-from": "^1.0.0", 551 | "inherits": "^2.0.3", 552 | "readable-stream": "^2.2.2", 553 | "typedarray": "^0.0.6" 554 | }, 555 | "dependencies": { 556 | "isarray": { 557 | "version": "1.0.0", 558 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 559 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 560 | }, 561 | "readable-stream": { 562 | "version": "2.3.7", 563 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 564 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 565 | "requires": { 566 | "core-util-is": "~1.0.0", 567 | "inherits": "~2.0.3", 568 | "isarray": "~1.0.0", 569 | "process-nextick-args": "~2.0.0", 570 | "safe-buffer": "~5.1.1", 571 | "string_decoder": "~1.1.1", 572 | "util-deprecate": "~1.0.1" 573 | } 574 | }, 575 | "string_decoder": { 576 | "version": "1.1.1", 577 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 578 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 579 | "requires": { 580 | "safe-buffer": "~5.1.0" 581 | } 582 | } 583 | } 584 | }, 585 | "console-control-strings": { 586 | "version": "1.1.0", 587 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 588 | "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 589 | }, 590 | "content-disposition": { 591 | "version": "0.5.3", 592 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 593 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 594 | "requires": { 595 | "safe-buffer": "5.1.2" 596 | } 597 | }, 598 | "content-type": { 599 | "version": "1.0.4", 600 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 601 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 602 | }, 603 | "cookie": { 604 | "version": "0.4.0", 605 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 606 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 607 | }, 608 | "cookie-signature": { 609 | "version": "1.0.6", 610 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 611 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 612 | }, 613 | "core-js": { 614 | "version": "3.6.5", 615 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", 616 | "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" 617 | }, 618 | "core-util-is": { 619 | "version": "1.0.2", 620 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 621 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 622 | }, 623 | "cors": { 624 | "version": "2.8.5", 625 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 626 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 627 | "requires": { 628 | "object-assign": "^4", 629 | "vary": "^1" 630 | } 631 | }, 632 | "cryptiles": { 633 | "version": "4.1.3", 634 | "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz", 635 | "integrity": "sha512-gT9nyTMSUC1JnziQpPbxKGBbUg8VL7Zn2NB4E1cJYvuXdElHrwxrV9bmltZGDzet45zSDGyYceueke1TjynGzw==", 636 | "requires": { 637 | "boom": "7.x.x" 638 | } 639 | }, 640 | "debug": { 641 | "version": "2.6.9", 642 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 643 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 644 | "requires": { 645 | "ms": "2.0.0" 646 | } 647 | }, 648 | "deep-extend": { 649 | "version": "0.6.0", 650 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 651 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" 652 | }, 653 | "delegates": { 654 | "version": "1.0.0", 655 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 656 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" 657 | }, 658 | "depd": { 659 | "version": "1.1.2", 660 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 661 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 662 | }, 663 | "destroy": { 664 | "version": "1.0.4", 665 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 666 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 667 | }, 668 | "detect-libc": { 669 | "version": "1.0.3", 670 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", 671 | "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" 672 | }, 673 | "dicer": { 674 | "version": "0.2.5", 675 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", 676 | "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", 677 | "requires": { 678 | "readable-stream": "1.1.x", 679 | "streamsearch": "0.1.2" 680 | } 681 | }, 682 | "dom-walk": { 683 | "version": "0.1.2", 684 | "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", 685 | "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" 686 | }, 687 | "ecdsa-sig-formatter": { 688 | "version": "1.0.11", 689 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 690 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 691 | "requires": { 692 | "safe-buffer": "^5.0.1" 693 | } 694 | }, 695 | "ee-first": { 696 | "version": "1.1.1", 697 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 698 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 699 | }, 700 | "encodeurl": { 701 | "version": "1.0.2", 702 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 703 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 704 | }, 705 | "escape-html": { 706 | "version": "1.0.3", 707 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 708 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 709 | }, 710 | "etag": { 711 | "version": "1.8.1", 712 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 713 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 714 | }, 715 | "exif-parser": { 716 | "version": "0.1.12", 717 | "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", 718 | "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" 719 | }, 720 | "express": { 721 | "version": "4.17.1", 722 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 723 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 724 | "requires": { 725 | "accepts": "~1.3.7", 726 | "array-flatten": "1.1.1", 727 | "body-parser": "1.19.0", 728 | "content-disposition": "0.5.3", 729 | "content-type": "~1.0.4", 730 | "cookie": "0.4.0", 731 | "cookie-signature": "1.0.6", 732 | "debug": "2.6.9", 733 | "depd": "~1.1.2", 734 | "encodeurl": "~1.0.2", 735 | "escape-html": "~1.0.3", 736 | "etag": "~1.8.1", 737 | "finalhandler": "~1.1.2", 738 | "fresh": "0.5.2", 739 | "merge-descriptors": "1.0.1", 740 | "methods": "~1.1.2", 741 | "on-finished": "~2.3.0", 742 | "parseurl": "~1.3.3", 743 | "path-to-regexp": "0.1.7", 744 | "proxy-addr": "~2.0.5", 745 | "qs": "6.7.0", 746 | "range-parser": "~1.2.1", 747 | "safe-buffer": "5.1.2", 748 | "send": "0.17.1", 749 | "serve-static": "1.14.1", 750 | "setprototypeof": "1.1.1", 751 | "statuses": "~1.5.0", 752 | "type-is": "~1.6.18", 753 | "utils-merge": "1.0.1", 754 | "vary": "~1.1.2" 755 | } 756 | }, 757 | "file-type": { 758 | "version": "9.0.0", 759 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", 760 | "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" 761 | }, 762 | "finalhandler": { 763 | "version": "1.1.2", 764 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 765 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 766 | "requires": { 767 | "debug": "2.6.9", 768 | "encodeurl": "~1.0.2", 769 | "escape-html": "~1.0.3", 770 | "on-finished": "~2.3.0", 771 | "parseurl": "~1.3.3", 772 | "statuses": "~1.5.0", 773 | "unpipe": "~1.0.0" 774 | } 775 | }, 776 | "forwarded": { 777 | "version": "0.1.2", 778 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 779 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 780 | }, 781 | "fresh": { 782 | "version": "0.5.2", 783 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 784 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 785 | }, 786 | "fs-minipass": { 787 | "version": "1.2.7", 788 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", 789 | "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", 790 | "requires": { 791 | "minipass": "^2.6.0" 792 | } 793 | }, 794 | "fs.realpath": { 795 | "version": "1.0.0", 796 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 797 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 798 | }, 799 | "gauge": { 800 | "version": "2.7.4", 801 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", 802 | "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", 803 | "requires": { 804 | "aproba": "^1.0.3", 805 | "console-control-strings": "^1.0.0", 806 | "has-unicode": "^2.0.0", 807 | "object-assign": "^4.1.0", 808 | "signal-exit": "^3.0.0", 809 | "string-width": "^1.0.1", 810 | "strip-ansi": "^3.0.1", 811 | "wide-align": "^1.1.0" 812 | } 813 | }, 814 | "glob": { 815 | "version": "7.1.6", 816 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 817 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 818 | "requires": { 819 | "fs.realpath": "^1.0.0", 820 | "inflight": "^1.0.4", 821 | "inherits": "2", 822 | "minimatch": "^3.0.4", 823 | "once": "^1.3.0", 824 | "path-is-absolute": "^1.0.0" 825 | } 826 | }, 827 | "global": { 828 | "version": "4.3.2", 829 | "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", 830 | "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", 831 | "requires": { 832 | "min-document": "^2.19.0", 833 | "process": "~0.5.1" 834 | } 835 | }, 836 | "has-unicode": { 837 | "version": "2.0.1", 838 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 839 | "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" 840 | }, 841 | "hoek": { 842 | "version": "6.1.3", 843 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", 844 | "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" 845 | }, 846 | "http-errors": { 847 | "version": "1.7.2", 848 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 849 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 850 | "requires": { 851 | "depd": "~1.1.2", 852 | "inherits": "2.0.3", 853 | "setprototypeof": "1.1.1", 854 | "statuses": ">= 1.5.0 < 2", 855 | "toidentifier": "1.0.0" 856 | } 857 | }, 858 | "iconv-lite": { 859 | "version": "0.4.24", 860 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 861 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 862 | "requires": { 863 | "safer-buffer": ">= 2.1.2 < 3" 864 | } 865 | }, 866 | "ieee754": { 867 | "version": "1.1.13", 868 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 869 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 870 | }, 871 | "ignore-walk": { 872 | "version": "3.0.3", 873 | "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", 874 | "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", 875 | "requires": { 876 | "minimatch": "^3.0.4" 877 | } 878 | }, 879 | "inflight": { 880 | "version": "1.0.6", 881 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 882 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 883 | "requires": { 884 | "once": "^1.3.0", 885 | "wrappy": "1" 886 | } 887 | }, 888 | "inherits": { 889 | "version": "2.0.3", 890 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 891 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 892 | }, 893 | "ini": { 894 | "version": "1.3.5", 895 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 896 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" 897 | }, 898 | "ipaddr.js": { 899 | "version": "1.9.1", 900 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 901 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 902 | }, 903 | "is-fullwidth-code-point": { 904 | "version": "1.0.0", 905 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 906 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 907 | "requires": { 908 | "number-is-nan": "^1.0.0" 909 | } 910 | }, 911 | "is-function": { 912 | "version": "1.0.2", 913 | "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", 914 | "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" 915 | }, 916 | "isarray": { 917 | "version": "0.0.1", 918 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 919 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 920 | }, 921 | "jimp": { 922 | "version": "0.10.3", 923 | "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.10.3.tgz", 924 | "integrity": "sha512-meVWmDMtyUG5uYjFkmzu0zBgnCvvxwWNi27c4cg55vWNVC9ES4Lcwb+ogx+uBBQE3Q+dLKjXaLl0JVW+nUNwbQ==", 925 | "requires": { 926 | "@babel/runtime": "^7.7.2", 927 | "@jimp/custom": "^0.10.3", 928 | "@jimp/plugins": "^0.10.3", 929 | "@jimp/types": "^0.10.3", 930 | "core-js": "^3.4.1", 931 | "regenerator-runtime": "^0.13.3" 932 | } 933 | }, 934 | "jpeg-js": { 935 | "version": "0.3.7", 936 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", 937 | "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" 938 | }, 939 | "jsonwebtoken": { 940 | "version": "8.5.1", 941 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", 942 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", 943 | "requires": { 944 | "jws": "^3.2.2", 945 | "lodash.includes": "^4.3.0", 946 | "lodash.isboolean": "^3.0.3", 947 | "lodash.isinteger": "^4.0.4", 948 | "lodash.isnumber": "^3.0.3", 949 | "lodash.isplainobject": "^4.0.6", 950 | "lodash.isstring": "^4.0.1", 951 | "lodash.once": "^4.0.0", 952 | "ms": "^2.1.1", 953 | "semver": "^5.6.0" 954 | }, 955 | "dependencies": { 956 | "ms": { 957 | "version": "2.1.2", 958 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 959 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 960 | } 961 | } 962 | }, 963 | "jwa": { 964 | "version": "1.4.1", 965 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 966 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 967 | "requires": { 968 | "buffer-equal-constant-time": "1.0.1", 969 | "ecdsa-sig-formatter": "1.0.11", 970 | "safe-buffer": "^5.0.1" 971 | } 972 | }, 973 | "jws": { 974 | "version": "3.2.2", 975 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 976 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 977 | "requires": { 978 | "jwa": "^1.4.1", 979 | "safe-buffer": "^5.0.1" 980 | } 981 | }, 982 | "load-bmfont": { 983 | "version": "1.4.1", 984 | "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", 985 | "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", 986 | "requires": { 987 | "buffer-equal": "0.0.1", 988 | "mime": "^1.3.4", 989 | "parse-bmfont-ascii": "^1.0.3", 990 | "parse-bmfont-binary": "^1.0.5", 991 | "parse-bmfont-xml": "^1.1.4", 992 | "phin": "^2.9.1", 993 | "xhr": "^2.0.1", 994 | "xtend": "^4.0.0" 995 | } 996 | }, 997 | "lodash.includes": { 998 | "version": "4.3.0", 999 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 1000 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" 1001 | }, 1002 | "lodash.isboolean": { 1003 | "version": "3.0.3", 1004 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 1005 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" 1006 | }, 1007 | "lodash.isinteger": { 1008 | "version": "4.0.4", 1009 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 1010 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" 1011 | }, 1012 | "lodash.isnumber": { 1013 | "version": "3.0.3", 1014 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 1015 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" 1016 | }, 1017 | "lodash.isplainobject": { 1018 | "version": "4.0.6", 1019 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 1020 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" 1021 | }, 1022 | "lodash.isstring": { 1023 | "version": "4.0.1", 1024 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 1025 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" 1026 | }, 1027 | "lodash.once": { 1028 | "version": "4.1.1", 1029 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 1030 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" 1031 | }, 1032 | "media-typer": { 1033 | "version": "0.3.0", 1034 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1035 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1036 | }, 1037 | "merge-descriptors": { 1038 | "version": "1.0.1", 1039 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1040 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1041 | }, 1042 | "methods": { 1043 | "version": "1.1.2", 1044 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1045 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1046 | }, 1047 | "mime": { 1048 | "version": "1.6.0", 1049 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1050 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1051 | }, 1052 | "mime-db": { 1053 | "version": "1.44.0", 1054 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 1055 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 1056 | }, 1057 | "mime-types": { 1058 | "version": "2.1.27", 1059 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 1060 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 1061 | "requires": { 1062 | "mime-db": "1.44.0" 1063 | } 1064 | }, 1065 | "min-document": { 1066 | "version": "2.19.0", 1067 | "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", 1068 | "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", 1069 | "requires": { 1070 | "dom-walk": "^0.1.0" 1071 | } 1072 | }, 1073 | "minimatch": { 1074 | "version": "3.0.4", 1075 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1076 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1077 | "requires": { 1078 | "brace-expansion": "^1.1.7" 1079 | } 1080 | }, 1081 | "minimist": { 1082 | "version": "1.2.5", 1083 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1084 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 1085 | }, 1086 | "minipass": { 1087 | "version": "2.9.0", 1088 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", 1089 | "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", 1090 | "requires": { 1091 | "safe-buffer": "^5.1.2", 1092 | "yallist": "^3.0.0" 1093 | } 1094 | }, 1095 | "minizlib": { 1096 | "version": "1.3.3", 1097 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", 1098 | "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", 1099 | "requires": { 1100 | "minipass": "^2.9.0" 1101 | } 1102 | }, 1103 | "mkdirp": { 1104 | "version": "0.5.5", 1105 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1106 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1107 | "requires": { 1108 | "minimist": "^1.2.5" 1109 | } 1110 | }, 1111 | "ms": { 1112 | "version": "2.0.0", 1113 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1114 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1115 | }, 1116 | "multer": { 1117 | "version": "1.4.2", 1118 | "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", 1119 | "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", 1120 | "requires": { 1121 | "append-field": "^1.0.0", 1122 | "busboy": "^0.2.11", 1123 | "concat-stream": "^1.5.2", 1124 | "mkdirp": "^0.5.1", 1125 | "object-assign": "^4.1.1", 1126 | "on-finished": "^2.3.0", 1127 | "type-is": "^1.6.4", 1128 | "xtend": "^4.0.0" 1129 | } 1130 | }, 1131 | "nan": { 1132 | "version": "2.14.1", 1133 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", 1134 | "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" 1135 | }, 1136 | "needle": { 1137 | "version": "2.5.0", 1138 | "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz", 1139 | "integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==", 1140 | "requires": { 1141 | "debug": "^3.2.6", 1142 | "iconv-lite": "^0.4.4", 1143 | "sax": "^1.2.4" 1144 | }, 1145 | "dependencies": { 1146 | "debug": { 1147 | "version": "3.2.6", 1148 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 1149 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 1150 | "requires": { 1151 | "ms": "^2.1.1" 1152 | } 1153 | }, 1154 | "ms": { 1155 | "version": "2.1.2", 1156 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1157 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1158 | } 1159 | } 1160 | }, 1161 | "negotiator": { 1162 | "version": "0.6.2", 1163 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1164 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 1165 | }, 1166 | "node-pre-gyp": { 1167 | "version": "0.11.0", 1168 | "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", 1169 | "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", 1170 | "requires": { 1171 | "detect-libc": "^1.0.2", 1172 | "mkdirp": "^0.5.1", 1173 | "needle": "^2.2.1", 1174 | "nopt": "^4.0.1", 1175 | "npm-packlist": "^1.1.6", 1176 | "npmlog": "^4.0.2", 1177 | "rc": "^1.2.7", 1178 | "rimraf": "^2.6.1", 1179 | "semver": "^5.3.0", 1180 | "tar": "^4" 1181 | } 1182 | }, 1183 | "nopt": { 1184 | "version": "4.0.3", 1185 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", 1186 | "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", 1187 | "requires": { 1188 | "abbrev": "1", 1189 | "osenv": "^0.1.4" 1190 | } 1191 | }, 1192 | "npm-bundled": { 1193 | "version": "1.1.1", 1194 | "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", 1195 | "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", 1196 | "requires": { 1197 | "npm-normalize-package-bin": "^1.0.1" 1198 | } 1199 | }, 1200 | "npm-normalize-package-bin": { 1201 | "version": "1.0.1", 1202 | "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", 1203 | "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" 1204 | }, 1205 | "npm-packlist": { 1206 | "version": "1.4.8", 1207 | "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", 1208 | "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", 1209 | "requires": { 1210 | "ignore-walk": "^3.0.1", 1211 | "npm-bundled": "^1.0.1", 1212 | "npm-normalize-package-bin": "^1.0.1" 1213 | } 1214 | }, 1215 | "npmlog": { 1216 | "version": "4.1.2", 1217 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", 1218 | "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", 1219 | "requires": { 1220 | "are-we-there-yet": "~1.1.2", 1221 | "console-control-strings": "~1.1.0", 1222 | "gauge": "~2.7.3", 1223 | "set-blocking": "~2.0.0" 1224 | } 1225 | }, 1226 | "number-is-nan": { 1227 | "version": "1.0.1", 1228 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1229 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 1230 | }, 1231 | "object-assign": { 1232 | "version": "4.1.1", 1233 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1234 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1235 | }, 1236 | "omggif": { 1237 | "version": "1.0.10", 1238 | "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", 1239 | "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" 1240 | }, 1241 | "on-finished": { 1242 | "version": "2.3.0", 1243 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1244 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1245 | "requires": { 1246 | "ee-first": "1.1.1" 1247 | } 1248 | }, 1249 | "once": { 1250 | "version": "1.4.0", 1251 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1252 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1253 | "requires": { 1254 | "wrappy": "1" 1255 | } 1256 | }, 1257 | "os-homedir": { 1258 | "version": "1.0.2", 1259 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 1260 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" 1261 | }, 1262 | "os-tmpdir": { 1263 | "version": "1.0.2", 1264 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1265 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 1266 | }, 1267 | "osenv": { 1268 | "version": "0.1.5", 1269 | "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", 1270 | "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", 1271 | "requires": { 1272 | "os-homedir": "^1.0.0", 1273 | "os-tmpdir": "^1.0.0" 1274 | } 1275 | }, 1276 | "pako": { 1277 | "version": "1.0.11", 1278 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 1279 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" 1280 | }, 1281 | "parse-bmfont-ascii": { 1282 | "version": "1.0.6", 1283 | "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", 1284 | "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" 1285 | }, 1286 | "parse-bmfont-binary": { 1287 | "version": "1.0.6", 1288 | "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", 1289 | "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" 1290 | }, 1291 | "parse-bmfont-xml": { 1292 | "version": "1.1.4", 1293 | "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", 1294 | "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", 1295 | "requires": { 1296 | "xml-parse-from-string": "^1.0.0", 1297 | "xml2js": "^0.4.5" 1298 | } 1299 | }, 1300 | "parse-headers": { 1301 | "version": "2.0.3", 1302 | "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", 1303 | "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" 1304 | }, 1305 | "parseurl": { 1306 | "version": "1.3.3", 1307 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1308 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1309 | }, 1310 | "path-is-absolute": { 1311 | "version": "1.0.1", 1312 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1313 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1314 | }, 1315 | "path-to-regexp": { 1316 | "version": "0.1.7", 1317 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1318 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1319 | }, 1320 | "phin": { 1321 | "version": "2.9.3", 1322 | "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", 1323 | "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" 1324 | }, 1325 | "pixelmatch": { 1326 | "version": "4.0.2", 1327 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", 1328 | "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", 1329 | "requires": { 1330 | "pngjs": "^3.0.0" 1331 | } 1332 | }, 1333 | "pngjs": { 1334 | "version": "3.4.0", 1335 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", 1336 | "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" 1337 | }, 1338 | "process": { 1339 | "version": "0.5.2", 1340 | "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", 1341 | "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" 1342 | }, 1343 | "process-nextick-args": { 1344 | "version": "2.0.1", 1345 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1346 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1347 | }, 1348 | "proxy-addr": { 1349 | "version": "2.0.6", 1350 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 1351 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 1352 | "requires": { 1353 | "forwarded": "~0.1.2", 1354 | "ipaddr.js": "1.9.1" 1355 | } 1356 | }, 1357 | "qs": { 1358 | "version": "6.7.0", 1359 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1360 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 1361 | }, 1362 | "range-parser": { 1363 | "version": "1.2.1", 1364 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1365 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1366 | }, 1367 | "raw-body": { 1368 | "version": "2.4.0", 1369 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1370 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1371 | "requires": { 1372 | "bytes": "3.1.0", 1373 | "http-errors": "1.7.2", 1374 | "iconv-lite": "0.4.24", 1375 | "unpipe": "1.0.0" 1376 | } 1377 | }, 1378 | "rc": { 1379 | "version": "1.2.8", 1380 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 1381 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 1382 | "requires": { 1383 | "deep-extend": "^0.6.0", 1384 | "ini": "~1.3.0", 1385 | "minimist": "^1.2.0", 1386 | "strip-json-comments": "~2.0.1" 1387 | } 1388 | }, 1389 | "readable-stream": { 1390 | "version": "1.1.14", 1391 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 1392 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 1393 | "requires": { 1394 | "core-util-is": "~1.0.0", 1395 | "inherits": "~2.0.1", 1396 | "isarray": "0.0.1", 1397 | "string_decoder": "~0.10.x" 1398 | } 1399 | }, 1400 | "regenerator-runtime": { 1401 | "version": "0.13.7", 1402 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", 1403 | "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" 1404 | }, 1405 | "rimraf": { 1406 | "version": "2.7.1", 1407 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 1408 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 1409 | "requires": { 1410 | "glob": "^7.1.3" 1411 | } 1412 | }, 1413 | "safe-buffer": { 1414 | "version": "5.1.2", 1415 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1416 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1417 | }, 1418 | "safer-buffer": { 1419 | "version": "2.1.2", 1420 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1421 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1422 | }, 1423 | "sax": { 1424 | "version": "1.2.4", 1425 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1426 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1427 | }, 1428 | "semver": { 1429 | "version": "5.7.1", 1430 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1431 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 1432 | }, 1433 | "send": { 1434 | "version": "0.17.1", 1435 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1436 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1437 | "requires": { 1438 | "debug": "2.6.9", 1439 | "depd": "~1.1.2", 1440 | "destroy": "~1.0.4", 1441 | "encodeurl": "~1.0.2", 1442 | "escape-html": "~1.0.3", 1443 | "etag": "~1.8.1", 1444 | "fresh": "0.5.2", 1445 | "http-errors": "~1.7.2", 1446 | "mime": "1.6.0", 1447 | "ms": "2.1.1", 1448 | "on-finished": "~2.3.0", 1449 | "range-parser": "~1.2.1", 1450 | "statuses": "~1.5.0" 1451 | }, 1452 | "dependencies": { 1453 | "ms": { 1454 | "version": "2.1.1", 1455 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1456 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1457 | } 1458 | } 1459 | }, 1460 | "serve-static": { 1461 | "version": "1.14.1", 1462 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1463 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1464 | "requires": { 1465 | "encodeurl": "~1.0.2", 1466 | "escape-html": "~1.0.3", 1467 | "parseurl": "~1.3.3", 1468 | "send": "0.17.1" 1469 | } 1470 | }, 1471 | "set-blocking": { 1472 | "version": "2.0.0", 1473 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1474 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 1475 | }, 1476 | "setprototypeof": { 1477 | "version": "1.1.1", 1478 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1479 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1480 | }, 1481 | "signal-exit": { 1482 | "version": "3.0.3", 1483 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 1484 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" 1485 | }, 1486 | "sqlite3": { 1487 | "version": "4.2.0", 1488 | "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", 1489 | "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", 1490 | "requires": { 1491 | "nan": "^2.12.1", 1492 | "node-pre-gyp": "^0.11.0" 1493 | } 1494 | }, 1495 | "statuses": { 1496 | "version": "1.5.0", 1497 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1498 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1499 | }, 1500 | "streamsearch": { 1501 | "version": "0.1.2", 1502 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 1503 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" 1504 | }, 1505 | "string-width": { 1506 | "version": "1.0.2", 1507 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1508 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1509 | "requires": { 1510 | "code-point-at": "^1.0.0", 1511 | "is-fullwidth-code-point": "^1.0.0", 1512 | "strip-ansi": "^3.0.0" 1513 | } 1514 | }, 1515 | "string_decoder": { 1516 | "version": "0.10.31", 1517 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1518 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 1519 | }, 1520 | "strip-ansi": { 1521 | "version": "3.0.1", 1522 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1523 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1524 | "requires": { 1525 | "ansi-regex": "^2.0.0" 1526 | } 1527 | }, 1528 | "strip-json-comments": { 1529 | "version": "2.0.1", 1530 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1531 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" 1532 | }, 1533 | "tar": { 1534 | "version": "4.4.13", 1535 | "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", 1536 | "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", 1537 | "requires": { 1538 | "chownr": "^1.1.1", 1539 | "fs-minipass": "^1.2.5", 1540 | "minipass": "^2.8.6", 1541 | "minizlib": "^1.2.1", 1542 | "mkdirp": "^0.5.0", 1543 | "safe-buffer": "^5.1.2", 1544 | "yallist": "^3.0.3" 1545 | } 1546 | }, 1547 | "timm": { 1548 | "version": "1.6.2", 1549 | "resolved": "https://registry.npmjs.org/timm/-/timm-1.6.2.tgz", 1550 | "integrity": "sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw==" 1551 | }, 1552 | "tinycolor2": { 1553 | "version": "1.4.1", 1554 | "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", 1555 | "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" 1556 | }, 1557 | "toidentifier": { 1558 | "version": "1.0.0", 1559 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1560 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1561 | }, 1562 | "type-is": { 1563 | "version": "1.6.18", 1564 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1565 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1566 | "requires": { 1567 | "media-typer": "0.3.0", 1568 | "mime-types": "~2.1.24" 1569 | } 1570 | }, 1571 | "typedarray": { 1572 | "version": "0.0.6", 1573 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1574 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" 1575 | }, 1576 | "unpipe": { 1577 | "version": "1.0.0", 1578 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1579 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1580 | }, 1581 | "utif": { 1582 | "version": "2.0.1", 1583 | "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", 1584 | "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", 1585 | "requires": { 1586 | "pako": "^1.0.5" 1587 | } 1588 | }, 1589 | "util-deprecate": { 1590 | "version": "1.0.2", 1591 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1592 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1593 | }, 1594 | "utils-merge": { 1595 | "version": "1.0.1", 1596 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1597 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1598 | }, 1599 | "uuid": { 1600 | "version": "8.3.0", 1601 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", 1602 | "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" 1603 | }, 1604 | "vary": { 1605 | "version": "1.1.2", 1606 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1607 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1608 | }, 1609 | "wide-align": { 1610 | "version": "1.1.3", 1611 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1612 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1613 | "requires": { 1614 | "string-width": "^1.0.2 || 2" 1615 | } 1616 | }, 1617 | "wrappy": { 1618 | "version": "1.0.2", 1619 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1620 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1621 | }, 1622 | "xhr": { 1623 | "version": "2.5.0", 1624 | "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", 1625 | "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", 1626 | "requires": { 1627 | "global": "~4.3.0", 1628 | "is-function": "^1.0.1", 1629 | "parse-headers": "^2.0.0", 1630 | "xtend": "^4.0.0" 1631 | } 1632 | }, 1633 | "xml-parse-from-string": { 1634 | "version": "1.0.1", 1635 | "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", 1636 | "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" 1637 | }, 1638 | "xml2js": { 1639 | "version": "0.4.23", 1640 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 1641 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 1642 | "requires": { 1643 | "sax": ">=0.6.0", 1644 | "xmlbuilder": "~11.0.0" 1645 | } 1646 | }, 1647 | "xmlbuilder": { 1648 | "version": "11.0.1", 1649 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 1650 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 1651 | }, 1652 | "xtend": { 1653 | "version": "4.0.2", 1654 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1655 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1656 | }, 1657 | "yallist": { 1658 | "version": "3.1.1", 1659 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 1660 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 1661 | } 1662 | } 1663 | } 1664 | -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bytebankbroker", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.19.0", 14 | "cors": "^2.8.5", 15 | "cryptiles": "^4.1.3", 16 | "express": "^4.17.1", 17 | "jimp": "^0.10.3", 18 | "jsonwebtoken": "^8.5.1", 19 | "multer": "^1.4.2", 20 | "sqlite3": "^4.2.0", 21 | "uuid": "^8.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /api/server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | const app = require("./config/express"); 3 | 4 | http.createServer(app).listen(3000, function () { 5 | console.log("Servidor escutando na porta: " + this.address().port); 6 | }); 7 | -------------------------------------------------------------------------------- /byte-bank-broker/.angulardoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "repoId": "d7a4d2c9-d38d-4175-8e5f-774ae9829293", 3 | "lastSync": 0 4 | } -------------------------------------------------------------------------------- /byte-bank-broker/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /byte-bank-broker/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /byte-bank-broker/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /byte-bank-broker/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#2f7c47", 4 | "activityBar.activeBorder": "#422c74", 5 | "activityBar.background": "#2f7c47", 6 | "activityBar.foreground": "#e7e7e7", 7 | "activityBar.inactiveForeground": "#e7e7e799", 8 | "activityBarBadge.background": "#422c74", 9 | "activityBarBadge.foreground": "#e7e7e7", 10 | "statusBar.background": "#215732", 11 | "statusBar.foreground": "#e7e7e7", 12 | "statusBarItem.hoverBackground": "#2f7c47", 13 | "titleBar.activeBackground": "#215732", 14 | "titleBar.activeForeground": "#e7e7e7", 15 | "titleBar.inactiveBackground": "#21573299", 16 | "titleBar.inactiveForeground": "#e7e7e799" 17 | }, 18 | "peacock.color": "#215732" 19 | } -------------------------------------------------------------------------------- /byte-bank-broker/README.md: -------------------------------------------------------------------------------- 1 | # ByteBankBroker 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.4. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /byte-bank-broker/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "byte-bank-broker": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "outputPath": "dist/byte-bank-broker", 17 | "index": "src/index.html", 18 | "main": "src/main.ts", 19 | "polyfills": "src/polyfills.ts", 20 | "tsConfig": "tsconfig.app.json", 21 | "aot": true, 22 | "assets": [ 23 | "src/favicon.ico", 24 | "src/assets", 25 | { 26 | "glob": "**/*", 27 | "input": "node_modules/@po-ui/style/images", 28 | "output": "assets/images" 29 | } 30 | ], 31 | "styles": [ 32 | "./node_modules/@po-ui/style/css/po-theme-default.min.css", 33 | "./node_modules/@po-ui/style/css/po-theme-default-variables.min.css", 34 | "./node_modules/byte-bank-theme/css/po-theme-custom-variables.min.css", 35 | "./node_modules/@po-ui/style/css/po-theme-core.min.css", 36 | "src/styles.css" 37 | ], 38 | "scripts": [] 39 | }, 40 | "configurations": { 41 | "production": { 42 | "fileReplacements": [ 43 | { 44 | "replace": "src/environments/environment.ts", 45 | "with": "src/environments/environment.prod.ts" 46 | } 47 | ], 48 | "optimization": true, 49 | "outputHashing": "all", 50 | "sourceMap": false, 51 | "extractCss": true, 52 | "namedChunks": false, 53 | "extractLicenses": true, 54 | "vendorChunk": false, 55 | "buildOptimizer": true, 56 | "budgets": [ 57 | { 58 | "type": "initial", 59 | "maximumWarning": "2mb", 60 | "maximumError": "5mb" 61 | }, 62 | { 63 | "type": "anyComponentStyle", 64 | "maximumWarning": "6kb", 65 | "maximumError": "10kb" 66 | } 67 | ] 68 | } 69 | } 70 | }, 71 | "serve": { 72 | "builder": "@angular-devkit/build-angular:dev-server", 73 | "options": { 74 | "browserTarget": "byte-bank-broker:build" 75 | }, 76 | "configurations": { 77 | "production": { 78 | "browserTarget": "byte-bank-broker:build:production" 79 | } 80 | } 81 | }, 82 | "extract-i18n": { 83 | "builder": "@angular-devkit/build-angular:extract-i18n", 84 | "options": { 85 | "browserTarget": "byte-bank-broker:build" 86 | } 87 | }, 88 | "test": { 89 | "builder": "@angular-devkit/build-angular:karma", 90 | "options": { 91 | "main": "src/test.ts", 92 | "polyfills": "src/polyfills.ts", 93 | "tsConfig": "tsconfig.spec.json", 94 | "karmaConfig": "karma.conf.js", 95 | "assets": [ 96 | "src/favicon.ico", 97 | "src/assets" 98 | ], 99 | "styles": [ 100 | "./node_modules/@po-ui/style/css/po-theme-default.min.css", 101 | "./node_modules/@po-ui/style/css/po-theme-default-variables.min.css", 102 | "./node_modules/byte-bank-theme/css/po-theme-custom-variables.min.css", 103 | "./node_modules/@po-ui/style/css/po-theme-core.min.css", 104 | "src/styles.css" 105 | ], 106 | "scripts": [] 107 | } 108 | }, 109 | "lint": { 110 | "builder": "@angular-devkit/build-angular:tslint", 111 | "options": { 112 | "tsConfig": [ 113 | "tsconfig.app.json", 114 | "tsconfig.spec.json", 115 | "e2e/tsconfig.json" 116 | ], 117 | "exclude": [ 118 | "**/node_modules/**" 119 | ] 120 | } 121 | }, 122 | "e2e": { 123 | "builder": "@angular-devkit/build-angular:protractor", 124 | "options": { 125 | "protractorConfig": "e2e/protractor.conf.js", 126 | "devServerTarget": "byte-bank-broker:serve" 127 | }, 128 | "configurations": { 129 | "production": { 130 | "devServerTarget": "byte-bank-broker:serve:production" 131 | } 132 | } 133 | } 134 | } 135 | } 136 | }, 137 | "defaultProject": "byte-bank-broker", 138 | "cli": { 139 | "analytics": "474b4f10-10d8-4bcb-80c4-715fac42bcf5" 140 | } 141 | } -------------------------------------------------------------------------------- /byte-bank-broker/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4200/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 31 | } 32 | }; -------------------------------------------------------------------------------- /byte-bank-broker/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('byte-bank-broker app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /byte-bank-broker/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo(): Promise { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /byte-bank-broker/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es2018", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /byte-bank-broker/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, './coverage/byte-bank-broker'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /byte-bank-broker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "byte-bank-broker", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "~10.0.7", 15 | "@angular/common": "~10.0.7", 16 | "@angular/compiler": "~10.0.7", 17 | "@angular/core": "~10.0.7", 18 | "@angular/forms": "~10.0.7", 19 | "@angular/platform-browser": "~10.0.7", 20 | "@angular/platform-browser-dynamic": "~10.0.7", 21 | "@angular/router": "~10.0.7", 22 | "@po-ui/ng-components": "3.0.0", 23 | "@po-ui/ng-templates": "3.0.0", 24 | "byte-bank-theme": "^1.0.0", 25 | "rxjs": "~6.5.4", 26 | "tslib": "^2.0.0", 27 | "zone.js": "~0.10.2" 28 | }, 29 | "devDependencies": { 30 | "@angular-devkit/build-angular": "~0.1000.5", 31 | "@angular/cli": "~10.0.5", 32 | "@angular/compiler-cli": "~10.0.7", 33 | "@angular/language-service": "~10.0.7", 34 | "@types/jasmine": "~3.5.0", 35 | "@types/jasminewd2": "~2.0.3", 36 | "@types/node": "^12.11.1", 37 | "codelyzer": "^6.0.0", 38 | "jasmine-core": "~3.5.0", 39 | "jasmine-spec-reporter": "~5.0.0", 40 | "karma": "~5.0.0", 41 | "karma-chrome-launcher": "~3.1.0", 42 | "karma-coverage-istanbul-reporter": "~3.0.2", 43 | "karma-jasmine": "~3.3.0", 44 | "karma-jasmine-html-reporter": "^1.5.0", 45 | "protractor": "~7.0.0", 46 | "ts-node": "~8.3.0", 47 | "tslint": "~6.1.0", 48 | "typescript": "~3.9.7" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/acoes-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { AcoesComponent } from './acoes.component'; 4 | 5 | export const routes: Routes = [ 6 | { 7 | path: '', 8 | component: AcoesComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class AcoesRoutingModule {} 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/acoes.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/app/acoes/acoes.component.css -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/acoes.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 |
7 |
8 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/acoes.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AcoesComponent } from './acoes.component'; 4 | 5 | describe('StockComponent', () => { 6 | let component: AcoesComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AcoesComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AcoesComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/acoes.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormControl } from '@angular/forms'; 3 | 4 | @Component({ 5 | selector: 'app-acoes', 6 | templateUrl: './acoes.component.html', 7 | styleUrls: ['./acoes.component.css'], 8 | }) 9 | export class AcoesComponent { 10 | acoesInput = new FormControl(); 11 | 12 | constructor() {} 13 | } 14 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/acoes.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { AcoesRoutingModule } from './acoes-routing.module'; 5 | import { AcoesComponent } from './acoes.component'; 6 | import { SharedModule } from '../shared/shared.module'; 7 | import { CardAcoesComponent } from './card-acoes/card-acoes.component'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [AcoesComponent, CardAcoesComponent], 12 | imports: [ 13 | CommonModule, 14 | AcoesRoutingModule, 15 | SharedModule 16 | ] 17 | }) 18 | export class AcoesModule { } 19 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/card-acoes/card-acoes.component.css: -------------------------------------------------------------------------------- 1 | app-card-acoes .po-widget { 2 | margin: 0 10px 10px 0; 3 | } 4 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/card-acoes/card-acoes.component.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/card-acoes/card-acoes.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CardAcoesComponent } from './card-acoes.component'; 4 | 5 | describe('StockCardComponent', () => { 6 | let component: CardAcoesComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ CardAcoesComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CardAcoesComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/acoes/card-acoes/card-acoes.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-card-acoes', 5 | templateUrl: './card-acoes.component.html', 6 | styleUrls: ['./card-acoes.component.css'], 7 | encapsulation: ViewEncapsulation.None, 8 | }) 9 | export class CardAcoesComponent implements OnInit { 10 | @Input() acao: any; 11 | 12 | constructor() {} 13 | 14 | ngOnInit(): void {} 15 | } 16 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { AuthorizationGuard } from './authorization/authorization.guard'; 4 | 5 | export const routes: Routes = [ 6 | { path: '', pathMatch: 'full', redirectTo: 'home' }, 7 | { 8 | path: 'home', 9 | loadChildren: () => 10 | import('../app/home/home.module').then((m) => m.HomeModule), 11 | canLoad: [AuthorizationGuard], 12 | }, 13 | { 14 | path: 'login', 15 | loadChildren: () => 16 | import('../app/login/login.module').then((m) => m.LoginModule), 17 | }, 18 | { path: '**', redirectTo: '', pathMatch: 'full' }, 19 | ]; 20 | 21 | @NgModule({ 22 | imports: [RouterModule.forRoot(routes)], 23 | exports: [RouterModule], 24 | }) 25 | export class AppRoutingModule {} 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/app/app.component.css -------------------------------------------------------------------------------- /byte-bank-broker/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | 4 | import { PoMenuModule, PoPageModule, PoToolbarModule } from '@po-ui/ng-components'; 5 | 6 | import { AppComponent } from './app.component'; 7 | 8 | describe('AppComponent', () => { 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | imports: [ 12 | PoMenuModule, 13 | PoPageModule, 14 | PoToolbarModule, 15 | RouterTestingModule 16 | ], 17 | declarations: [ 18 | AppComponent 19 | ], 20 | }).compileComponents(); 21 | })); 22 | 23 | it('should create the app', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.debugElement.componentInstance; 26 | 27 | expect(app).toBeTruthy(); 28 | }); 29 | 30 | }); 31 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { Title } from '@angular/platform-browser'; 4 | import { environment } from 'src/environments/environment'; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.css'], 10 | }) 11 | export class AppComponent implements OnInit { 12 | title: string; 13 | constructor(private titleService: Title) {} 14 | 15 | ngOnInit(): void { 16 | this.title = environment.name; 17 | this.titleService.setTitle(this.title); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { AppRoutingModule } from './app-routing.module'; 4 | import { AppComponent } from './app.component'; 5 | import { RouterModule } from '@angular/router'; 6 | import { CoreModule } from './core/core.module'; 7 | 8 | @NgModule({ 9 | declarations: [AppComponent], 10 | imports: [CoreModule, AppRoutingModule, RouterModule.forRoot([])], 11 | providers: [], 12 | bootstrap: [AppComponent], 13 | }) 14 | export class AppModule {} 15 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AuthorizationGuard } from './authorization.guard'; 4 | 5 | describe('AuthorizationGuard', () => { 6 | let guard: AuthorizationGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(AuthorizationGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { 3 | ActivatedRouteSnapshot, 4 | CanActivate, 5 | CanActivateChild, 6 | CanLoad, 7 | Route, 8 | Router, 9 | RouterStateSnapshot, 10 | } from '@angular/router'; 11 | import { Observable } from 'rxjs'; 12 | import { AuthorizationService } from './authorization.service'; 13 | 14 | type canActivateReturn = Observable | Promise | boolean; 15 | 16 | @Injectable({ 17 | providedIn: 'root', 18 | }) 19 | export class AuthorizationGuard 20 | implements CanActivate, CanActivateChild, CanLoad { 21 | constructor( 22 | private authService: AuthorizationService, 23 | private router: Router 24 | ) {} 25 | 26 | canActivate( 27 | next: ActivatedRouteSnapshot, 28 | state: RouterStateSnapshot 29 | ): canActivateReturn { 30 | const url: string = state.url; 31 | return this.checkLogin(url); 32 | } 33 | 34 | checkLogin(url: string): canActivateReturn { 35 | if (this.authService.isUserAuthenticated()) { 36 | return true; 37 | } 38 | this.authService.redirectUrl = url; 39 | this.router.navigate(['/login']); 40 | return false; 41 | } 42 | 43 | canActivateChild( 44 | route: ActivatedRouteSnapshot, 45 | state: RouterStateSnapshot 46 | ): canActivateReturn { 47 | return this.canActivate(route, state); 48 | } 49 | 50 | canLoad(route: Route): canActivateReturn { 51 | const url = `/${route.path}`; 52 | return this.checkLogin(url); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.interceptor.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AuthorizationInteceptor } from './authorization.interceptor'; 3 | 4 | describe('AuthorizationInterceptor', () => { 5 | beforeEach(() => 6 | TestBed.configureTestingModule({ 7 | providers: [AuthorizationInteceptor], 8 | }) 9 | ); 10 | 11 | it('should be created', () => { 12 | const interceptor: AuthorizationInteceptor = TestBed.inject( 13 | AuthorizationInteceptor 14 | ); 15 | expect(interceptor).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HttpEvent, 3 | HttpHandler, 4 | HttpInterceptor, 5 | HttpRequest, 6 | } from '@angular/common/http'; 7 | import { Injectable, Injector, Type } from '@angular/core'; 8 | import { Observable } from 'rxjs'; 9 | import { AuthorizationService } from './authorization.service'; 10 | 11 | /** 12 | * @description 13 | * 14 | * Interceptor que pega a requisição html e insere no header o token. 15 | */ 16 | 17 | @Injectable({ 18 | providedIn: 'root', 19 | }) 20 | export class AuthorizationInteceptor implements HttpInterceptor { 21 | constructor(private injector: Injector) {} 22 | 23 | intercept( 24 | original_request: HttpRequest, 25 | next: HttpHandler 26 | ): Observable> { 27 | let requestResult: HttpRequest; 28 | if (this.isUrlNeedsProAuth(original_request.url)) { 29 | requestResult = this.appendTokenToRequest(original_request); 30 | } else { 31 | requestResult = original_request.clone(); 32 | } 33 | return next.handle(requestResult); 34 | } 35 | 36 | appendTokenToRequest(request: HttpRequest): HttpRequest { 37 | const authService: AuthorizationService = this.injector.get< 38 | AuthorizationService 39 | >(AuthorizationService as Type); 40 | const token = authService.getAuthenticatedUser().token; 41 | return request.clone({ 42 | headers: request.headers.set('x-access-token', token), 43 | }); 44 | } 45 | 46 | isUrlNeedsProAuth(url: string): boolean { 47 | let needProAuth = true; 48 | const whiteList = [/login/, /assets/]; 49 | 50 | for (const whiteUrl of whiteList) { 51 | if (url.search(whiteUrl) >= 0) { 52 | needProAuth = false; 53 | break; 54 | } 55 | } 56 | return needProAuth; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { HTTP_INTERCEPTORS } from '@angular/common/http'; 4 | import { AuthorizationInteceptor } from './authorization.interceptor'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule], 8 | providers: [ 9 | { 10 | provide: HTTP_INTERCEPTORS, 11 | useClass: AuthorizationInteceptor, 12 | multi: true, 13 | }, 14 | ], 15 | }) 16 | export class AuthorizationModule {} 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AuthorizationService } from './authorization.service'; 4 | 5 | describe('AuthorizationService', () => { 6 | let service: AuthorizationService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(AuthorizationService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/authorization.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient, HttpResponse } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable, Subject } from 'rxjs'; 4 | import { User } from './model/user'; 5 | import { UserLogin } from './model/user-login'; 6 | import { environment } from 'src/environments/environment'; 7 | 8 | 9 | const CACHE_KEY_TOKEN = 'TOKEN'; 10 | const TOKEN_ENDPOINT = `${environment.api}/user/login`; 11 | 12 | @Injectable({ 13 | providedIn: 'root', 14 | }) 15 | export class AuthorizationService { 16 | public redirectUrl: string; 17 | private _user: User; 18 | 19 | constructor(private http: HttpClient) {} 20 | 21 | requestToken(user: UserLogin): Observable> { 22 | return this.http.post( 23 | TOKEN_ENDPOINT, 24 | { 25 | userName: user.userName, 26 | password: user.password, 27 | }, 28 | { observe: 'response' } 29 | ); 30 | } 31 | 32 | login(user: UserLogin): Observable { 33 | const loginSubject = new Subject(); 34 | this.requestToken(user).subscribe( 35 | (response: HttpResponse) => { 36 | const { body: loggedUser } = response; 37 | loggedUser.token = response.headers.get('x-access-token'); 38 | this.saveUserInfo(loggedUser); 39 | loginSubject.next(loggedUser); 40 | }, 41 | (error) => { 42 | loginSubject.error(error); 43 | } 44 | ); 45 | return loginSubject.asObservable(); 46 | } 47 | 48 | saveUserInfo(user: User) { 49 | this._user = user; 50 | this.setUser(this._user); 51 | } 52 | 53 | /** 54 | * Efetua o logout do usuário autenticado. 55 | */ 56 | logout(): void { 57 | this._user = undefined; 58 | this.removeUser(); 59 | } 60 | 61 | private setUser(user: User): void { 62 | sessionStorage.setItem(CACHE_KEY_TOKEN, JSON.stringify(user)); 63 | } 64 | 65 | private removeUser(): void { 66 | sessionStorage.removeItem(CACHE_KEY_TOKEN); 67 | } 68 | 69 | getAuthenticatedUser(): User { 70 | return this._user || JSON.parse(sessionStorage.getItem(CACHE_KEY_TOKEN)); 71 | } 72 | 73 | isUserAuthenticated(): boolean { 74 | return this.getAuthenticatedUser() !== null; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/model/user-login.ts: -------------------------------------------------------------------------------- 1 | export interface UserLogin { 2 | userName: string; 3 | password: string; 4 | remindUser: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/authorization/model/user.ts: -------------------------------------------------------------------------------- 1 | export interface User { 2 | id: string; 3 | name: string; 4 | email: string; 5 | token: string; 6 | expire?: Date; 7 | } 8 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { HttpClientModule } from '@angular/common/http'; 4 | import { BrowserModule } from '@angular/platform-browser'; 5 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 6 | 7 | @NgModule({ 8 | declarations: [], 9 | imports: [ 10 | CommonModule, 11 | HttpClientModule, 12 | BrowserModule, 13 | BrowserAnimationsModule, 14 | ], 15 | exports: [ 16 | HttpClientModule, 17 | BrowserModule, 18 | BrowserAnimationsModule, 19 | ], 20 | }) 21 | export class CoreModule {} 22 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/home/home-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | import { HomeComponent } from './home.component'; 5 | 6 | export const routes: Routes = [ 7 | { 8 | path: '', 9 | component: HomeComponent, 10 | children: [ 11 | { 12 | path: 'acoes', 13 | loadChildren: () => 14 | import('../acoes/acoes.module').then((m) => m.AcoesModule), 15 | }, 16 | { 17 | path: '', 18 | redirectTo: 'acoes', 19 | pathMatch: 'full', 20 | }, 21 | { 22 | path: '**', 23 | redirectTo: 'acoes', 24 | }, 25 | ], 26 | }, 27 | ]; 28 | 29 | @NgModule({ 30 | imports: [RouterModule.forChild(routes)], 31 | exports: [RouterModule], 32 | }) 33 | export class HomeRoutingModule {} 34 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/home/home.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/app/home/home.component.css -------------------------------------------------------------------------------- /byte-bank-broker/src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 10 | 11 | 12 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HomeComponent } from './home.component'; 4 | 5 | describe('HomeComponent', () => { 6 | let component: HomeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ HomeComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HomeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { PoMenuItem, PoToolbarAction, PoToolbarProfile } from '@po-ui/ng-components'; 4 | import { Subscription } from 'rxjs'; 5 | import { environment } from 'src/environments/environment'; 6 | 7 | import { AuthorizationService } from '../authorization/authorization.service'; 8 | import { User } from '../authorization/model/user'; 9 | 10 | @Component({ 11 | selector: 'app-home', 12 | templateUrl: './home.component.html', 13 | styleUrls: ['./home.component.css'], 14 | encapsulation: ViewEncapsulation.None, 15 | }) 16 | export class HomeComponent implements OnInit, OnDestroy { 17 | public logo: string; 18 | public title: string; 19 | public menu: Array; 20 | public user: User; 21 | public profileActions: Array = []; 22 | public profile: PoToolbarProfile = { 23 | avatar: '', 24 | title: '', 25 | }; 26 | private subs = new Subscription(); 27 | 28 | public name: string; 29 | 30 | constructor( 31 | private router: Router, 32 | private authService: AuthorizationService 33 | ) { 34 | this.title = environment.name; 35 | this.logo = `../../${environment.imagesPath}/bytebank.png`; 36 | } 37 | 38 | ngOnInit() { 39 | this.setHomeInfo(); 40 | } 41 | 42 | ngOnDestroy() { 43 | this.subs.unsubscribe(); 44 | } 45 | 46 | private logout(): void { 47 | this.authService.logout(); 48 | this.router.navigate(['login']); 49 | } 50 | 51 | private setHomeInfo(): void { 52 | this.user = this.authService.getAuthenticatedUser(); 53 | this.profileActions.push({ 54 | label: 'Logout', 55 | action: () => this.logout(), 56 | }); 57 | this.menu = this.getMenus(); 58 | this.profile.title = this.user.name; 59 | } 60 | 61 | private getMenus(): Array { 62 | const menu: Array = [ 63 | { 64 | label: 'Home', 65 | link: '/home', 66 | }, 67 | { 68 | label: 'Ações', 69 | link: '/home/acoes', 70 | }, 71 | ]; 72 | return menu; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { HomeRoutingModule } from './home-routing.module'; 5 | import { HomeComponent } from './home.component'; 6 | import { SharedModule } from '../shared/shared.module'; 7 | 8 | @NgModule({ 9 | declarations: [HomeComponent], 10 | imports: [CommonModule, HomeRoutingModule, SharedModule], 11 | }) 12 | export class HomeModule {} 13 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/login/login-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { LoginComponent } from './login.component'; 4 | 5 | export const routes: Routes = [ 6 | { 7 | path: '', 8 | component: LoginComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class LoginRoutingModule {} 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/login/login.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/app/login/login.component.css -------------------------------------------------------------------------------- /byte-bank-broker/src/app/login/login.component.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/login/login.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoginComponent } from './login.component'; 4 | 5 | describe('LoginComponent', () => { 6 | let component: LoginComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LoginComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoginComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/login/login.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { Subscription } from 'rxjs'; 3 | import { Router } from '@angular/router'; 4 | import { AuthorizationService } from '../authorization/authorization.service'; 5 | import { MessagesService } from '../messages/messages.service'; 6 | import { environment } from 'src/environments/environment'; 7 | import { PoPageLogin } from '@po-ui/ng-templates'; 8 | import { UserLogin } from '../authorization/model/user-login'; 9 | import { HttpErrorResponse } from '@angular/common/http'; 10 | 11 | @Component({ 12 | selector: 'app-login', 13 | templateUrl: './login.component.html', 14 | styleUrls: ['./login.component.css'], 15 | }) 16 | export class LoginComponent implements OnInit, OnDestroy { 17 | public isLoading: boolean; 18 | public logo: string; 19 | public secondaryLogo: string; 20 | private subs = new Subscription(); 21 | 22 | constructor( 23 | private route: Router, 24 | private authService: AuthorizationService, 25 | private messageService: MessagesService 26 | ) { 27 | this.logo = `../../${environment.imagesPath}/bytebank.png`; 28 | this.secondaryLogo = `../../${environment.imagesPath}/bytebank.png`; 29 | } 30 | 31 | ngOnInit() { 32 | this.authService.logout(); 33 | this.isLoading = false; 34 | } 35 | 36 | onloginSubmit(formData: PoPageLogin): void { 37 | const user: UserLogin = { 38 | userName: formData.login, 39 | password: formData.password, 40 | remindUser: formData.rememberUser, 41 | }; 42 | this.login(user); 43 | } 44 | 45 | private login(user: UserLogin): void { 46 | this.isLoading = true; 47 | 48 | this.subs.add( 49 | this.authService.login(user).subscribe( 50 | () => { 51 | this.isLoading = false; 52 | const redirect = this.authService.redirectUrl 53 | ? this.authService.redirectUrl 54 | : '/home'; 55 | this.route.navigate([redirect]); 56 | }, 57 | (error: HttpErrorResponse) => { 58 | this.isLoading = false; 59 | this.messageService.showMessageError('Senha inválida'); 60 | this.route.navigate(['/login']); 61 | } 62 | ) 63 | ); 64 | } 65 | 66 | ngOnDestroy() { 67 | this.subs.unsubscribe(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/login/login.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { LoginRoutingModule } from './login-routing.module'; 5 | import { PoTemplatesModule } from '@po-ui/ng-templates'; 6 | import { LoginComponent } from './login.component'; 7 | import { SharedModule } from '../shared/shared.module'; 8 | 9 | @NgModule({ 10 | declarations: [LoginComponent], 11 | imports: [CommonModule, LoginRoutingModule, PoTemplatesModule, SharedModule], 12 | }) 13 | export class LoginModule {} 14 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/messages/messages.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { MessagesService } from './messages.service'; 4 | 5 | @NgModule({ 6 | providers: [MessagesService], 7 | imports: [CommonModule], 8 | }) 9 | export class MessagesModule {} 10 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/messages/messages.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { MessagesService } from './messages.service'; 4 | 5 | describe('MessagesService', () => { 6 | let service: MessagesService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(MessagesService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/messages/messages.service.ts: -------------------------------------------------------------------------------- 1 | 2 | import { 3 | PoNotificationService, 4 | PoNotification, 5 | PoToasterOrientation, 6 | } from '@po-ui/ng-components'; 7 | import { Injectable } from '@angular/core'; 8 | 9 | @Injectable({ 10 | providedIn: 'root', 11 | }) 12 | export class MessagesService { 13 | 14 | constructor(private poNotificationService: PoNotificationService) {} 15 | 16 | showMessageError(message: string) { 17 | const notification: PoNotification = { 18 | message, 19 | orientation: PoToasterOrientation.Bottom, 20 | }; 21 | this.poNotificationService.error(notification); 22 | } 23 | 24 | showMessageSucess(message: string) { 25 | const notification: PoNotification = { 26 | message, 27 | orientation: PoToasterOrientation.Bottom, 28 | }; 29 | this.poNotificationService.success(notification); 30 | } 31 | 32 | showMessageInfo(message: string) { 33 | const notification: PoNotification = { 34 | message, 35 | orientation: PoToasterOrientation.Bottom, 36 | }; 37 | this.poNotificationService.information(notification); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/no-data/no-data.component.css: -------------------------------------------------------------------------------- 1 | .app-no-data { 2 | position: relative; 3 | padding: 8px 8px 8px 48px; 4 | color: #ffffff; 5 | } 6 | 7 | .app-no-data.app-no-data-warning { 8 | background-color: #ea9b3e; 9 | } 10 | 11 | .app-no-data.app-no-data-warning::before { 12 | content: '!'; 13 | position: absolute; 14 | left: 23px; 15 | } 16 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/no-data/no-data.component.html: -------------------------------------------------------------------------------- 1 |
2 | {{ noDataFound }} 3 |
4 | 5 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/no-data/no-data.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NoDataComponent } from './no-data.component'; 4 | 5 | describe('NoDataComponent', () => { 6 | let component: NoDataComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ NoDataComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NoDataComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/no-data/no-data.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-no-data', 5 | templateUrl: './no-data.component.html', 6 | styleUrls: ['./no-data.component.css'], 7 | }) 8 | export class NoDataComponent implements OnInit { 9 | noDataFound = 'Não há dados'; 10 | 11 | constructor() {} 12 | 13 | ngOnInit(): void {} 14 | } 15 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/no-data/no-data.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NoDataComponent } from './no-data.component'; 4 | 5 | @NgModule({ 6 | declarations: [NoDataComponent], 7 | imports: [CommonModule], 8 | exports: [NoDataComponent], 9 | }) 10 | export class NoDataModule {} 11 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/model/portfolio.ts: -------------------------------------------------------------------------------- 1 | interface PortFolio { 2 | portfolio_id: string; 3 | portfolio_descricao: string; 4 | user_id: number; 5 | items: Array; 6 | } 7 | 8 | interface PortFolioItem { 9 | item_quantidade: number; 10 | item_preco: number; 11 | acoes_id: number; 12 | } 13 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-form/portfolio-form.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/app/portfolio/portfolio-form/portfolio-form.component.css -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-form/portfolio-form.component.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-form/portfolio-form.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PortfolioFormComponent } from './portfolio-form.component'; 4 | 5 | describe('PortfolioFormComponent', () => { 6 | let component: PortfolioFormComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ PortfolioFormComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PortfolioFormComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-form/portfolio-form.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { 4 | PoPageDynamicEditActions, 5 | PoPageDynamicEditField, 6 | } from '@po-ui/ng-templates'; 7 | 8 | @Component({ 9 | selector: 'app-portfolio-form', 10 | templateUrl: './portfolio-form.component.html', 11 | styleUrls: ['./portfolio-form.component.css'], 12 | }) 13 | export class PortfolioFormComponent implements OnInit { 14 | public readonly serviceApi = 'http://localhost:3000/portfolios'; 15 | title = 'Novo portfolio'; 16 | 17 | public readonly actions: PoPageDynamicEditActions = { 18 | cancel: '/home/portfolio', 19 | save: '/home/portfolio', 20 | }; 21 | 22 | public readonly fields: Array = [ 23 | { property: 'portfolio_id', key: true, visible: false }, 24 | { 25 | label: 'Descrição', 26 | property: 'portfolio_descricao', 27 | }, 28 | ]; 29 | 30 | constructor(private activatedRoute: ActivatedRoute) {} 31 | 32 | ngOnInit() { 33 | this.activatedRoute.params.subscribe((params) => { 34 | this.title = params.id ? 'Editando' : 'Novo portfolio'; 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-list/portfolio-list.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/app/portfolio/portfolio-list/portfolio-list.component.css -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-list/portfolio-list.component.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-list/portfolio-list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PortfolioListComponent } from './portfolio-list.component'; 4 | 5 | describe('PortfolioListComponent', () => { 6 | let component: PortfolioListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ PortfolioListComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PortfolioListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-list/portfolio-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { PoPageDynamicTableActions } from '@po-ui/ng-templates'; 3 | import { PoBreadcrumb } from '@po-ui/ng-components'; 4 | 5 | @Component({ 6 | selector: 'app-portfolio-list', 7 | templateUrl: './portfolio-list.component.html', 8 | styleUrls: ['./portfolio-list.component.css'], 9 | }) 10 | export class PortfolioListComponent { 11 | public readonly serviceApi = 'http://localhost:3000/portfolios'; 12 | 13 | public readonly actions: PoPageDynamicTableActions = { 14 | new: '/home/portfolio/new', 15 | detail: '/home/portfolio/detail/:id', 16 | remove: true, 17 | }; 18 | 19 | public readonly breadcrumb: PoBreadcrumb = { 20 | items: [{ label: 'Home', link: '/' }, { label: 'Portfolio' }], 21 | }; 22 | 23 | public readonly fields: Array = [ 24 | { property: 'portfolio_id', key: true }, 25 | { 26 | property: 'portfolio_descricao', 27 | label: 'Descrição', 28 | filter: true, 29 | gridColumns: 6, 30 | }, 31 | ]; 32 | } 33 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { PortfolioListComponent } from './portfolio-list/portfolio-list.component'; 4 | import { PortfolioFormComponent } from './portfolio-form/portfolio-form.component'; 5 | 6 | export const routes: Routes = [ 7 | { 8 | path: '', 9 | component: PortfolioListComponent, 10 | }, 11 | { 12 | path: 'new', 13 | component: PortfolioFormComponent, 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule], 20 | }) 21 | export class PortfolioRoutingModule {} 22 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { PortfolioRoutingModule } from './portfolio-routing.module'; 5 | import { SharedModule } from '../shared/shared.module'; 6 | import { PoTemplatesModule } from '@po-ui/ng-templates'; 7 | import { PortfolioListComponent } from './portfolio-list/portfolio-list.component'; 8 | import { PortfolioFormComponent } from './portfolio-form/portfolio-form.component'; 9 | 10 | @NgModule({ 11 | declarations: [PortfolioListComponent, PortfolioFormComponent], 12 | imports: [ 13 | CommonModule, 14 | PortfolioRoutingModule, 15 | SharedModule, 16 | PoTemplatesModule, 17 | ], 18 | }) 19 | export class PortfolioModule {} 20 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { PortfolioService } from './portfolio.service'; 4 | 5 | describe('PortfolioService', () => { 6 | let service: PortfolioService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(PortfolioService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/portfolio/portfolio.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { environment } from 'src/environments/environment'; 4 | import { Observable } from 'rxjs'; 5 | 6 | @Injectable({ 7 | providedIn: 'root', 8 | }) 9 | export class PortfolioService { 10 | private readonly portfoliopUrl = `${environment.api}/portfolios`; 11 | constructor(private httpClient: HttpClient) {} 12 | 13 | getPortFolio(id: string): Observable { 14 | return this.httpClient.get(`${this.portfoliopUrl}/${id}`); 15 | } 16 | 17 | putPortFolio(id: string, portfolio: PortFolio): Observable { 18 | return this.httpClient.put( 19 | `${this.portfoliopUrl}/${id}`, 20 | portfolio 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /byte-bank-broker/src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { PoModule } from '@po-ui/ng-components'; 4 | import { MessagesModule } from '../messages/messages.module'; 5 | import { NoDataModule } from '../no-data/no-data.module'; 6 | import { ReactiveFormsModule } from '@angular/forms'; 7 | import { AuthorizationModule } from '../authorization/authorization.module'; 8 | 9 | @NgModule({ 10 | imports: [ 11 | CommonModule, 12 | PoModule, 13 | MessagesModule, 14 | NoDataModule, 15 | ReactiveFormsModule, 16 | AuthorizationModule, 17 | ], 18 | exports: [ 19 | PoModule, 20 | MessagesModule, 21 | NoDataModule, 22 | ReactiveFormsModule, 23 | AuthorizationModule, 24 | ], 25 | }) 26 | export class SharedModule {} 27 | -------------------------------------------------------------------------------- /byte-bank-broker/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/assets/.gitkeep -------------------------------------------------------------------------------- /byte-bank-broker/src/assets/bytebank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/assets/bytebank.png -------------------------------------------------------------------------------- /byte-bank-broker/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | api: 'http://localhost:3000', 4 | imagesPath: 'assets', 5 | name: 'Byte Bank Broker', 6 | }; 7 | -------------------------------------------------------------------------------- /byte-bank-broker/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | api: 'http://localhost:3000', 8 | imagesPath: 'assets', 9 | name: 'Byte Bank Broker', 10 | }; 11 | 12 | /* 13 | * For easier debugging in development mode, you can import the following file 14 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 15 | * 16 | * This import should be commented out in production mode because it will have a negative impact 17 | * on performance if an error is thrown. 18 | */ 19 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 20 | -------------------------------------------------------------------------------- /byte-bank-broker/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alura-cursos/alura_angular_rxjs_1/1d59513b331644b4a41b7b1acce1b095e81e9f64/byte-bank-broker/src/favicon.ico -------------------------------------------------------------------------------- /byte-bank-broker/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ByteBankBroker 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /byte-bank-broker/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /byte-bank-broker/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | 61 | /*************************************************************************************************** 62 | * APPLICATION IMPORTS 63 | */ 64 | -------------------------------------------------------------------------------- /byte-bank-broker/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /byte-bank-broker/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting() 21 | ); 22 | // Then we find all the tests. 23 | const context = require.context('./', true, /\.spec\.ts$/); 24 | // And load the modules. 25 | context.keys().map(context); 26 | -------------------------------------------------------------------------------- /byte-bank-broker/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /byte-bank-broker/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "module": "es2020", 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ] 18 | }, 19 | "angularCompilerOptions": { 20 | "fullTemplateTypeCheck": true, 21 | "strictInjectionParameters": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /byte-bank-broker/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience. 3 | It is not intended to be used to perform a compilation. 4 | 5 | To learn more about this file see: https://angular.io/config/solution-tsconfig. 6 | */ 7 | { 8 | "files": [], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.app.json" 12 | }, 13 | { 14 | "path": "./tsconfig.spec.json" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /byte-bank-broker/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /byte-bank-broker/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "align": { 5 | "options": [ 6 | "parameters", 7 | "statements" 8 | ] 9 | }, 10 | "array-type": false, 11 | "arrow-return-shorthand": true, 12 | "curly": true, 13 | "deprecation": { 14 | "severity": "warning" 15 | }, 16 | "component-class-suffix": true, 17 | "contextual-lifecycle": true, 18 | "directive-class-suffix": true, 19 | "directive-selector": [ 20 | true, 21 | "attribute", 22 | "app", 23 | "camelCase" 24 | ], 25 | "component-selector": [ 26 | true, 27 | "element", 28 | "app", 29 | "kebab-case" 30 | ], 31 | "eofline": true, 32 | "import-blacklist": [ 33 | true, 34 | "rxjs/Rx" 35 | ], 36 | "import-spacing": true, 37 | "indent": { 38 | "options": [ 39 | "spaces" 40 | ] 41 | }, 42 | "max-classes-per-file": false, 43 | "max-line-length": [ 44 | true, 45 | 140 46 | ], 47 | "member-ordering": [ 48 | true, 49 | { 50 | "order": [ 51 | "static-field", 52 | "instance-field", 53 | "static-method", 54 | "instance-method" 55 | ] 56 | } 57 | ], 58 | "no-console": [ 59 | true, 60 | "debug", 61 | "info", 62 | "time", 63 | "timeEnd", 64 | "trace" 65 | ], 66 | "no-empty": false, 67 | "no-inferrable-types": [ 68 | true, 69 | "ignore-params" 70 | ], 71 | "no-non-null-assertion": true, 72 | "no-redundant-jsdoc": true, 73 | "no-switch-case-fall-through": true, 74 | "no-var-requires": false, 75 | "object-literal-key-quotes": [ 76 | true, 77 | "as-needed" 78 | ], 79 | "quotemark": [ 80 | true, 81 | "single" 82 | ], 83 | "semicolon": { 84 | "options": [ 85 | "always" 86 | ] 87 | }, 88 | "space-before-function-paren": { 89 | "options": { 90 | "anonymous": "never", 91 | "asyncArrow": "always", 92 | "constructor": "never", 93 | "method": "never", 94 | "named": "never" 95 | } 96 | }, 97 | "typedef-whitespace": { 98 | "options": [ 99 | { 100 | "call-signature": "nospace", 101 | "index-signature": "nospace", 102 | "parameter": "nospace", 103 | "property-declaration": "nospace", 104 | "variable-declaration": "nospace" 105 | }, 106 | { 107 | "call-signature": "onespace", 108 | "index-signature": "onespace", 109 | "parameter": "onespace", 110 | "property-declaration": "onespace", 111 | "variable-declaration": "onespace" 112 | } 113 | ] 114 | }, 115 | "variable-name": { 116 | "options": [ 117 | "ban-keywords", 118 | "check-format", 119 | "allow-pascal-case" 120 | ] 121 | }, 122 | "whitespace": { 123 | "options": [ 124 | "check-branch", 125 | "check-decl", 126 | "check-operator", 127 | "check-separator", 128 | "check-type", 129 | "check-typecast" 130 | ] 131 | }, 132 | "no-conflicting-lifecycle": true, 133 | "no-host-metadata-property": true, 134 | "no-input-rename": true, 135 | "no-inputs-metadata-property": true, 136 | "no-output-native": true, 137 | "no-output-on-prefix": true, 138 | "no-output-rename": true, 139 | "no-outputs-metadata-property": true, 140 | "template-banana-in-box": true, 141 | "template-no-negated-async": true, 142 | "use-lifecycle-interface": true, 143 | "use-pipe-transform-interface": true 144 | }, 145 | "rulesDirectory": [ 146 | "codelyzer" 147 | ] 148 | } --------------------------------------------------------------------------------