├── .gitignore ├── README.md ├── backend ├── .eslintrc.json ├── handler.js ├── package-lock.json ├── package.json └── serverless.yml └── frontend ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json └── src ├── App.css ├── App.js ├── App.test.js ├── chatWindow.js ├── config.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js /.gitignore: -------------------------------------------------------------------------------- 1 | # package directories 2 | node_modules 3 | jspm_packages 4 | 5 | # Serverless directories 6 | .serverless -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## This repo is deprecated, please check out new example repo https://github.com/yai333/QuestionAnswerChatbot 2 | 3 | Realtime chat web app using React, AWS API Gateway Websockets, Dynamodb and custom Cognito authorizer. 4 | https://medium.com/neami-apps/how-to-build-a-react-chat-app-with-aws-api-gateway-websockets-and-cognito-custom-authorizer-6f84f2da47ec 5 | 6 | ## Project Structure 7 | 8 | ```bash 9 | ── /backend/ # Api Gateway Websockets and Lambda functions 10 | ── /frontend/ # Frontend React web app 11 | ``` 12 | 13 | ## Stack 14 | 15 | - React 16.8+ 16 | - Serverless 1.38+ 17 | - Node.js 8.10 18 | 19 | ## Create AWS Cognito User Pool 20 | 21 | https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html 22 | 23 | Once User Pool created, Replace all APP_CLIENT_ID and USER_POOL_ID to your created IDs 24 | 25 | ## Deploy Backend 26 | 27 | ``` 28 | cd backend 29 | sls deploy 30 | cd .. 31 | ``` 32 | 33 | ## Run React App 34 | 35 | ``` 36 | cd frontend 37 | npm install 38 | npm start 39 | ``` 40 | -------------------------------------------------------------------------------- /backend/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "globals": { 10 | "Atomics": "readonly", 11 | "SharedArrayBuffer": "readonly" 12 | }, 13 | "parserOptions": { 14 | "ecmaVersion": 2018 15 | }, 16 | "rules": {} 17 | } 18 | -------------------------------------------------------------------------------- /backend/handler.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const AWS = require("aws-sdk"); 4 | const Bluebird = require("bluebird"); 5 | AWS.config.update({ region: process.env.AWS_REGION }); 6 | const DDB = new AWS.DynamoDB({ apiVersion: "2012-10-08" }); 7 | AWS.config.setPromisesDependency(Bluebird); 8 | require("aws-sdk/clients/apigatewaymanagementapi"); 9 | 10 | const successfullResponse = { 11 | statusCode: 200, 12 | body: "Connected" 13 | }; 14 | 15 | const jose = require("node-jose"); 16 | const fetch = require("node-fetch"); 17 | fetch.Promise = Bluebird; 18 | 19 | module.exports.connectionManager = (event, context, callback) => { 20 | if (event.requestContext.eventType === "CONNECT") { 21 | addConnection(event.requestContext.connectionId) 22 | .then(() => { 23 | callback(null, successfullResponse); 24 | }) 25 | .catch(err => { 26 | callback(null, JSON.stringify(err)); 27 | }); 28 | } else if (event.requestContext.eventType === "DISCONNECT") { 29 | deleteConnection(event.requestContext.connectionId) 30 | .then(() => { 31 | callback(null, successfullResponse); 32 | }) 33 | .catch(err => { 34 | callback(null, { 35 | statusCode: 500, 36 | body: "Failed to connect: " + JSON.stringify(err) 37 | }); 38 | }); 39 | } 40 | }; 41 | 42 | module.exports.defaultMessage = (event, context, callback) => { 43 | callback(null); 44 | }; 45 | 46 | module.exports.sendMessage = async (event, context, callback) => { 47 | let connectionData; 48 | try { 49 | connectionData = await DDB.scan({ 50 | TableName: process.env.CHATCONNECTION_TABLE, 51 | ProjectionExpression: "connectionId" 52 | }).promise(); 53 | } catch (err) { 54 | console.log(err); 55 | return { statusCode: 500 }; 56 | } 57 | const postCalls = connectionData.Items.map(async ({ connectionId }) => { 58 | try { 59 | return await send(event, connectionId.S); 60 | } catch (err) { 61 | if (err.statusCode === 410) { 62 | return await deleteConnection(connectionId.S); 63 | } 64 | console.log(JSON.stringify(err)); 65 | throw err; 66 | } 67 | }); 68 | 69 | try { 70 | await Promise.all(postCalls); 71 | } catch (err) { 72 | console.log(err); 73 | callback(null, JSON.stringify(err)); 74 | } 75 | callback(null, successfullResponse); 76 | }; 77 | 78 | const send = (event, connectionId) => { 79 | const postData = JSON.parse(event.body).data; 80 | const apigwManagementApi = new AWS.ApiGatewayManagementApi({ 81 | apiVersion: "2018-11-29", 82 | endpoint: event.requestContext.domainName + "/" + event.requestContext.stage 83 | }); 84 | return apigwManagementApi 85 | .postToConnection({ ConnectionId: connectionId, Data: postData }) 86 | .promise(); 87 | }; 88 | 89 | const addConnection = connectionId => { 90 | const putParams = { 91 | TableName: process.env.CHATCONNECTION_TABLE, 92 | Item: { 93 | connectionId: { S: connectionId } 94 | } 95 | }; 96 | 97 | return DDB.putItem(putParams).promise(); 98 | }; 99 | 100 | const deleteConnection = connectionId => { 101 | const deleteParams = { 102 | TableName: process.env.CHATCONNECTION_TABLE, 103 | Key: { 104 | connectionId: { S: connectionId } 105 | } 106 | }; 107 | 108 | return DDB.deleteItem(deleteParams).promise(); 109 | }; 110 | 111 | module.exports.authorizerFunc = async (event, context, callback) => { 112 | const keys_url = 113 | "https://cognito-idp.ap-southeast-2.amazonaws.com/USER_POOL_ID/.well-known/jwks.json"; 114 | const { 115 | queryStringParameters: { token }, 116 | methodArn 117 | } = event; 118 | 119 | const app_client_id = APP_CLIENT_ID; 120 | if (!token) return context.fail("Unauthorized"); 121 | const sections = token.split("."); 122 | let authHeader = jose.util.base64url.decode(sections[0]); 123 | authHeader = JSON.parse(authHeader); 124 | const kid = authHeader.kid; 125 | const rawRes = await fetch(keys_url); 126 | const response = await rawRes.json(); 127 | 128 | if (rawRes.ok) { 129 | const keys = response["keys"]; 130 | let key_index = -1; 131 | keys.some((key, index) => { 132 | if (kid == key.kid) { 133 | key_index = index; 134 | } 135 | }); 136 | const foundKey = keys.find(key => { 137 | return kid === key.kid; 138 | }); 139 | 140 | if (!foundKey) { 141 | context.fail("Public key not found in jwks.json"); 142 | } 143 | 144 | jose.JWK.asKey(foundKey).then(function(result) { 145 | // verify the signature 146 | jose.JWS.createVerify(result) 147 | .verify(token) 148 | .then(function(result) { 149 | // now we can use the claims 150 | const claims = JSON.parse(result.payload); 151 | // additionally we can verify the token expiration 152 | const current_ts = Math.floor(new Date() / 1000); 153 | if (current_ts > claims.exp) { 154 | context.fail("Token is expired"); 155 | } 156 | // and the Audience (use claims.client_id if verifying an access token) 157 | if (claims.aud != app_client_id) { 158 | context.fail("Token was not issued for this audience"); 159 | } 160 | context.succeed(generateAllow("me", methodArn)); 161 | }) 162 | .catch(err => { 163 | context.fail("Signature verification failed"); 164 | }); 165 | }); 166 | } 167 | }; 168 | 169 | const generatePolicy = function(principalId, effect, resource) { 170 | var authResponse = {}; 171 | authResponse.principalId = principalId; 172 | if (effect && resource) { 173 | var policyDocument = {}; 174 | policyDocument.Version = "2012-10-17"; // default version 175 | policyDocument.Statement = []; 176 | var statementOne = {}; 177 | statementOne.Action = "execute-api:Invoke"; // default action 178 | statementOne.Effect = effect; 179 | statementOne.Resource = resource; 180 | policyDocument.Statement[0] = statementOne; 181 | authResponse.policyDocument = policyDocument; 182 | } 183 | return authResponse; 184 | }; 185 | 186 | const generateAllow = function(principalId, resource) { 187 | return generatePolicy(principalId, "Allow", resource); 188 | }; 189 | 190 | const generateDeny = function(principalId, resource) { 191 | return generatePolicy(principalId, "Deny", resource); 192 | }; 193 | -------------------------------------------------------------------------------- /backend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chat", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.0.0", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", 10 | "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/highlight": { 17 | "version": "7.0.0", 18 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", 19 | "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", 20 | "dev": true, 21 | "requires": { 22 | "chalk": "^2.0.0", 23 | "esutils": "^2.0.2", 24 | "js-tokens": "^4.0.0" 25 | } 26 | }, 27 | "@babel/polyfill": { 28 | "version": "7.2.5", 29 | "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz", 30 | "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==", 31 | "requires": { 32 | "core-js": "^2.5.7", 33 | "regenerator-runtime": "^0.12.0" 34 | } 35 | }, 36 | "@serverless/utils": { 37 | "version": "0.0.20", 38 | "resolved": "https://registry.npmjs.org/@serverless/utils/-/utils-0.0.20.tgz", 39 | "integrity": "sha512-naG6GhxlDwuKFzH0lEN0poNkxW6sn42exrD7s3Ii5qemOzYlbGoyzlGjhT4ti11tJXI/qpdeqhz8agFY+FGLtQ==", 40 | "requires": { 41 | "@babel/polyfill": "^7.0.0", 42 | "archiver": "^2.1.1", 43 | "bluebird": "^3.5.1", 44 | "cross-fetch": "^2.2.2", 45 | "crypto-extra": "^0.4.0", 46 | "fs-extra": "^5.0.0", 47 | "is-url": "^1.2.4", 48 | "js-yaml": "^3.11.0", 49 | "ramda": "^0.25.0", 50 | "source-map-support": "^0.5.5" 51 | } 52 | }, 53 | "acorn": { 54 | "version": "6.4.1", 55 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", 56 | "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", 57 | "dev": true 58 | }, 59 | "acorn-jsx": { 60 | "version": "5.0.1", 61 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", 62 | "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", 63 | "dev": true 64 | }, 65 | "ajv": { 66 | "version": "6.10.0", 67 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", 68 | "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", 69 | "dev": true, 70 | "requires": { 71 | "fast-deep-equal": "^2.0.1", 72 | "fast-json-stable-stringify": "^2.0.0", 73 | "json-schema-traverse": "^0.4.1", 74 | "uri-js": "^4.2.2" 75 | } 76 | }, 77 | "ansi-escapes": { 78 | "version": "3.2.0", 79 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 80 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", 81 | "dev": true 82 | }, 83 | "ansi-regex": { 84 | "version": "3.0.0", 85 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 86 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 87 | "dev": true 88 | }, 89 | "ansi-styles": { 90 | "version": "3.2.1", 91 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 92 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 93 | "requires": { 94 | "color-convert": "^1.9.0" 95 | } 96 | }, 97 | "archiver": { 98 | "version": "2.1.1", 99 | "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", 100 | "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", 101 | "requires": { 102 | "archiver-utils": "^1.3.0", 103 | "async": "^2.0.0", 104 | "buffer-crc32": "^0.2.1", 105 | "glob": "^7.0.0", 106 | "lodash": "^4.8.0", 107 | "readable-stream": "^2.0.0", 108 | "tar-stream": "^1.5.0", 109 | "zip-stream": "^1.2.0" 110 | } 111 | }, 112 | "archiver-utils": { 113 | "version": "1.3.0", 114 | "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", 115 | "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", 116 | "requires": { 117 | "glob": "^7.0.0", 118 | "graceful-fs": "^4.1.0", 119 | "lazystream": "^1.0.0", 120 | "lodash": "^4.8.0", 121 | "normalize-path": "^2.0.0", 122 | "readable-stream": "^2.0.0" 123 | } 124 | }, 125 | "argparse": { 126 | "version": "1.0.10", 127 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 128 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 129 | "requires": { 130 | "sprintf-js": "~1.0.2" 131 | } 132 | }, 133 | "astral-regex": { 134 | "version": "1.0.0", 135 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", 136 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", 137 | "dev": true 138 | }, 139 | "async": { 140 | "version": "2.6.1", 141 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", 142 | "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", 143 | "requires": { 144 | "lodash": "^4.17.10" 145 | } 146 | }, 147 | "aws-sdk": { 148 | "version": "2.382.0", 149 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.382.0.tgz", 150 | "integrity": "sha512-wGjZLYo2ZxGTlj2cHy/0zOfYJKUVBQYG1vpW4Cnbgo3HTtOu906a6tqkiD8QuN0EyEkn7i+wyjSiUFOCh3T/2g==", 151 | "requires": { 152 | "buffer": "4.9.1", 153 | "events": "1.1.1", 154 | "ieee754": "1.1.8", 155 | "jmespath": "0.15.0", 156 | "querystring": "0.2.0", 157 | "sax": "1.2.1", 158 | "url": "0.10.3", 159 | "uuid": "3.1.0", 160 | "xml2js": "0.4.19" 161 | } 162 | }, 163 | "balanced-match": { 164 | "version": "1.0.0", 165 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 166 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 167 | }, 168 | "base64-js": { 169 | "version": "1.3.0", 170 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", 171 | "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" 172 | }, 173 | "base64url": { 174 | "version": "3.0.1", 175 | "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", 176 | "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" 177 | }, 178 | "bl": { 179 | "version": "1.2.2", 180 | "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", 181 | "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", 182 | "requires": { 183 | "readable-stream": "^2.3.5", 184 | "safe-buffer": "^5.1.1" 185 | } 186 | }, 187 | "bluebird": { 188 | "version": "3.5.3", 189 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", 190 | "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" 191 | }, 192 | "brace-expansion": { 193 | "version": "1.1.11", 194 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 195 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 196 | "requires": { 197 | "balanced-match": "^1.0.0", 198 | "concat-map": "0.0.1" 199 | } 200 | }, 201 | "buffer": { 202 | "version": "4.9.1", 203 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", 204 | "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", 205 | "requires": { 206 | "base64-js": "^1.0.2", 207 | "ieee754": "^1.1.4", 208 | "isarray": "^1.0.0" 209 | } 210 | }, 211 | "buffer-alloc": { 212 | "version": "1.2.0", 213 | "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", 214 | "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", 215 | "requires": { 216 | "buffer-alloc-unsafe": "^1.1.0", 217 | "buffer-fill": "^1.0.0" 218 | } 219 | }, 220 | "buffer-alloc-unsafe": { 221 | "version": "1.1.0", 222 | "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", 223 | "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" 224 | }, 225 | "buffer-crc32": { 226 | "version": "0.2.13", 227 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 228 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" 229 | }, 230 | "buffer-fill": { 231 | "version": "1.0.0", 232 | "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", 233 | "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" 234 | }, 235 | "buffer-from": { 236 | "version": "1.1.1", 237 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 238 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 239 | }, 240 | "callsites": { 241 | "version": "3.0.0", 242 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", 243 | "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", 244 | "dev": true 245 | }, 246 | "chalk": { 247 | "version": "2.4.1", 248 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 249 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 250 | "requires": { 251 | "ansi-styles": "^3.2.1", 252 | "escape-string-regexp": "^1.0.5", 253 | "supports-color": "^5.3.0" 254 | } 255 | }, 256 | "chardet": { 257 | "version": "0.7.0", 258 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 259 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", 260 | "dev": true 261 | }, 262 | "cli-cursor": { 263 | "version": "2.1.0", 264 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 265 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 266 | "dev": true, 267 | "requires": { 268 | "restore-cursor": "^2.0.0" 269 | } 270 | }, 271 | "cli-width": { 272 | "version": "2.2.0", 273 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 274 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 275 | "dev": true 276 | }, 277 | "color-convert": { 278 | "version": "1.9.3", 279 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 280 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 281 | "requires": { 282 | "color-name": "1.1.3" 283 | } 284 | }, 285 | "color-name": { 286 | "version": "1.1.3", 287 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 288 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 289 | }, 290 | "compress-commons": { 291 | "version": "1.2.2", 292 | "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", 293 | "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", 294 | "requires": { 295 | "buffer-crc32": "^0.2.1", 296 | "crc32-stream": "^2.0.0", 297 | "normalize-path": "^2.0.0", 298 | "readable-stream": "^2.0.0" 299 | } 300 | }, 301 | "concat-map": { 302 | "version": "0.0.1", 303 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 304 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 305 | }, 306 | "core-js": { 307 | "version": "2.6.1", 308 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz", 309 | "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==" 310 | }, 311 | "core-util-is": { 312 | "version": "1.0.2", 313 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 314 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 315 | }, 316 | "crc": { 317 | "version": "3.8.0", 318 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", 319 | "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", 320 | "requires": { 321 | "buffer": "^5.1.0" 322 | }, 323 | "dependencies": { 324 | "buffer": { 325 | "version": "5.2.1", 326 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", 327 | "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", 328 | "requires": { 329 | "base64-js": "^1.0.2", 330 | "ieee754": "^1.1.4" 331 | } 332 | } 333 | } 334 | }, 335 | "crc32-stream": { 336 | "version": "2.0.0", 337 | "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", 338 | "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", 339 | "requires": { 340 | "crc": "^3.4.4", 341 | "readable-stream": "^2.0.0" 342 | } 343 | }, 344 | "cross-fetch": { 345 | "version": "2.2.3", 346 | "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", 347 | "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", 348 | "requires": { 349 | "node-fetch": "2.1.2", 350 | "whatwg-fetch": "2.0.4" 351 | }, 352 | "dependencies": { 353 | "node-fetch": { 354 | "version": "2.1.2", 355 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", 356 | "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" 357 | } 358 | } 359 | }, 360 | "cross-spawn": { 361 | "version": "6.0.5", 362 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 363 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 364 | "dev": true, 365 | "requires": { 366 | "nice-try": "^1.0.4", 367 | "path-key": "^2.0.1", 368 | "semver": "^5.5.0", 369 | "shebang-command": "^1.2.0", 370 | "which": "^1.2.9" 371 | } 372 | }, 373 | "crypto-extra": { 374 | "version": "0.4.0", 375 | "resolved": "https://registry.npmjs.org/crypto-extra/-/crypto-extra-0.4.0.tgz", 376 | "integrity": "sha1-MWdA6i4umLisscm5GZrh123COTQ=" 377 | }, 378 | "debug": { 379 | "version": "4.1.1", 380 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 381 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 382 | "dev": true, 383 | "requires": { 384 | "ms": "^2.1.1" 385 | } 386 | }, 387 | "deep-is": { 388 | "version": "0.1.3", 389 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 390 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 391 | "dev": true 392 | }, 393 | "doctrine": { 394 | "version": "3.0.0", 395 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 396 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 397 | "dev": true, 398 | "requires": { 399 | "esutils": "^2.0.2" 400 | } 401 | }, 402 | "emoji-regex": { 403 | "version": "7.0.3", 404 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 405 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 406 | "dev": true 407 | }, 408 | "end-of-stream": { 409 | "version": "1.4.1", 410 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 411 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 412 | "requires": { 413 | "once": "^1.4.0" 414 | } 415 | }, 416 | "es6-promise": { 417 | "version": "4.2.6", 418 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", 419 | "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" 420 | }, 421 | "escape-string-regexp": { 422 | "version": "1.0.5", 423 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 424 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 425 | }, 426 | "eslint": { 427 | "version": "5.15.1", 428 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.15.1.tgz", 429 | "integrity": "sha512-NTcm6vQ+PTgN3UBsALw5BMhgO6i5EpIjQF/Xb5tIh3sk9QhrFafujUOczGz4J24JBlzWclSB9Vmx8d+9Z6bFCg==", 430 | "dev": true, 431 | "requires": { 432 | "@babel/code-frame": "^7.0.0", 433 | "ajv": "^6.9.1", 434 | "chalk": "^2.1.0", 435 | "cross-spawn": "^6.0.5", 436 | "debug": "^4.0.1", 437 | "doctrine": "^3.0.0", 438 | "eslint-scope": "^4.0.2", 439 | "eslint-utils": "^1.3.1", 440 | "eslint-visitor-keys": "^1.0.0", 441 | "espree": "^5.0.1", 442 | "esquery": "^1.0.1", 443 | "esutils": "^2.0.2", 444 | "file-entry-cache": "^5.0.1", 445 | "functional-red-black-tree": "^1.0.1", 446 | "glob": "^7.1.2", 447 | "globals": "^11.7.0", 448 | "ignore": "^4.0.6", 449 | "import-fresh": "^3.0.0", 450 | "imurmurhash": "^0.1.4", 451 | "inquirer": "^6.2.2", 452 | "js-yaml": "^3.12.0", 453 | "json-stable-stringify-without-jsonify": "^1.0.1", 454 | "levn": "^0.3.0", 455 | "lodash": "^4.17.11", 456 | "minimatch": "^3.0.4", 457 | "mkdirp": "^0.5.1", 458 | "natural-compare": "^1.4.0", 459 | "optionator": "^0.8.2", 460 | "path-is-inside": "^1.0.2", 461 | "progress": "^2.0.0", 462 | "regexpp": "^2.0.1", 463 | "semver": "^5.5.1", 464 | "strip-ansi": "^4.0.0", 465 | "strip-json-comments": "^2.0.1", 466 | "table": "^5.2.3", 467 | "text-table": "^0.2.0" 468 | } 469 | }, 470 | "eslint-scope": { 471 | "version": "4.0.2", 472 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.2.tgz", 473 | "integrity": "sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg==", 474 | "dev": true, 475 | "requires": { 476 | "esrecurse": "^4.1.0", 477 | "estraverse": "^4.1.1" 478 | } 479 | }, 480 | "eslint-utils": { 481 | "version": "1.4.3", 482 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", 483 | "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", 484 | "dev": true, 485 | "requires": { 486 | "eslint-visitor-keys": "^1.1.0" 487 | }, 488 | "dependencies": { 489 | "eslint-visitor-keys": { 490 | "version": "1.1.0", 491 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 492 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 493 | "dev": true 494 | } 495 | } 496 | }, 497 | "eslint-visitor-keys": { 498 | "version": "1.0.0", 499 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", 500 | "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", 501 | "dev": true 502 | }, 503 | "espree": { 504 | "version": "5.0.1", 505 | "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", 506 | "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", 507 | "dev": true, 508 | "requires": { 509 | "acorn": "^6.0.7", 510 | "acorn-jsx": "^5.0.0", 511 | "eslint-visitor-keys": "^1.0.0" 512 | } 513 | }, 514 | "esprima": { 515 | "version": "4.0.1", 516 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 517 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 518 | }, 519 | "esquery": { 520 | "version": "1.0.1", 521 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 522 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 523 | "dev": true, 524 | "requires": { 525 | "estraverse": "^4.0.0" 526 | } 527 | }, 528 | "esrecurse": { 529 | "version": "4.2.1", 530 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 531 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 532 | "dev": true, 533 | "requires": { 534 | "estraverse": "^4.1.0" 535 | } 536 | }, 537 | "estraverse": { 538 | "version": "4.2.0", 539 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 540 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 541 | "dev": true 542 | }, 543 | "esutils": { 544 | "version": "2.0.2", 545 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 546 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 547 | "dev": true 548 | }, 549 | "events": { 550 | "version": "1.1.1", 551 | "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", 552 | "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" 553 | }, 554 | "external-editor": { 555 | "version": "3.0.3", 556 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", 557 | "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", 558 | "dev": true, 559 | "requires": { 560 | "chardet": "^0.7.0", 561 | "iconv-lite": "^0.4.24", 562 | "tmp": "^0.0.33" 563 | } 564 | }, 565 | "fast-deep-equal": { 566 | "version": "2.0.1", 567 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 568 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 569 | "dev": true 570 | }, 571 | "fast-json-stable-stringify": { 572 | "version": "2.0.0", 573 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 574 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 575 | "dev": true 576 | }, 577 | "fast-levenshtein": { 578 | "version": "2.0.6", 579 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 580 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 581 | "dev": true 582 | }, 583 | "figures": { 584 | "version": "2.0.0", 585 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 586 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 587 | "dev": true, 588 | "requires": { 589 | "escape-string-regexp": "^1.0.5" 590 | } 591 | }, 592 | "file-entry-cache": { 593 | "version": "5.0.1", 594 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", 595 | "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", 596 | "dev": true, 597 | "requires": { 598 | "flat-cache": "^2.0.1" 599 | } 600 | }, 601 | "flat-cache": { 602 | "version": "2.0.1", 603 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", 604 | "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", 605 | "dev": true, 606 | "requires": { 607 | "flatted": "^2.0.0", 608 | "rimraf": "2.6.3", 609 | "write": "1.0.3" 610 | } 611 | }, 612 | "flatted": { 613 | "version": "2.0.0", 614 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", 615 | "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", 616 | "dev": true 617 | }, 618 | "fs-constants": { 619 | "version": "1.0.0", 620 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 621 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 622 | }, 623 | "fs-extra": { 624 | "version": "5.0.0", 625 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", 626 | "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", 627 | "requires": { 628 | "graceful-fs": "^4.1.2", 629 | "jsonfile": "^4.0.0", 630 | "universalify": "^0.1.0" 631 | } 632 | }, 633 | "fs.realpath": { 634 | "version": "1.0.0", 635 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 636 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 637 | }, 638 | "functional-red-black-tree": { 639 | "version": "1.0.1", 640 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 641 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 642 | "dev": true 643 | }, 644 | "glob": { 645 | "version": "7.1.3", 646 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 647 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 648 | "requires": { 649 | "fs.realpath": "^1.0.0", 650 | "inflight": "^1.0.4", 651 | "inherits": "2", 652 | "minimatch": "^3.0.4", 653 | "once": "^1.3.0", 654 | "path-is-absolute": "^1.0.0" 655 | } 656 | }, 657 | "globals": { 658 | "version": "11.11.0", 659 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", 660 | "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", 661 | "dev": true 662 | }, 663 | "graceful-fs": { 664 | "version": "4.1.15", 665 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 666 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" 667 | }, 668 | "has-flag": { 669 | "version": "3.0.0", 670 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 671 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 672 | }, 673 | "iconv-lite": { 674 | "version": "0.4.24", 675 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 676 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 677 | "dev": true, 678 | "requires": { 679 | "safer-buffer": ">= 2.1.2 < 3" 680 | } 681 | }, 682 | "ieee754": { 683 | "version": "1.1.8", 684 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", 685 | "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" 686 | }, 687 | "ignore": { 688 | "version": "4.0.6", 689 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 690 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 691 | "dev": true 692 | }, 693 | "import-fresh": { 694 | "version": "3.0.0", 695 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", 696 | "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", 697 | "dev": true, 698 | "requires": { 699 | "parent-module": "^1.0.0", 700 | "resolve-from": "^4.0.0" 701 | } 702 | }, 703 | "imurmurhash": { 704 | "version": "0.1.4", 705 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 706 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 707 | "dev": true 708 | }, 709 | "inflight": { 710 | "version": "1.0.6", 711 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 712 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 713 | "requires": { 714 | "once": "^1.3.0", 715 | "wrappy": "1" 716 | } 717 | }, 718 | "inherits": { 719 | "version": "2.0.3", 720 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 721 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 722 | }, 723 | "inquirer": { 724 | "version": "6.2.2", 725 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", 726 | "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", 727 | "dev": true, 728 | "requires": { 729 | "ansi-escapes": "^3.2.0", 730 | "chalk": "^2.4.2", 731 | "cli-cursor": "^2.1.0", 732 | "cli-width": "^2.0.0", 733 | "external-editor": "^3.0.3", 734 | "figures": "^2.0.0", 735 | "lodash": "^4.17.11", 736 | "mute-stream": "0.0.7", 737 | "run-async": "^2.2.0", 738 | "rxjs": "^6.4.0", 739 | "string-width": "^2.1.0", 740 | "strip-ansi": "^5.0.0", 741 | "through": "^2.3.6" 742 | }, 743 | "dependencies": { 744 | "ansi-regex": { 745 | "version": "4.0.0", 746 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", 747 | "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", 748 | "dev": true 749 | }, 750 | "chalk": { 751 | "version": "2.4.2", 752 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 753 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 754 | "dev": true, 755 | "requires": { 756 | "ansi-styles": "^3.2.1", 757 | "escape-string-regexp": "^1.0.5", 758 | "supports-color": "^5.3.0" 759 | } 760 | }, 761 | "strip-ansi": { 762 | "version": "5.0.0", 763 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", 764 | "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", 765 | "dev": true, 766 | "requires": { 767 | "ansi-regex": "^4.0.0" 768 | } 769 | } 770 | } 771 | }, 772 | "is-fullwidth-code-point": { 773 | "version": "2.0.0", 774 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 775 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 776 | "dev": true 777 | }, 778 | "is-promise": { 779 | "version": "2.1.0", 780 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 781 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 782 | "dev": true 783 | }, 784 | "is-url": { 785 | "version": "1.2.4", 786 | "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", 787 | "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" 788 | }, 789 | "isarray": { 790 | "version": "1.0.0", 791 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 792 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 793 | }, 794 | "isexe": { 795 | "version": "2.0.0", 796 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 797 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 798 | "dev": true 799 | }, 800 | "jmespath": { 801 | "version": "0.15.0", 802 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", 803 | "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" 804 | }, 805 | "js-tokens": { 806 | "version": "4.0.0", 807 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 808 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 809 | "dev": true 810 | }, 811 | "js-yaml": { 812 | "version": "3.13.1", 813 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 814 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 815 | "requires": { 816 | "argparse": "^1.0.7", 817 | "esprima": "^4.0.0" 818 | } 819 | }, 820 | "json-schema-traverse": { 821 | "version": "0.4.1", 822 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 823 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 824 | "dev": true 825 | }, 826 | "json-stable-stringify-without-jsonify": { 827 | "version": "1.0.1", 828 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 829 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 830 | "dev": true 831 | }, 832 | "jsonfile": { 833 | "version": "4.0.0", 834 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 835 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 836 | "requires": { 837 | "graceful-fs": "^4.1.6" 838 | } 839 | }, 840 | "lazystream": { 841 | "version": "1.0.0", 842 | "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", 843 | "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", 844 | "requires": { 845 | "readable-stream": "^2.0.5" 846 | } 847 | }, 848 | "levn": { 849 | "version": "0.3.0", 850 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 851 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 852 | "dev": true, 853 | "requires": { 854 | "prelude-ls": "~1.1.2", 855 | "type-check": "~0.3.2" 856 | } 857 | }, 858 | "lodash": { 859 | "version": "4.17.15", 860 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 861 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 862 | }, 863 | "long": { 864 | "version": "4.0.0", 865 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 866 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 867 | }, 868 | "mimic-fn": { 869 | "version": "1.2.0", 870 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 871 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 872 | "dev": true 873 | }, 874 | "minimatch": { 875 | "version": "3.0.4", 876 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 877 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 878 | "requires": { 879 | "brace-expansion": "^1.1.7" 880 | } 881 | }, 882 | "minimist": { 883 | "version": "0.0.8", 884 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 885 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 886 | "dev": true 887 | }, 888 | "mkdirp": { 889 | "version": "0.5.1", 890 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 891 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 892 | "dev": true, 893 | "requires": { 894 | "minimist": "0.0.8" 895 | } 896 | }, 897 | "ms": { 898 | "version": "2.1.1", 899 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 900 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 901 | "dev": true 902 | }, 903 | "mute-stream": { 904 | "version": "0.0.7", 905 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 906 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 907 | "dev": true 908 | }, 909 | "natural-compare": { 910 | "version": "1.4.0", 911 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 912 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 913 | "dev": true 914 | }, 915 | "nice-try": { 916 | "version": "1.0.5", 917 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 918 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 919 | "dev": true 920 | }, 921 | "node-fetch": { 922 | "version": "2.3.0", 923 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", 924 | "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" 925 | }, 926 | "node-forge": { 927 | "version": "0.8.1", 928 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.8.1.tgz", 929 | "integrity": "sha512-C/42HVb5eRtnDgRKOFx4bJH6LwbGQwbEHOC/trQwQSR6xWAUR/jlWoUJnxOmFTvdmDIZtjl2VH4dl3VpQuIz5g==" 930 | }, 931 | "node-jose": { 932 | "version": "1.1.2", 933 | "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-1.1.2.tgz", 934 | "integrity": "sha512-SotC7+9MGPSDcMlrLFcv09nv33Sw/WPT7qgZOLC0v6nY8E4n7dt7orGO13rGtb3kK163VEwJO06owkXY7LWjrQ==", 935 | "requires": { 936 | "base64url": "^3.0.1", 937 | "es6-promise": "^4.2.6", 938 | "lodash": "^4.17.11", 939 | "long": "^4.0.0", 940 | "node-forge": "^0.8.1", 941 | "uuid": "^3.3.2" 942 | }, 943 | "dependencies": { 944 | "uuid": { 945 | "version": "3.3.2", 946 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 947 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 948 | } 949 | } 950 | }, 951 | "normalize-path": { 952 | "version": "2.1.1", 953 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", 954 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", 955 | "requires": { 956 | "remove-trailing-separator": "^1.0.1" 957 | } 958 | }, 959 | "once": { 960 | "version": "1.4.0", 961 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 962 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 963 | "requires": { 964 | "wrappy": "1" 965 | } 966 | }, 967 | "onetime": { 968 | "version": "2.0.1", 969 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 970 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 971 | "dev": true, 972 | "requires": { 973 | "mimic-fn": "^1.0.0" 974 | } 975 | }, 976 | "optionator": { 977 | "version": "0.8.2", 978 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 979 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 980 | "dev": true, 981 | "requires": { 982 | "deep-is": "~0.1.3", 983 | "fast-levenshtein": "~2.0.4", 984 | "levn": "~0.3.0", 985 | "prelude-ls": "~1.1.2", 986 | "type-check": "~0.3.2", 987 | "wordwrap": "~1.0.0" 988 | } 989 | }, 990 | "os-tmpdir": { 991 | "version": "1.0.2", 992 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 993 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 994 | "dev": true 995 | }, 996 | "parent-module": { 997 | "version": "1.0.0", 998 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", 999 | "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", 1000 | "dev": true, 1001 | "requires": { 1002 | "callsites": "^3.0.0" 1003 | } 1004 | }, 1005 | "path-is-absolute": { 1006 | "version": "1.0.1", 1007 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1008 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1009 | }, 1010 | "path-is-inside": { 1011 | "version": "1.0.2", 1012 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1013 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1014 | "dev": true 1015 | }, 1016 | "path-key": { 1017 | "version": "2.0.1", 1018 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1019 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1020 | "dev": true 1021 | }, 1022 | "prelude-ls": { 1023 | "version": "1.1.2", 1024 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1025 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1026 | "dev": true 1027 | }, 1028 | "process-nextick-args": { 1029 | "version": "2.0.0", 1030 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 1031 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 1032 | }, 1033 | "progress": { 1034 | "version": "2.0.3", 1035 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1036 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1037 | "dev": true 1038 | }, 1039 | "punycode": { 1040 | "version": "1.3.2", 1041 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1042 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 1043 | }, 1044 | "querystring": { 1045 | "version": "0.2.0", 1046 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1047 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1048 | }, 1049 | "ramda": { 1050 | "version": "0.25.0", 1051 | "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", 1052 | "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==" 1053 | }, 1054 | "readable-stream": { 1055 | "version": "2.3.6", 1056 | "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1057 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1058 | "requires": { 1059 | "core-util-is": "~1.0.0", 1060 | "inherits": "~2.0.3", 1061 | "isarray": "~1.0.0", 1062 | "process-nextick-args": "~2.0.0", 1063 | "safe-buffer": "~5.1.1", 1064 | "string_decoder": "~1.1.1", 1065 | "util-deprecate": "~1.0.1" 1066 | } 1067 | }, 1068 | "regenerator-runtime": { 1069 | "version": "0.12.1", 1070 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", 1071 | "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" 1072 | }, 1073 | "regexpp": { 1074 | "version": "2.0.1", 1075 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", 1076 | "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", 1077 | "dev": true 1078 | }, 1079 | "remove-trailing-separator": { 1080 | "version": "1.1.0", 1081 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", 1082 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" 1083 | }, 1084 | "resolve-from": { 1085 | "version": "4.0.0", 1086 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1087 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1088 | "dev": true 1089 | }, 1090 | "restore-cursor": { 1091 | "version": "2.0.0", 1092 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 1093 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 1094 | "dev": true, 1095 | "requires": { 1096 | "onetime": "^2.0.0", 1097 | "signal-exit": "^3.0.2" 1098 | } 1099 | }, 1100 | "rimraf": { 1101 | "version": "2.6.3", 1102 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1103 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1104 | "dev": true, 1105 | "requires": { 1106 | "glob": "^7.1.3" 1107 | } 1108 | }, 1109 | "run-async": { 1110 | "version": "2.3.0", 1111 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 1112 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 1113 | "dev": true, 1114 | "requires": { 1115 | "is-promise": "^2.1.0" 1116 | } 1117 | }, 1118 | "rxjs": { 1119 | "version": "6.4.0", 1120 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", 1121 | "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", 1122 | "dev": true, 1123 | "requires": { 1124 | "tslib": "^1.9.0" 1125 | } 1126 | }, 1127 | "safe-buffer": { 1128 | "version": "5.1.2", 1129 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1130 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1131 | }, 1132 | "safer-buffer": { 1133 | "version": "2.1.2", 1134 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1135 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1136 | "dev": true 1137 | }, 1138 | "sax": { 1139 | "version": "1.2.1", 1140 | "resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 1141 | "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" 1142 | }, 1143 | "semver": { 1144 | "version": "5.6.0", 1145 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", 1146 | "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", 1147 | "dev": true 1148 | }, 1149 | "serverless-websockets-plugin": { 1150 | "version": "1.0.0", 1151 | "resolved": "https://registry.npmjs.org/serverless-websockets-plugin/-/serverless-websockets-plugin-1.0.0.tgz", 1152 | "integrity": "sha512-54FSeGAH/0pRpfLf/xPdY+yl8u9glbJXndd0YDcQcjeoTYaNmM7qi5r09bv8mBI5zvpxw99EZgaoXyaKvPqkHg==", 1153 | "requires": { 1154 | "@babel/polyfill": "^7.0.0", 1155 | "@serverless/utils": "0.0.20", 1156 | "chalk": "^2.4.1", 1157 | "source-map-support": "^0.5.5" 1158 | } 1159 | }, 1160 | "shebang-command": { 1161 | "version": "1.2.0", 1162 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1163 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1164 | "dev": true, 1165 | "requires": { 1166 | "shebang-regex": "^1.0.0" 1167 | } 1168 | }, 1169 | "shebang-regex": { 1170 | "version": "1.0.0", 1171 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1172 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1173 | "dev": true 1174 | }, 1175 | "signal-exit": { 1176 | "version": "3.0.2", 1177 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1178 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1179 | "dev": true 1180 | }, 1181 | "slice-ansi": { 1182 | "version": "2.1.0", 1183 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", 1184 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", 1185 | "dev": true, 1186 | "requires": { 1187 | "ansi-styles": "^3.2.0", 1188 | "astral-regex": "^1.0.0", 1189 | "is-fullwidth-code-point": "^2.0.0" 1190 | } 1191 | }, 1192 | "source-map": { 1193 | "version": "0.6.1", 1194 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1195 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 1196 | }, 1197 | "source-map-support": { 1198 | "version": "0.5.9", 1199 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", 1200 | "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", 1201 | "requires": { 1202 | "buffer-from": "^1.0.0", 1203 | "source-map": "^0.6.0" 1204 | } 1205 | }, 1206 | "sprintf-js": { 1207 | "version": "1.0.3", 1208 | "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1209 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 1210 | }, 1211 | "string-width": { 1212 | "version": "2.1.1", 1213 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1214 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1215 | "dev": true, 1216 | "requires": { 1217 | "is-fullwidth-code-point": "^2.0.0", 1218 | "strip-ansi": "^4.0.0" 1219 | } 1220 | }, 1221 | "string_decoder": { 1222 | "version": "1.1.1", 1223 | "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1224 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1225 | "requires": { 1226 | "safe-buffer": "~5.1.0" 1227 | } 1228 | }, 1229 | "strip-ansi": { 1230 | "version": "4.0.0", 1231 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1232 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1233 | "dev": true, 1234 | "requires": { 1235 | "ansi-regex": "^3.0.0" 1236 | } 1237 | }, 1238 | "strip-json-comments": { 1239 | "version": "2.0.1", 1240 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1241 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1242 | "dev": true 1243 | }, 1244 | "supports-color": { 1245 | "version": "5.5.0", 1246 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1247 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1248 | "requires": { 1249 | "has-flag": "^3.0.0" 1250 | } 1251 | }, 1252 | "table": { 1253 | "version": "5.2.3", 1254 | "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", 1255 | "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", 1256 | "dev": true, 1257 | "requires": { 1258 | "ajv": "^6.9.1", 1259 | "lodash": "^4.17.11", 1260 | "slice-ansi": "^2.1.0", 1261 | "string-width": "^3.0.0" 1262 | }, 1263 | "dependencies": { 1264 | "ansi-regex": { 1265 | "version": "4.0.0", 1266 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", 1267 | "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", 1268 | "dev": true 1269 | }, 1270 | "string-width": { 1271 | "version": "3.0.0", 1272 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", 1273 | "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", 1274 | "dev": true, 1275 | "requires": { 1276 | "emoji-regex": "^7.0.1", 1277 | "is-fullwidth-code-point": "^2.0.0", 1278 | "strip-ansi": "^5.0.0" 1279 | } 1280 | }, 1281 | "strip-ansi": { 1282 | "version": "5.0.0", 1283 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", 1284 | "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", 1285 | "dev": true, 1286 | "requires": { 1287 | "ansi-regex": "^4.0.0" 1288 | } 1289 | } 1290 | } 1291 | }, 1292 | "tar-stream": { 1293 | "version": "1.6.2", 1294 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", 1295 | "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", 1296 | "requires": { 1297 | "bl": "^1.0.0", 1298 | "buffer-alloc": "^1.2.0", 1299 | "end-of-stream": "^1.0.0", 1300 | "fs-constants": "^1.0.0", 1301 | "readable-stream": "^2.3.0", 1302 | "to-buffer": "^1.1.1", 1303 | "xtend": "^4.0.0" 1304 | } 1305 | }, 1306 | "text-table": { 1307 | "version": "0.2.0", 1308 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1309 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1310 | "dev": true 1311 | }, 1312 | "through": { 1313 | "version": "2.3.8", 1314 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1315 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1316 | "dev": true 1317 | }, 1318 | "tmp": { 1319 | "version": "0.0.33", 1320 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1321 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1322 | "dev": true, 1323 | "requires": { 1324 | "os-tmpdir": "~1.0.2" 1325 | } 1326 | }, 1327 | "to-buffer": { 1328 | "version": "1.1.1", 1329 | "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", 1330 | "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" 1331 | }, 1332 | "tslib": { 1333 | "version": "1.9.3", 1334 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", 1335 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", 1336 | "dev": true 1337 | }, 1338 | "type-check": { 1339 | "version": "0.3.2", 1340 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1341 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1342 | "dev": true, 1343 | "requires": { 1344 | "prelude-ls": "~1.1.2" 1345 | } 1346 | }, 1347 | "universalify": { 1348 | "version": "0.1.2", 1349 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1350 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" 1351 | }, 1352 | "uri-js": { 1353 | "version": "4.2.2", 1354 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1355 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1356 | "dev": true, 1357 | "requires": { 1358 | "punycode": "^2.1.0" 1359 | }, 1360 | "dependencies": { 1361 | "punycode": { 1362 | "version": "2.1.1", 1363 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1364 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1365 | "dev": true 1366 | } 1367 | } 1368 | }, 1369 | "url": { 1370 | "version": "0.10.3", 1371 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 1372 | "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", 1373 | "requires": { 1374 | "punycode": "1.3.2", 1375 | "querystring": "0.2.0" 1376 | } 1377 | }, 1378 | "util-deprecate": { 1379 | "version": "1.0.2", 1380 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1381 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1382 | }, 1383 | "uuid": { 1384 | "version": "3.1.0", 1385 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 1386 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" 1387 | }, 1388 | "whatwg-fetch": { 1389 | "version": "2.0.4", 1390 | "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", 1391 | "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" 1392 | }, 1393 | "which": { 1394 | "version": "1.3.1", 1395 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1396 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1397 | "dev": true, 1398 | "requires": { 1399 | "isexe": "^2.0.0" 1400 | } 1401 | }, 1402 | "wordwrap": { 1403 | "version": "1.0.0", 1404 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1405 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1406 | "dev": true 1407 | }, 1408 | "wrappy": { 1409 | "version": "1.0.2", 1410 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1411 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1412 | }, 1413 | "write": { 1414 | "version": "1.0.3", 1415 | "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", 1416 | "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", 1417 | "dev": true, 1418 | "requires": { 1419 | "mkdirp": "^0.5.1" 1420 | } 1421 | }, 1422 | "xml2js": { 1423 | "version": "0.4.19", 1424 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 1425 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 1426 | "requires": { 1427 | "sax": ">=0.6.0", 1428 | "xmlbuilder": "~9.0.1" 1429 | } 1430 | }, 1431 | "xmlbuilder": { 1432 | "version": "9.0.7", 1433 | "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 1434 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 1435 | }, 1436 | "xtend": { 1437 | "version": "4.0.1", 1438 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 1439 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 1440 | }, 1441 | "zip-stream": { 1442 | "version": "1.2.0", 1443 | "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", 1444 | "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", 1445 | "requires": { 1446 | "archiver-utils": "^1.3.0", 1447 | "compress-commons": "^1.2.0", 1448 | "lodash": "^4.8.0", 1449 | "readable-stream": "^2.0.0" 1450 | } 1451 | } 1452 | } 1453 | } 1454 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chat", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "handler.js", 6 | "dependencies": { 7 | "aws-sdk": "^2.382.0", 8 | "bluebird": "^3.5.3", 9 | "serverless-websockets-plugin": "^1.0.0", 10 | "node-fetch": "^2.3.0", 11 | "node-jose": "^1.1.0" 12 | }, 13 | "devDependencies": { 14 | "eslint": "^5.15.1" 15 | }, 16 | "scripts": { 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "author": "", 20 | "license": "ISC" 21 | } 22 | -------------------------------------------------------------------------------- /backend/serverless.yml: -------------------------------------------------------------------------------- 1 | service: serverless-chat 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | stackName: ${self:service}-${self:provider.stage} 7 | stage: ${opt:stage, 'dev'} 8 | region: ${opt:region, 'ap-southeast-2'} 9 | iamRoleStatements: 10 | - Effect: Allow 11 | Action: 12 | - "execute-api:ManageConnections" 13 | Resource: 14 | - "arn:aws:execute-api:*:*:**/@connections/*" 15 | - Effect: Allow 16 | Action: 17 | - "dynamodb:PutItem" 18 | - "dynamodb:GetItem" 19 | - "dynamodb:UpdateItem" 20 | - "dynamodb:DeleteItem" 21 | - "dynamodb:Query" 22 | - "dynamodb:Scan" 23 | Resource: 24 | - Fn::GetAtt: [ChatConnectionsTable, Arn] 25 | - Fn::Join: 26 | - "/" 27 | - - Fn::GetAtt: [ChatConnectionsTable, Arn] 28 | - "*" 29 | environment: 30 | CHATCONNECTION_TABLE: 31 | Ref: ChatConnectionsTable 32 | 33 | websocketApiName: websocket-chat-${self:provider.stage} 34 | websocketApiRouteSelectionExpression: $request.body.action 35 | 36 | functions: 37 | connectionManager: 38 | handler: handler.connectionManager 39 | events: 40 | - websocket: 41 | route: $connect 42 | authorizer: authorizerFunc # references the authorizerFunc function below 43 | - websocket: 44 | route: $disconnect 45 | authorizerFunc: 46 | handler: handler.authorizerFunc 47 | defaultMessages: 48 | handler: handler.defaultMessage 49 | events: 50 | - websocket: 51 | route: $default 52 | sendMessage: 53 | handler: handler.sendMessage 54 | events: 55 | - websocket: 56 | route: sendMessage 57 | resources: 58 | Resources: 59 | ChatConnectionsTable: 60 | Type: AWS::DynamoDB::Table 61 | Properties: 62 | AttributeDefinitions: 63 | - AttributeName: connectionId 64 | AttributeType: S 65 | KeySchema: 66 | - AttributeName: connectionId 67 | KeyType: HASH 68 | ProvisionedThroughput: 69 | ReadCapacityUnits: 5 70 | WriteCapacityUnits: 5 71 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatapp", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-amplify": "^1.1.17", 7 | "aws-amplify-react": "^2.2.4", 8 | "react": "^16.8.4", 9 | "react-chat-window": "^1.0.8", 10 | "react-dom": "^16.8.4", 11 | "react-scripts": "2.1.1", 12 | "sockette": "^2.0.5" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": [ 24 | ">0.2%", 25 | "not dead", 26 | "not ie <= 11", 27 | "not op_mini all" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yai333/React-Chat-App-using-AWS-API-Gateway-Websocket-and-Serverless-Framework/3f23a121a0b61840843a936478a6d7e485d35cab/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 |
18 | Edit src/App.js
and save to reload.
19 |