├── functions ├── .gitignore ├── README.md ├── package.json ├── repos.js ├── .gcloudignore ├── src │ ├── rollout.js │ ├── config.js │ ├── approval_msg.js │ ├── approval.js │ ├── scanning.js │ ├── slack_utils.js │ └── cloudbuild_utils.js ├── index.js └── package-lock.json ├── .gitignore ├── docs ├── arch.png └── slack.png ├── app ├── config.js ├── integration-tests │ ├── config.js │ └── e2e.js ├── repo-key-encrypted │ └── id_rsa_repo_key.enc ├── Dockerfile ├── src │ └── controllers.js ├── cloudbuild-master-pr.yml ├── test │ └── controllers.js ├── package.json ├── index.js ├── staging-kubernetes.yaml.tpl ├── cloudbuild-master.yml ├── views │ ├── index.ejs │ └── index_dark.ejs └── package-lock.json ├── .pre-commit-config.yaml ├── .gcloudignore ├── SECURITY.md └── README.md /functions/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /docs/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ollionorg/gcp-cnci/HEAD/docs/arch.png -------------------------------------------------------------------------------- /docs/slack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ollionorg/gcp-cnci/HEAD/docs/slack.png -------------------------------------------------------------------------------- /app/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ENV_NAME: process.env.ENVIRONMENT_NAME, 3 | } -------------------------------------------------------------------------------- /app/integration-tests/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | API_BASE: 'http://35.240.202.244' 3 | } -------------------------------------------------------------------------------- /functions/README.md: -------------------------------------------------------------------------------- 1 | # Cloud Functions to listen to Cloudbuild updates and Slack approval events -------------------------------------------------------------------------------- /app/repo-key-encrypted/id_rsa_repo_key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ollionorg/gcp-cnci/HEAD/app/repo-key-encrypted/id_rsa_repo_key.enc -------------------------------------------------------------------------------- /app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.12.0-alpine 2 | COPY package.json package.json 3 | RUN npm install 4 | COPY *.js / 5 | COPY src /src 6 | COPY views /views 7 | CMD ["npm", "start"] 8 | -------------------------------------------------------------------------------- /app/src/controllers.js: -------------------------------------------------------------------------------- 1 | const config = require('./../config') 2 | 3 | function hello() { 4 | return { 5 | msg: 'Hello, Singapore!', 6 | environment: config.ENV_NAME 7 | } 8 | }; 9 | 10 | module.exports = { 11 | hello: hello 12 | } -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: local 3 | hooks: 4 | - id: trufflehog 5 | name: TruffleHog 6 | description: Detect secrets in your data. 7 | entry: bash -c 'trufflehog git file://. --since-commit HEAD --only-verified --fail' 8 | language: system 9 | stages: ["commit", "push"] 10 | -------------------------------------------------------------------------------- /app/cloudbuild-master-pr.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - name: 'node:latest' 3 | id: Perform Unit Tests 4 | entrypoint: /bin/sh 5 | args: 6 | - -c 7 | - 'cd ${_APP_DIR} && npm install && npm test' 8 | 9 | - name: 'gcr.io/cloud-builders/docker' 10 | id: Build Docker Image 11 | args: 12 | - 'build' 13 | - '-t' 14 | - '${PROJECT_ID}/${REPO_NAME}:${SHORT_SHA}' 15 | - '${_APP_DIR}/' -------------------------------------------------------------------------------- /app/test/controllers.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const controllers = require('../src/controllers') 3 | 4 | const HOME_API_EXPECTED_MSG = 'Hello, Singapore!'; 5 | 6 | describe('Controllers', function() { 7 | describe('hello', function() { 8 | it('should return Hello World!', function() { 9 | const helloFromSomeEnv = controllers.hello(); 10 | assert.equal(helloFromSomeEnv.msg, HOME_API_EXPECTED_MSG); 11 | }); 12 | }); 13 | }); -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcp-cnci-example-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha", 8 | "integration-tests": "mocha integration-tests", 9 | "start": "node index.js" 10 | }, 11 | "author": "", 12 | "dependencies": { 13 | "ejs": "^2.7.1", 14 | "express": "^4.17.1" 15 | }, 16 | "devDependencies": { 17 | "axios": "^0.19.2", 18 | "mocha": "^6.2.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcp-cicd-cloudfuncs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha", 8 | "start": "node index.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@slack/web-api": "^5.1.0", 14 | "axios": "^0.19.0", 15 | "googleapis": "^43.0.0", 16 | "lodash": "^4.17.15" 17 | }, 18 | "devDependencies": { 19 | "mocha": "^6.2.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /functions/repos.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'gcp-cnci': { 3 | 'name': 'gcp-cnci', 4 | 'channel': 'gcp-cicd', 5 | 'deploymentSourceBranch': 'master', 6 | 'productionCandidateBranch': 'production-candidate', 7 | 'repoLink': 'https://github.com/cldcvr/gcp-cnci/', 8 | 'productionTriggerId': 'gcp-cnci-production-deploy-trigger', 9 | 'stagingEnvUrl': 'http://35.240.202.244/', 10 | 'productionEnvUrl': 'http://35.240.171.202/', 11 | 'gcrImageId': 'gcp-cnci-example-app' 12 | } 13 | } -------------------------------------------------------------------------------- /.gcloudignore: -------------------------------------------------------------------------------- 1 | # This file specifies files that are *not* uploaded to Google Cloud Platform 2 | # using gcloud. It follows the same syntax as .gitignore, with the addition of 3 | # "#!include" directives (which insert the entries of the given .gitignore-style 4 | # file at that point). 5 | # 6 | # For more information, run: 7 | # $ gcloud topic gcloudignore 8 | # 9 | .gcloudignore 10 | # If you would like to upload your .git directory, .gitignore file or files 11 | # from your .gitignore file, remove the corresponding line 12 | # below: 13 | .git 14 | .gitignore 15 | 16 | node_modules 17 | #!include:.gitignore 18 | -------------------------------------------------------------------------------- /functions/.gcloudignore: -------------------------------------------------------------------------------- 1 | # This file specifies files that are *not* uploaded to Google Cloud Platform 2 | # using gcloud. It follows the same syntax as .gitignore, with the addition of 3 | # "#!include" directives (which insert the entries of the given .gitignore-style 4 | # file at that point). 5 | # 6 | # For more information, run: 7 | # $ gcloud topic gcloudignore 8 | # 9 | .gcloudignore 10 | # If you would like to upload your .git directory, .gitignore file or files 11 | # from your .gitignore file, remove the corresponding line 12 | # below: 13 | .git 14 | .gitignore 15 | 16 | node_modules 17 | #!include:.gitignore 18 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const controllers = require('./src/controllers') 3 | const config = require('./config') 4 | 5 | const app = express() 6 | const port = 8080 7 | 8 | app.set('view engine', 'ejs'); 9 | 10 | app.get('/', (req, res) => { 11 | const templateToServe = { 12 | 'staging': 'index', 13 | 'production': 'index_dark' 14 | } 15 | res.render(templateToServe[config.ENV_NAME], {hellodd: controllers.hello()}) 16 | }); 17 | 18 | app.get('/hello', (req, res) => { 19 | res.status(200).json(controllers.hello()) 20 | }) 21 | 22 | app.listen(port, () => { 23 | console.log(`Example app listening on port ${port}!`) 24 | }) 25 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /functions/src/rollout.js: -------------------------------------------------------------------------------- 1 | const {google} = require('googleapis'); 2 | const cloudbuild = google.cloudbuild('v1'); 3 | 4 | const auth = new google.auth.GoogleAuth({ 5 | scopes: ['https://www.googleapis.com/auth/cloud-platform'] 6 | }); 7 | 8 | async function rollout(repo, commit) { 9 | const authClient = await auth.getClient(); 10 | const project = await auth.getProjectId(); 11 | 12 | await cloudbuild.projects.triggers.run({ 13 | projectId: project, 14 | auth: authClient, 15 | triggerId: repo.productionTriggerId, 16 | requestBody: { 17 | tagName: 'release-' + commit 18 | } 19 | }) 20 | } 21 | 22 | module.exports = { 23 | rollout: rollout 24 | } -------------------------------------------------------------------------------- /functions/src/config.js: -------------------------------------------------------------------------------- 1 | const repos = require('./../repos') 2 | 3 | const colors = { 4 | "SUCCESS": "#28c72a", 5 | "FAILURE": "#eb0011", 6 | "QUEUED": "#0083cc", 7 | "WORKING": "#07b5ff", 8 | "INTERNAL_ERROR": "#eb0011", 9 | "TIMEOUT": "#f40072", 10 | "CANCELLED": "#3a4247" 11 | } 12 | 13 | function getRepo(name) { 14 | let req_repo = undefined; 15 | for(let repo of Object.keys(repos)){ 16 | if (repos[repo].name == name) { 17 | req_repo = repos[repo]; 18 | break; 19 | } 20 | } 21 | return req_repo; 22 | } 23 | 24 | module.exports = { 25 | getRepo: getRepo, 26 | SLACK_TOKEN: process.env.SLACK_BOT_TOKEN, 27 | GCP_PROJECT_ID: process.env.GCLOUD_PROJECT, 28 | colors: colors 29 | } -------------------------------------------------------------------------------- /app/staging-kubernetes.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: gcp-cnci-example-app 5 | labels: 6 | app: gcp-cnci-example-app 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: gcp-cnci-example-app 12 | template: 13 | metadata: 14 | labels: 15 | app: gcp-cnci-example-app 16 | spec: 17 | containers: 18 | - name: gcp-cnci-example-app 19 | image: IMAGE_TO_DEPLOY 20 | ports: 21 | - containerPort: 8080 22 | env: 23 | - name: ENVIRONMENT_NAME 24 | value: "staging" 25 | --- 26 | kind: Service 27 | apiVersion: v1 28 | metadata: 29 | name: gcp-cnci-example-app 30 | spec: 31 | selector: 32 | app: gcp-cnci-example-app 33 | ports: 34 | - protocol: TCP 35 | port: 80 36 | targetPort: 8080 37 | type: LoadBalancer -------------------------------------------------------------------------------- /app/integration-tests/e2e.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const axios = require('axios'); 3 | const STAGING_DEPLOYMENT_API_URL = require('./config').API_BASE; 4 | 5 | // Constants 6 | const HOME_API_EXPECTED_MSG = 'Hello, Singapore!'; 7 | const STAGING_ENVIRONMENT_NAME = 'staging'; 8 | 9 | const HELLO_API = () => axios.get(STAGING_DEPLOYMENT_API_URL + '/hello'); 10 | 11 | describe('API Integration Tests', function() { 12 | describe('APIs', function() { 13 | 14 | it('\'/hello\' should return correct environment!', function() { 15 | return HELLO_API().then(response => { 16 | assert.equal(response.status, 200) 17 | assert.equal(response.data.environment, STAGING_ENVIRONMENT_NAME) 18 | }) 19 | }); 20 | 21 | it('\'/hello\' should return 200 and Hello World!', function() { 22 | return HELLO_API().then(response => { 23 | assert.equal(response.status, 200) 24 | assert.equal(response.data.msg, HOME_API_EXPECTED_MSG) 25 | }) 26 | }); 27 | }); 28 | }); -------------------------------------------------------------------------------- /functions/src/approval_msg.js: -------------------------------------------------------------------------------- 1 | const block_id = 'TY-approval-4YT'; 2 | 3 | const approval_msg = (message, yes_value, no_value) => { 4 | return [ 5 | { 6 | 'type': 'section', 7 | 'text': { 8 | 'type': 'mrkdwn', 9 | 'text': message 10 | } 11 | }, 12 | { 13 | 'type': 'actions', 14 | 'block_id': block_id, 15 | 'elements': [ 16 | { 17 | 'type': 'button', 18 | 'text': { 19 | 'type': 'plain_text', 20 | 'text': 'Yes', 21 | 'emoji': true 22 | }, 23 | 'value': JSON.stringify(yes_value), 24 | 'style': 'primary' 25 | }, 26 | { 27 | 'type': 'button', 28 | 'text': { 29 | 'type': 'plain_text', 30 | 'text': 'No', 31 | 'emoji': true 32 | }, 33 | 'value': JSON.stringify(no_value), 34 | 'style': 'danger' 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | 41 | module.exports = { 42 | msg: approval_msg, 43 | block_id: block_id 44 | } -------------------------------------------------------------------------------- /functions/index.js: -------------------------------------------------------------------------------- 1 | const cloudbuild_utils = require('./src/cloudbuild_utils'); 2 | const config = require('./src/config') 3 | const approval = require('./src/approval') 4 | 5 | const eventToBuild = (data) => { 6 | return JSON.parse(new Buffer(data, 'base64').toString()); 7 | } 8 | 9 | function isDuplicate(req) { 10 | if (req.headers['x-slack-retry-num']) { 11 | // this is a retry, don't process. TODO: find a better solution 12 | console.log('Message was retried, ignoring'); 13 | return true; 14 | } 15 | return false; 16 | } 17 | 18 | exports.gcpCiCdSlackEvents = (event, context) => { 19 | const build = eventToBuild(event.data); 20 | console.log(JSON.stringify(build)); 21 | const repo = config.getRepo(build.substitutions.REPO_NAME) 22 | 23 | if (repo && build.substitutions.TAG_NAME) { 24 | cloudbuild_utils.handleProductionDeployment(build, repo) 25 | .then(() => {}).catch(err => console.log(err)); 26 | } else if (repo) { 27 | cloudbuild_utils.handleBranchAndPRBuilds(build, repo).then(()=>{}); 28 | } 29 | }; 30 | 31 | exports.gcpCiCdApprovalAction = (req, res) => { 32 | if (isDuplicate(req)) { 33 | res.sendStatus(200); 34 | return; 35 | } 36 | 37 | if (req.method === 'POST') { 38 | approval.processAction(req.body).then(() => {}); 39 | } 40 | res.sendStatus(200); 41 | } -------------------------------------------------------------------------------- /functions/src/approval.js: -------------------------------------------------------------------------------- 1 | const slack_utils = require('./slack_utils') 2 | const approval_msg = require('./approval_msg') 3 | const rollout = require('./rollout').rollout 4 | const config = require('./config') 5 | 6 | async function onUserAction(userActionPayload, slack_context) { 7 | let action = userActionPayload.actions[0]; 8 | if (action.blockId != approval_msg.block_id) { 9 | console.log('Actions of this block not supported'); 10 | return; 11 | } 12 | 13 | if (new Date().getTime() - (1000 * userActionPayload.messageTs) >= 15 * 60 * 1000) { 14 | console.log('Action was posted before 15 mins, ignoring'); 15 | await slack_utils.replaceAction(userActionPayload.responseUrl, 'This action has expired'); 16 | return; 17 | } 18 | 19 | const payload = JSON.parse(action.value); 20 | if (payload.value == 'yes') { 21 | await slack_utils.replaceAction(userActionPayload.responseUrl, 'Roger that, rolling out to production'); 22 | await rollout(config.getRepo(payload.repoName), payload.commit); 23 | } else { 24 | await slack_utils.replaceAction(userActionPayload.responseUrl, 'Rollout to production cancelled'); 25 | } 26 | } 27 | 28 | function processAction(body) { 29 | return new Promise((resolve, reject) => { 30 | const userActionPayload = slack_utils.extractGenericAction(body); 31 | if (userActionPayload.type == slack_utils.ACTION_TYPE.OTHER) { 32 | resolve({}); 33 | return; 34 | } 35 | onUserAction(userActionPayload, {}).then(() => resolve({})).catch(reject); 36 | }); 37 | } 38 | 39 | module.exports = { 40 | processAction: processAction 41 | } -------------------------------------------------------------------------------- /functions/src/scanning.js: -------------------------------------------------------------------------------- 1 | const approval_msg = require('./approval_msg'); 2 | const slack_utils = require('./slack_utils'); 3 | const config = require('./config'); 4 | const {google} = require('googleapis'); 5 | const axios = require('axios'); 6 | let _ = require('lodash'); 7 | 8 | const auth = new google.auth.GoogleAuth({ 9 | scopes: ['https://www.googleapis.com/auth/cloud-platform'] 10 | }); 11 | 12 | const imageDigest = async (imageId, tag) => { 13 | const authClient = await auth.getClient(); 14 | const tokenRes = await authClient.getAccessToken(); 15 | const apiConfig = { 16 | headers: { 17 | 'Authorization': 'Bearer ' + tokenRes.token 18 | } 19 | } 20 | 21 | const apiRes = await axios.get('https://gcr.io/v2/' 22 | + config.GCP_PROJECT_ID + '/' 23 | + imageId + '/tags/list', apiConfig); 24 | 25 | const image = apiRes.data; 26 | const req_digests = _.filter( 27 | Object.keys(image.manifest), 28 | (digest) => { 29 | return image.manifest[digest].tag.length > 0 30 | && image.manifest[digest].tag[0] == tag 31 | }); 32 | if (req_digests.length > 0) { 33 | return req_digests[0]; 34 | } 35 | } 36 | 37 | const imageUrl = async (imageId, tag) => { 38 | const digest = await imageDigest(imageId, tag); 39 | if (digest) { 40 | return 'https://gcr.io/' + config.GCP_PROJECT_ID + '/' + imageId + '@' + digest; 41 | } 42 | } 43 | 44 | const sendApproval = async (repo, cloudbuild_data) => { 45 | const commitLink = '<' + repo.repoLink + 'commit/' + cloudbuild_data.substitutions.SHORT_SHA 46 | + '|' + repo.name + '/' + cloudbuild_data.substitutions.BRANCH_NAME 47 | + '/' + cloudbuild_data.substitutions.SHORT_SHA +'>'; 48 | 49 | const approvalInputMsg = 'Approve rollout to production for ' + commitLink + '?'; 50 | const msg = approval_msg.msg(approvalInputMsg,{ 51 | value: 'yes', 52 | repoName: repo.name, 53 | commit: cloudbuild_data.substitutions.SHORT_SHA 54 | }, { 55 | value: 'no' 56 | }); 57 | 58 | await slack_utils.sendSlackMsg({'blocks': msg}, repo.channel); 59 | } 60 | 61 | const scanProgress = async (repo, cloudbuild_data) => { 62 | const url = await imageUrl(repo.gcrImageId, cloudbuild_data.substitutions.SHORT_SHA); 63 | 64 | await slack_utils.sendSlackMsg({ 65 | 'attachments': [{ 66 | 'fallback': 'Image Vulnerability scan is in progress. Check result at ' + url, 67 | 'text': 'Image vulnerability scan is in `progress`. You can check results <'+ url + '|here>' 68 | }] 69 | }, repo.channel); 70 | 71 | await sendApproval(repo, cloudbuild_data); 72 | } 73 | 74 | module.exports = { 75 | scanProgress: scanProgress 76 | } -------------------------------------------------------------------------------- /functions/src/slack_utils.js: -------------------------------------------------------------------------------- 1 | const config = require('./config'); 2 | const axios = require('axios'); 3 | const { WebClient, ErrorCode } = require('@slack/web-api'); 4 | const slack_bot_web = new WebClient(config.SLACK_TOKEN); 5 | 6 | const ACTION_TYPE = { 7 | BLOCK_ACTION: 1, 8 | OTHER: -1 9 | } 10 | 11 | async function sendSlackMsg(response, conversationId) { 12 | try { 13 | if (response.text || response.blocks || response.attachments) { 14 | const payload = { 15 | channel: conversationId, 16 | }; 17 | if (response.blocks) payload.blocks = response.blocks; 18 | else payload.text = response.text; 19 | 20 | if (response.attachments) payload.attachments = response.attachments; 21 | 22 | const result = await slack_bot_web.chat.postMessage(payload); 23 | console.log(`Successfully send message ${result.ts} in conversation ${conversationId}`); 24 | } 25 | } catch (error) { 26 | if (error.code === ErrorCode.PlatformError) { 27 | console.log(error.data); 28 | } else { 29 | console.log('Well, that was unexpected.'); 30 | console.log(error); 31 | } 32 | const errorPayload = { 33 | channel: conversationId, 34 | text: 'Encountered an error while psoting the result of the operation' 35 | }; 36 | await slack_bot_web.chat.postMessage(errorPayload); 37 | throw error; 38 | } 39 | } 40 | 41 | async function replaceAction(responseUrl, text) { 42 | try { 43 | const msg = { 44 | 'replace_original': 'true', 45 | 'text': '> ' + text 46 | } 47 | await axios.post(responseUrl, msg); 48 | } catch(err) { 49 | console.log('Error occured while replacing the action'); 50 | console.log(err); 51 | } 52 | } 53 | 54 | function extractGenericAction(body) { 55 | const payload = JSON.parse(body.payload); 56 | const actions = []; 57 | for (let action of payload.actions) { 58 | const newAction = {}; 59 | newAction.actionId = action.action_id; 60 | newAction.blockId = action.block_id; 61 | newAction.actionTs = action.action_ts; 62 | newAction.type = action.type; 63 | 64 | if (action.type == 'button') { 65 | newAction.text = action.text.text; 66 | newAction.value = action.value; 67 | } else if (action.type == 'static_select') { 68 | newAction.text = action.selected_option.text.text; 69 | newAction.value = action.selected_option.value; 70 | } 71 | 72 | actions.push(newAction); 73 | } 74 | 75 | let type = ACTION_TYPE.OTHER; 76 | if (payload.type == 'block_actions') { 77 | type = ACTION_TYPE.BLOCK_ACTION; 78 | } 79 | 80 | return { 81 | type: type, 82 | actions: actions, 83 | channel: payload.channel.id, 84 | responseUrl: payload.response_url, 85 | messageTs: payload.message.ts 86 | } 87 | } 88 | 89 | module.exports = { 90 | sendSlackMsg: sendSlackMsg, 91 | extractGenericAction: extractGenericAction, 92 | replaceAction: replaceAction, 93 | ACTION_TYPE: ACTION_TYPE 94 | } -------------------------------------------------------------------------------- /app/cloudbuild-master.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - name: 'node:latest' 3 | id: Perform Unit Tests 4 | entrypoint: /bin/sh 5 | args: 6 | - -c 7 | - 'cd ${_APP_DIR} && npm install && npm test' 8 | 9 | - name: 'gcr.io/cloud-builders/docker' 10 | id: Build Docker Image 11 | args: 12 | - 'build' 13 | - '-t' 14 | - 'gcr.io/$PROJECT_ID/${_IMAGE_ID}:$SHORT_SHA' 15 | - '${_APP_DIR}/' 16 | 17 | - name: 'gcr.io/cloud-builders/docker' 18 | id: Push Built Docker Image to GCR 19 | args: 20 | - 'push' 21 | - 'gcr.io/$PROJECT_ID/${_IMAGE_ID}:$SHORT_SHA' 22 | 23 | # manifest for staging 24 | - name: 'gcr.io/cloud-builders/gcloud' 25 | id: Generate deployment manifest for staging environment 26 | entrypoint: /bin/sh 27 | args: 28 | - '-c' 29 | - | 30 | cd ${_APP_DIR} && \ 31 | sed "s/IMAGE_TO_DEPLOY/gcr.io\/${PROJECT_ID}\/${_IMAGE_ID}:${SHORT_SHA}/g" ${_STAGING_KUBERENETES_TEMPLATE_FILE_NAME} > ${_STAGING_KUBERNETES_CONFIG_FILE_NAME} 32 | volumes: 33 | - name: 'ssh' 34 | path: /root/.ssh 35 | 36 | # Staging deployment 37 | - name: 'gcr.io/cloud-builders/kubectl' 38 | id: Deploy to Staging 39 | args: 40 | - 'apply' 41 | - '-f' 42 | - '${_APP_DIR}/${_STAGING_KUBERNETES_CONFIG_FILE_NAME}' 43 | env: 44 | - 'CLOUDSDK_COMPUTE_ZONE=${_STAGING_DEPLOY_ZONE}' 45 | - 'CLOUDSDK_CONTAINER_CLUSTER=${_STAGING_DEPLOY_CLUSTER}' 46 | 47 | # Integration testing 48 | - name: 'node:latest' 49 | id: Perform integration tests on staging 50 | entrypoint: /bin/sh 51 | args: 52 | - '-c' 53 | - | 54 | sleep 45s && \ 55 | cd ${_APP_DIR} && npm install && npm run integration-tests 56 | 57 | # Production manifest update 58 | - name: 'gcr.io/cloud-builders/gcloud' 59 | id: Decrypt Github SSH Key for repository 60 | args: 61 | - kms 62 | - decrypt 63 | - --ciphertext-file=${_GITHUB_REPO_ENC_KEY_PATH} 64 | - --plaintext-file=/root/.ssh/id_rsa_repo_key 65 | - --location=global 66 | - --keyring=${_GITHUB_REPO_KMS_KEYRING} 67 | - --key=${_GITHUB_REPO_KEY} 68 | volumes: 69 | - name: 'ssh' 70 | path: /root/.ssh 71 | 72 | # Set up git with key and domain 73 | - name: 'gcr.io/cloud-builders/git' 74 | id: Add Github Key obtained to local env 75 | entrypoint: 'bash' 76 | args: 77 | - '-c' 78 | - | 79 | chmod 600 /root/.ssh/id_rsa_repo_key 80 | cat </root/.ssh/config 81 | Hostname github.com 82 | IdentityFile /root/.ssh/id_rsa_repo_key 83 | EOF 84 | echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config 85 | volumes: 86 | - name: 'ssh' 87 | path: /root/.ssh 88 | 89 | - name: 'gcr.io/cloud-builders/gcloud' 90 | id: Clone Repository 91 | entrypoint: /bin/sh 92 | args: 93 | - '-c' 94 | - | 95 | git clone git@github.com:${_GITHUB_REPO_USERNAME}/$REPO_NAME && \ 96 | cd $REPO_NAME && \ 97 | git checkout ${_PRODUCTION_CANDIDATE_BRANCH} && \ 98 | git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)') 99 | volumes: 100 | - name: 'ssh' 101 | path: /root/.ssh 102 | 103 | 104 | # This step generates the new manifest for production 105 | - name: 'gcr.io/cloud-builders/gcloud' 106 | id: Generate deployment manifest for production environment 107 | entrypoint: /bin/sh 108 | args: 109 | - '-c' 110 | - | 111 | cd $REPO_NAME && \ 112 | sed "s/IMAGE_TO_DEPLOY/gcr.io\/${PROJECT_ID}\/${_IMAGE_ID}:${SHORT_SHA}/g" ${_PRODUCTION_KUBERENETES_TEMPLATE_FILE_NAME} > ${_PRODUCTION_KUBERNETES_CONFIG_FILE_NAME} 113 | volumes: 114 | - name: 'ssh' 115 | path: /root/.ssh 116 | 117 | # This step pushes the manifest back to gcp-cicd-env 118 | - name: 'gcr.io/cloud-builders/gcloud' 119 | id: Push deployment manifest for production environment 120 | entrypoint: /bin/sh 121 | args: 122 | - '-c' 123 | - | 124 | cd $REPO_NAME && \ 125 | git add ${_PRODUCTION_KUBERNETES_CONFIG_FILE_NAME} && \ 126 | git commit -m "Deploying image gcr.io/${PROJECT_ID}/${REPO_NAME}:${SHORT_SHA} 127 | Built from commit ${COMMIT_SHA} Author: $(git log --format='%an <%ae>' -n 1 HEAD)" || true && \ 128 | git push origin ${_PRODUCTION_CANDIDATE_BRANCH} && \ 129 | git tag 'release-'${SHORT_SHA} || true && \ 130 | git push origin 'release-'${SHORT_SHA} 131 | volumes: 132 | - name: 'ssh' 133 | path: /root/.ssh -------------------------------------------------------------------------------- /functions/src/cloudbuild_utils.js: -------------------------------------------------------------------------------- 1 | const slack_utils = require('./slack_utils'); 2 | const scanning = require('./scanning'); 3 | const config = require('./config') 4 | 5 | function getFailedStep(data) { 6 | let failedStep = undefined; 7 | for (let step of data.steps) { 8 | if (step.status === 'FAILURE') { 9 | failedStep = step; 10 | break; 11 | } 12 | } 13 | return failedStep; 14 | } 15 | 16 | const handleProductionDeployment = async (data, repo) => { 17 | let resText = undefined; 18 | let resColor = undefined; 19 | const LOGS = (name) => '<' + data.logUrl + '|' + name + '>'; 20 | const commitLink = '<' + repo.repoLink + 'commit/' + data.substitutions.SHORT_SHA 21 | + '|' + repo.name + '/' + repo.productionCandidateBranch + '/' + data.substitutions.SHORT_SHA + '>' 22 | 23 | if (data.status === 'QUEUED') { 24 | resText = 'Production rollout `' + LOGS('queued') 25 | + '` for ' + commitLink; 26 | } else if (data.status === 'WORKING') { 27 | resText = 'Production rollout in `' + LOGS('progress') 28 | + '` for ' + commitLink; 29 | resColor = config.colors.QUEUED; 30 | } else if (data.status === 'SUCCESS') { 31 | resText = 'Production rollout `' + LOGS('successful') 32 | + '` for ' + commitLink; 33 | 34 | if (data.status === 'SUCCESS') { 35 | resText = resText + '\n Click <' + repo.productionEnvUrl + '|here> to go to production environment' 36 | } 37 | 38 | resColor = config.colors.SUCCESS; 39 | } else if (data.status === 'FAILURE') { 40 | let failedStep = getFailedStep(data); 41 | resText = 'Production rollout `' + LOGS('failed') 42 | + '` for ' + commitLink + ' in stage `' + failedStep.id + '`'; 43 | resColor = config.colors.FAILURE; 44 | } 45 | 46 | if (resText) await slack_utils.sendSlackMsg({ 47 | 'attachments': [{ 48 | 'fallback': resText, 49 | 'text': resText, 50 | 'color': resColor 51 | }] 52 | }, repo.channel); 53 | } 54 | 55 | const handleBranchAndPRBuilds = async (data, repo) => { 56 | let resText = undefined; 57 | let resColor = undefined; 58 | 59 | const LOGS = (name) => '<' + data.logUrl + '|' + name + '>'; 60 | 61 | let slug = ''; 62 | if (data.substitutions._PR_NUMBER) { 63 | const PR_LINK = '<' + repo.repoLink + 'pull/' + data.substitutions._PR_NUMBER 64 | + '|' + repo.name + '/pull/' + data.substitutions._PR_NUMBER + '>'; 65 | if (data.status === 'QUEUED' || data.status === 'FAILURE' || data.status === 'WORKING') slug = 'pull request ' + PR_LINK; 66 | else if (data.status === 'SUCCESS') slug = 'pull request ' + PR_LINK + ', ready to merge!'; 67 | } else { 68 | const commitLink = '<' + repo.repoLink + 'commit/' + data.substitutions.SHORT_SHA 69 | + '|' + repo.name + '/' + data.substitutions.BRANCH_NAME + '/' + data.substitutions.SHORT_SHA +'>'; 70 | slug = commitLink; 71 | 72 | if (data.status === 'SUCCESS') { 73 | slug = slug + '\n Click <' + repo.stagingEnvUrl + '|here> to go to staging environment' 74 | } 75 | } 76 | 77 | if (data.status === 'QUEUED') { 78 | resText = 'Build `' + LOGS('queued') + '` for ' + slug; 79 | resColor = config.colors.QUEUED; 80 | } else if (data.status === 'WORKING') { 81 | resText = 'Build in `' + LOGS('progress') + '` for ' + slug; 82 | resColor = config.colors.QUEUED; 83 | } else if (data.status === 'SUCCESS') { 84 | resText = 'Build `' + LOGS('successful') + '` for ' + slug; 85 | resColor = config.colors.SUCCESS; 86 | } else if (data.status === 'FAILURE') { 87 | let failedStep = getFailedStep(data); 88 | resText = 'Build `' + LOGS('failed') + '` for ' + slug + ' in stage `' + failedStep.id + '`'; 89 | resColor = config.colors.FAILURE; 90 | } 91 | 92 | if (resText) await slack_utils.sendSlackMsg({ 93 | 'attachments': [{ 94 | 'fallback': resText, 95 | 'text': resText, 96 | 'color': resColor 97 | }] 98 | }, repo.channel); 99 | 100 | if (data.status === 'SUCCESS' 101 | && !data.substitutions._PR_NUMBER 102 | && repo.deploymentSourceBranch == data.substitutions.BRANCH_NAME) { 103 | await scanning.scanProgress(repo, data); 104 | } 105 | } 106 | 107 | module.exports = { 108 | handleBranchAndPRBuilds: handleBranchAndPRBuilds, 109 | handleProductionDeployment: handleProductionDeployment 110 | } 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cloud Native CI/CD on GCP 2 | 3 | ## Overview 4 | 5 | This repository contains code for the sample application and the cloud functions used during the demo of the Cloud Native CI/CD talk given by Vishal Parpia at the Google Cloud Summit Singapore ‘19. 6 | 7 | The /app folder contains the sample NodeJs application along with the CloudBuild yaml, Docker files and Kubernetes yaml. The application has some unit tests and integration tests defined which are checked during the build process. 8 | 9 | The /functions folder contains the code for the Cloud Functions to listen to Cloudbuild updates and Slack approval events. 10 | 11 | 12 | ## Process Flow 13 | 14 | The source for the application to be deployed is this GitHub repository. When a pull request is raised to the master branch it triggers CloudBuild to build and test code based on the PR. If it is successful then the user can merge the PR into the master branch. 15 | 16 | Merging the PR triggers another CloudBuild to perform unit tests, build the Docker image, push the image to Google Container Repository, deploy it to Kubernetes pods for the staging environment and then perform integration tests. 17 | 18 | Notifications at each stage are sent to a Slack channel. 19 | 20 | The user can now decide if he wants to roll out the build to production, this can be done by clicking on YES or NO action buttons which will be showing in the Slack channel to approve the rollout. If the rollout is approved then another CloudBuild trigger is executed which deploys it to Kubernetes pods for the production environment. 21 | 22 | ## Architecture 23 | 24 | ![Architecture](docs/arch.png) 25 | 26 | ## Setup Instructions 27 | 28 | ### Setting up GitHub Repository 29 | 30 | * Generate an SSH key using `ssh-keygen -t rsa -b 4096 -C “a@b.com”` 31 | * Add the public part of key generated above in Repository’s Deploy Keys (Settings -> Deploy Keys -> Add Key) 32 | * Encrypt the private part of key using Google KMS 33 | * Create a keyring 34 | 35 | ```gcloud kms keyrings create {keyring_name} --location=global``` 36 | 37 | * Create key 38 | 39 | ```gcloud kms keys create {key_name} --location=global --keyring={keyring_name} --purpose=encryption``` 40 | 41 | * Whitelist cloudbuild service account to decrypt the above key. This can be done as: 42 | 43 | In GCP Console: IAM -> Cryptographic keys -> {keyring_name} -> {key_name} -> Show Info Panel -> Add Member -> Give Decrypter permission to cloudbuild service account 44 | 45 | * Encrypt your private key 46 | 47 | ```gcloud kms encrypt --plaintext-file={private_key_path} --ciphertext-file={enc_key_path} --location=global --keyring={keyring_name} --key={key_name}``` 48 | 49 | * Replace the encrypted key at path `app/repo-key-encrypted` with your key 50 | 51 | * Create `production-candidate` branch. Replace the encrypted key generated and production kubernetes.yaml file and push it to repo. 52 | * Create `production` branch and push it (can be empty). Production configs are stored here 53 | 54 | ```Note: production-candidate and production branches should ideally be in different repository as it holds production configuration. The key added to production-candidate branch is for the repo holding production config.``` 55 | 56 | ### Create GKE Clusters 57 | 58 | Create two clusters, one for staging environment and other for production. Not down cluster names and deployment zones 59 | 60 | ### Connecting Repository to CloudBuild 61 | 62 | * Cloudbuild -> Triggers -> Connect Repository -> check GitHub App by Google -> Authenticate -> Select your repository -> Skip creating triggers for now 63 | Create Triggers 64 | * Create Trigger for Push on master branch. With following details 65 | 66 | ``` 67 | Type: Branch 68 | Regex: master 69 | 70 | Cloudbuild config path: app/cloudbuild-master.yml 71 | Substitution Vars: 72 | _APP_DIR: app 73 | _GITHUB_REPO_ENC_KEY_PATH: app/repo-key-encrypted/id_rsa_repo_key.enc 74 | _GITHUB_REPO_KEY: {key_name} 75 | _GITHUB_REPO_KMS_KEYRING: {keyring_name} 76 | _GITHUB_REPO_USERNAME: cldcvr 77 | _IMAGE_ID: gcp-cnci-example-app 78 | _PRODUCTION_CANDIDATE_BRANCH: production-candidate 79 | _PRODUCTION_KUBERENETES_TEMPLATE_FILE_NAME: kubernetes.yaml.tpl 80 | _PRODUCTION_KUBERNETES_CONFIG_FILE_NAME: kubernetes.yaml 81 | _STAGING_DEPLOY_CLUSTER: {STAGING_GKE_CLUSTER_NAME} 82 | _STAGING_DEPLOY_ZONE: {STAGING_GKE_CLUSTER_ZONE} 83 | _STAGING_KUBERENETES_TEMPLATE_FILE_NAME: staging-kubernetes.yaml.tpl 84 | _STAGING_KUBERNETES_CONFIG_FILE_NAME: staging-kubernetes.yaml 85 | ``` 86 | * Create Trigger for PR on master with details: 87 | 88 | ``` 89 | Type: Pull Request 90 | Regex: master 91 | 92 | Cloudbuild config: app/cloudbuild-master-pr.yml 93 | Substitution Vars: 94 | _APP_DIR: app 95 | ``` 96 | * Create Trigger for push on production-candidate with details 97 | 98 | ``` 99 | Type: Branch 100 | Regex: random_string. Note: Put random non existent branch. We will be firing this trigger manually. Note down the trigger name. 101 | 102 | Cloudbuild config: cloudbuild-delivery.yml 103 | Substitution vars: 104 | _GITHUB_REPO_ENC_KEY_PATH: repo-key-encrypted/id_rsa_repo_key.enc 105 | _GITHUB_REPO_KEY: {prod_config_repo_key_name} 106 | _GITHUB_REPO_KMS_KEYRING: {prod_config_repo_keyring_name} 107 | _GITHUB_REPO_USERNAME: cldcvr 108 | _PRODUCTION_BRANCH: production 109 | _PRODUCTION_DEPLOY_CLUSTER: {PRODUCTION_GKE_CLUSTER_NAME} 110 | _PRODUCTION_DEPLOY_ZONE: {PRODUCTION_GKE_CLUSTER_ZONE} 111 | _PRODUCTION_KUBERNETES_CONFIG_FILE_NAME: kubernetes.yaml 112 | ``` 113 | 114 | ### Generate Slack Bot User Token 115 | 116 | You can get the bot user token using OAuth2 or from your slack app dashboard (if you are using bot for your own workspace). For more information see: https://api.slack.com/docs/oauth#bots 117 | 118 | ### Deploy Cloudfunctions 119 | 120 | * Replace trigger name in `functions/repos.js` with your production trigger name. 121 | * Deploy Functions 122 | * Slack Approval Events Listener 123 | 124 | ``` 125 | cd functions 126 | gcloud functions deploy gcpCiCdApprovalAction --runtime nodejs10 --trigger-http --set-env-vars SLACK_BOT_TOKEN='{BOT_TOKEN}' --set-env-vars GCLOUD_PROJECT='{PROJECT_ID}' --service-account={CLOUDFUNCTION_SERVICE_ACCOUNT} 127 | ``` 128 | * CloudBuild Event Listener 129 | 130 | ``` 131 | cd functions 132 | gcloud functions deploy gcpCiCdSlackEvents --runtime nodejs10 --trigger-topic cloud-builds --set-env-vars SLACK_BOT_TOKEN='{BOT_TOKEN}' --set-env-vars GCLOUD_PROJECT='cloudcover-sandbox' --service-account={CLOUDFUNCTION_SERVICE_ACCOUNT} 133 | ``` 134 | 135 | ## Demos 136 | 137 | Talk - Google Cloud Summit Singapore ‘19 [[Video](https://www.youtube.com/watch?v=4swRBoiP8tQ&feature=youtu.be)] 138 | 139 | ## Screenshots 140 | 141 | ![Slack Notification for CI/CD Events](docs/slack.png) 142 | 143 | -------------------------------------------------------------------------------- /app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= hello.environment %> gcp-cnci demo 7 | 8 | 68 |
69 | 70 | 77 | 78 | 79 | 81 | 82 | 83 | 84 | 85 | 88 | 89 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 112 | 113 | 114 | 115 | 116 | 117 | 119 | 120 | 121 | 124 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 136 | 139 | 140 | 141 | 142 | 143 |
144 | 145 |
146 |
147 |

<%= hello.msg %>

148 |
149 |
150 | -------------------------------------------------------------------------------- /app/views/index_dark.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= hello.environment %> gcp-cnci demo 7 | 8 | 69 |
70 | 71 | 79 | 80 | 81 | 83 | 84 | 85 | 86 | 87 | 90 | 91 | 92 | 93 | 94 | 97 | 98 | 99 | 100 | 101 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 114 | 115 | 116 | 117 | 118 | 119 | 121 | 122 | 123 | 126 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 138 | 141 | 142 | 143 | 144 | 145 |
146 | 147 |
148 |
149 |

<%= hello.msg %>

150 |
151 |
152 | -------------------------------------------------------------------------------- /app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcp-cnci-example-app", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "ansi-colors": { 17 | "version": "3.2.3", 18 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", 19 | "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", 20 | "dev": true 21 | }, 22 | "ansi-regex": { 23 | "version": "3.0.0", 24 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 25 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 26 | "dev": true 27 | }, 28 | "ansi-styles": { 29 | "version": "3.2.1", 30 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 31 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 32 | "dev": true, 33 | "requires": { 34 | "color-convert": "^1.9.0" 35 | } 36 | }, 37 | "argparse": { 38 | "version": "1.0.10", 39 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 40 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 41 | "dev": true, 42 | "requires": { 43 | "sprintf-js": "~1.0.2" 44 | } 45 | }, 46 | "array-flatten": { 47 | "version": "1.1.1", 48 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 49 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 50 | }, 51 | "axios": { 52 | "version": "0.19.2", 53 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", 54 | "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", 55 | "dev": true, 56 | "requires": { 57 | "follow-redirects": "1.5.10" 58 | } 59 | }, 60 | "balanced-match": { 61 | "version": "1.0.0", 62 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 63 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 64 | "dev": true 65 | }, 66 | "body-parser": { 67 | "version": "1.19.0", 68 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 69 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 70 | "requires": { 71 | "bytes": "3.1.0", 72 | "content-type": "~1.0.4", 73 | "debug": "2.6.9", 74 | "depd": "~1.1.2", 75 | "http-errors": "1.7.2", 76 | "iconv-lite": "0.4.24", 77 | "on-finished": "~2.3.0", 78 | "qs": "6.7.0", 79 | "raw-body": "2.4.0", 80 | "type-is": "~1.6.17" 81 | } 82 | }, 83 | "brace-expansion": { 84 | "version": "1.1.11", 85 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 86 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 87 | "dev": true, 88 | "requires": { 89 | "balanced-match": "^1.0.0", 90 | "concat-map": "0.0.1" 91 | } 92 | }, 93 | "browser-stdout": { 94 | "version": "1.3.1", 95 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 96 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 97 | "dev": true 98 | }, 99 | "bytes": { 100 | "version": "3.1.0", 101 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 102 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 103 | }, 104 | "camelcase": { 105 | "version": "5.3.1", 106 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 107 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 108 | "dev": true 109 | }, 110 | "chalk": { 111 | "version": "2.4.2", 112 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 113 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 114 | "dev": true, 115 | "requires": { 116 | "ansi-styles": "^3.2.1", 117 | "escape-string-regexp": "^1.0.5", 118 | "supports-color": "^5.3.0" 119 | }, 120 | "dependencies": { 121 | "supports-color": { 122 | "version": "5.5.0", 123 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 124 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 125 | "dev": true, 126 | "requires": { 127 | "has-flag": "^3.0.0" 128 | } 129 | } 130 | } 131 | }, 132 | "cliui": { 133 | "version": "5.0.0", 134 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 135 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 136 | "dev": true, 137 | "requires": { 138 | "string-width": "^3.1.0", 139 | "strip-ansi": "^5.2.0", 140 | "wrap-ansi": "^5.1.0" 141 | }, 142 | "dependencies": { 143 | "ansi-regex": { 144 | "version": "4.1.0", 145 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 146 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 147 | "dev": true 148 | }, 149 | "string-width": { 150 | "version": "3.1.0", 151 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 152 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 153 | "dev": true, 154 | "requires": { 155 | "emoji-regex": "^7.0.1", 156 | "is-fullwidth-code-point": "^2.0.0", 157 | "strip-ansi": "^5.1.0" 158 | } 159 | }, 160 | "strip-ansi": { 161 | "version": "5.2.0", 162 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 163 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 164 | "dev": true, 165 | "requires": { 166 | "ansi-regex": "^4.1.0" 167 | } 168 | } 169 | } 170 | }, 171 | "color-convert": { 172 | "version": "1.9.3", 173 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 174 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 175 | "dev": true, 176 | "requires": { 177 | "color-name": "1.1.3" 178 | } 179 | }, 180 | "color-name": { 181 | "version": "1.1.3", 182 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 183 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 184 | "dev": true 185 | }, 186 | "concat-map": { 187 | "version": "0.0.1", 188 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 189 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 190 | "dev": true 191 | }, 192 | "content-disposition": { 193 | "version": "0.5.3", 194 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 195 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 196 | "requires": { 197 | "safe-buffer": "5.1.2" 198 | } 199 | }, 200 | "content-type": { 201 | "version": "1.0.4", 202 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 203 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 204 | }, 205 | "cookie": { 206 | "version": "0.4.0", 207 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 208 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 209 | }, 210 | "cookie-signature": { 211 | "version": "1.0.6", 212 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 213 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 214 | }, 215 | "debug": { 216 | "version": "2.6.9", 217 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 218 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 219 | "requires": { 220 | "ms": "2.0.0" 221 | } 222 | }, 223 | "decamelize": { 224 | "version": "1.2.0", 225 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 226 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 227 | "dev": true 228 | }, 229 | "define-properties": { 230 | "version": "1.1.3", 231 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 232 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 233 | "dev": true, 234 | "requires": { 235 | "object-keys": "^1.0.12" 236 | } 237 | }, 238 | "depd": { 239 | "version": "1.1.2", 240 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 241 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 242 | }, 243 | "destroy": { 244 | "version": "1.0.4", 245 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 246 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 247 | }, 248 | "diff": { 249 | "version": "3.5.0", 250 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 251 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 252 | "dev": true 253 | }, 254 | "ee-first": { 255 | "version": "1.1.1", 256 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 257 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 258 | }, 259 | "ejs": { 260 | "version": "2.7.4", 261 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", 262 | "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" 263 | }, 264 | "emoji-regex": { 265 | "version": "7.0.3", 266 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 267 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 268 | "dev": true 269 | }, 270 | "encodeurl": { 271 | "version": "1.0.2", 272 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 273 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 274 | }, 275 | "es-abstract": { 276 | "version": "1.17.5", 277 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", 278 | "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", 279 | "dev": true, 280 | "requires": { 281 | "es-to-primitive": "^1.2.1", 282 | "function-bind": "^1.1.1", 283 | "has": "^1.0.3", 284 | "has-symbols": "^1.0.1", 285 | "is-callable": "^1.1.5", 286 | "is-regex": "^1.0.5", 287 | "object-inspect": "^1.7.0", 288 | "object-keys": "^1.1.1", 289 | "object.assign": "^4.1.0", 290 | "string.prototype.trimleft": "^2.1.1", 291 | "string.prototype.trimright": "^2.1.1" 292 | } 293 | }, 294 | "es-to-primitive": { 295 | "version": "1.2.1", 296 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 297 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 298 | "dev": true, 299 | "requires": { 300 | "is-callable": "^1.1.4", 301 | "is-date-object": "^1.0.1", 302 | "is-symbol": "^1.0.2" 303 | } 304 | }, 305 | "escape-html": { 306 | "version": "1.0.3", 307 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 308 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 309 | }, 310 | "escape-string-regexp": { 311 | "version": "1.0.5", 312 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 313 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 314 | "dev": true 315 | }, 316 | "esprima": { 317 | "version": "4.0.1", 318 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 319 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 320 | "dev": true 321 | }, 322 | "etag": { 323 | "version": "1.8.1", 324 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 325 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 326 | }, 327 | "express": { 328 | "version": "4.17.1", 329 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 330 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 331 | "requires": { 332 | "accepts": "~1.3.7", 333 | "array-flatten": "1.1.1", 334 | "body-parser": "1.19.0", 335 | "content-disposition": "0.5.3", 336 | "content-type": "~1.0.4", 337 | "cookie": "0.4.0", 338 | "cookie-signature": "1.0.6", 339 | "debug": "2.6.9", 340 | "depd": "~1.1.2", 341 | "encodeurl": "~1.0.2", 342 | "escape-html": "~1.0.3", 343 | "etag": "~1.8.1", 344 | "finalhandler": "~1.1.2", 345 | "fresh": "0.5.2", 346 | "merge-descriptors": "1.0.1", 347 | "methods": "~1.1.2", 348 | "on-finished": "~2.3.0", 349 | "parseurl": "~1.3.3", 350 | "path-to-regexp": "0.1.7", 351 | "proxy-addr": "~2.0.5", 352 | "qs": "6.7.0", 353 | "range-parser": "~1.2.1", 354 | "safe-buffer": "5.1.2", 355 | "send": "0.17.1", 356 | "serve-static": "1.14.1", 357 | "setprototypeof": "1.1.1", 358 | "statuses": "~1.5.0", 359 | "type-is": "~1.6.18", 360 | "utils-merge": "1.0.1", 361 | "vary": "~1.1.2" 362 | } 363 | }, 364 | "finalhandler": { 365 | "version": "1.1.2", 366 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 367 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 368 | "requires": { 369 | "debug": "2.6.9", 370 | "encodeurl": "~1.0.2", 371 | "escape-html": "~1.0.3", 372 | "on-finished": "~2.3.0", 373 | "parseurl": "~1.3.3", 374 | "statuses": "~1.5.0", 375 | "unpipe": "~1.0.0" 376 | } 377 | }, 378 | "find-up": { 379 | "version": "3.0.0", 380 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 381 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 382 | "dev": true, 383 | "requires": { 384 | "locate-path": "^3.0.0" 385 | } 386 | }, 387 | "flat": { 388 | "version": "4.1.0", 389 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 390 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 391 | "dev": true, 392 | "requires": { 393 | "is-buffer": "~2.0.3" 394 | } 395 | }, 396 | "follow-redirects": { 397 | "version": "1.5.10", 398 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", 399 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", 400 | "dev": true, 401 | "requires": { 402 | "debug": "=3.1.0" 403 | }, 404 | "dependencies": { 405 | "debug": { 406 | "version": "3.1.0", 407 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 408 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 409 | "dev": true, 410 | "requires": { 411 | "ms": "2.0.0" 412 | } 413 | } 414 | } 415 | }, 416 | "forwarded": { 417 | "version": "0.1.2", 418 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 419 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 420 | }, 421 | "fresh": { 422 | "version": "0.5.2", 423 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 424 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 425 | }, 426 | "fs.realpath": { 427 | "version": "1.0.0", 428 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 429 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 430 | "dev": true 431 | }, 432 | "function-bind": { 433 | "version": "1.1.1", 434 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 435 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 436 | "dev": true 437 | }, 438 | "get-caller-file": { 439 | "version": "2.0.5", 440 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 441 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 442 | "dev": true 443 | }, 444 | "glob": { 445 | "version": "7.1.3", 446 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 447 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 448 | "dev": true, 449 | "requires": { 450 | "fs.realpath": "^1.0.0", 451 | "inflight": "^1.0.4", 452 | "inherits": "2", 453 | "minimatch": "^3.0.4", 454 | "once": "^1.3.0", 455 | "path-is-absolute": "^1.0.0" 456 | } 457 | }, 458 | "growl": { 459 | "version": "1.10.5", 460 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 461 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 462 | "dev": true 463 | }, 464 | "has": { 465 | "version": "1.0.3", 466 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 467 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 468 | "dev": true, 469 | "requires": { 470 | "function-bind": "^1.1.1" 471 | } 472 | }, 473 | "has-flag": { 474 | "version": "3.0.0", 475 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 476 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 477 | "dev": true 478 | }, 479 | "has-symbols": { 480 | "version": "1.0.1", 481 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 482 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", 483 | "dev": true 484 | }, 485 | "he": { 486 | "version": "1.2.0", 487 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 488 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 489 | "dev": true 490 | }, 491 | "http-errors": { 492 | "version": "1.7.2", 493 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 494 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 495 | "requires": { 496 | "depd": "~1.1.2", 497 | "inherits": "2.0.3", 498 | "setprototypeof": "1.1.1", 499 | "statuses": ">= 1.5.0 < 2", 500 | "toidentifier": "1.0.0" 501 | } 502 | }, 503 | "iconv-lite": { 504 | "version": "0.4.24", 505 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 506 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 507 | "requires": { 508 | "safer-buffer": ">= 2.1.2 < 3" 509 | } 510 | }, 511 | "inflight": { 512 | "version": "1.0.6", 513 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 514 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 515 | "dev": true, 516 | "requires": { 517 | "once": "^1.3.0", 518 | "wrappy": "1" 519 | } 520 | }, 521 | "inherits": { 522 | "version": "2.0.3", 523 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 524 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 525 | }, 526 | "ipaddr.js": { 527 | "version": "1.9.1", 528 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 529 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 530 | }, 531 | "is-buffer": { 532 | "version": "2.0.4", 533 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 534 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", 535 | "dev": true 536 | }, 537 | "is-callable": { 538 | "version": "1.1.5", 539 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", 540 | "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", 541 | "dev": true 542 | }, 543 | "is-date-object": { 544 | "version": "1.0.2", 545 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 546 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", 547 | "dev": true 548 | }, 549 | "is-fullwidth-code-point": { 550 | "version": "2.0.0", 551 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 552 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 553 | "dev": true 554 | }, 555 | "is-regex": { 556 | "version": "1.0.5", 557 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", 558 | "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", 559 | "dev": true, 560 | "requires": { 561 | "has": "^1.0.3" 562 | } 563 | }, 564 | "is-symbol": { 565 | "version": "1.0.3", 566 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 567 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 568 | "dev": true, 569 | "requires": { 570 | "has-symbols": "^1.0.1" 571 | } 572 | }, 573 | "isexe": { 574 | "version": "2.0.0", 575 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 576 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 577 | "dev": true 578 | }, 579 | "js-yaml": { 580 | "version": "3.13.1", 581 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 582 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 583 | "dev": true, 584 | "requires": { 585 | "argparse": "^1.0.7", 586 | "esprima": "^4.0.0" 587 | } 588 | }, 589 | "locate-path": { 590 | "version": "3.0.0", 591 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 592 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 593 | "dev": true, 594 | "requires": { 595 | "p-locate": "^3.0.0", 596 | "path-exists": "^3.0.0" 597 | } 598 | }, 599 | "lodash": { 600 | "version": "4.17.15", 601 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 602 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 603 | "dev": true 604 | }, 605 | "log-symbols": { 606 | "version": "2.2.0", 607 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", 608 | "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", 609 | "dev": true, 610 | "requires": { 611 | "chalk": "^2.0.1" 612 | } 613 | }, 614 | "media-typer": { 615 | "version": "0.3.0", 616 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 617 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 618 | }, 619 | "merge-descriptors": { 620 | "version": "1.0.1", 621 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 622 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 623 | }, 624 | "methods": { 625 | "version": "1.1.2", 626 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 627 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 628 | }, 629 | "mime": { 630 | "version": "1.6.0", 631 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 632 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 633 | }, 634 | "mime-db": { 635 | "version": "1.43.0", 636 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 637 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 638 | }, 639 | "mime-types": { 640 | "version": "2.1.26", 641 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 642 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 643 | "requires": { 644 | "mime-db": "1.43.0" 645 | } 646 | }, 647 | "minimatch": { 648 | "version": "3.0.4", 649 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 650 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 651 | "dev": true, 652 | "requires": { 653 | "brace-expansion": "^1.1.7" 654 | } 655 | }, 656 | "minimist": { 657 | "version": "1.2.5", 658 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 659 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 660 | "dev": true 661 | }, 662 | "mkdirp": { 663 | "version": "0.5.4", 664 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", 665 | "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", 666 | "dev": true, 667 | "requires": { 668 | "minimist": "^1.2.5" 669 | } 670 | }, 671 | "mocha": { 672 | "version": "6.2.3", 673 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", 674 | "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", 675 | "dev": true, 676 | "requires": { 677 | "ansi-colors": "3.2.3", 678 | "browser-stdout": "1.3.1", 679 | "debug": "3.2.6", 680 | "diff": "3.5.0", 681 | "escape-string-regexp": "1.0.5", 682 | "find-up": "3.0.0", 683 | "glob": "7.1.3", 684 | "growl": "1.10.5", 685 | "he": "1.2.0", 686 | "js-yaml": "3.13.1", 687 | "log-symbols": "2.2.0", 688 | "minimatch": "3.0.4", 689 | "mkdirp": "0.5.4", 690 | "ms": "2.1.1", 691 | "node-environment-flags": "1.0.5", 692 | "object.assign": "4.1.0", 693 | "strip-json-comments": "2.0.1", 694 | "supports-color": "6.0.0", 695 | "which": "1.3.1", 696 | "wide-align": "1.1.3", 697 | "yargs": "13.3.2", 698 | "yargs-parser": "13.1.2", 699 | "yargs-unparser": "1.6.0" 700 | }, 701 | "dependencies": { 702 | "debug": { 703 | "version": "3.2.6", 704 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 705 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 706 | "dev": true, 707 | "requires": { 708 | "ms": "^2.1.1" 709 | } 710 | }, 711 | "ms": { 712 | "version": "2.1.1", 713 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 714 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 715 | "dev": true 716 | } 717 | } 718 | }, 719 | "ms": { 720 | "version": "2.0.0", 721 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 722 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 723 | }, 724 | "negotiator": { 725 | "version": "0.6.2", 726 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 727 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 728 | }, 729 | "node-environment-flags": { 730 | "version": "1.0.5", 731 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", 732 | "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", 733 | "dev": true, 734 | "requires": { 735 | "object.getownpropertydescriptors": "^2.0.3", 736 | "semver": "^5.7.0" 737 | } 738 | }, 739 | "object-inspect": { 740 | "version": "1.7.0", 741 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 742 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", 743 | "dev": true 744 | }, 745 | "object-keys": { 746 | "version": "1.1.1", 747 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 748 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 749 | "dev": true 750 | }, 751 | "object.assign": { 752 | "version": "4.1.0", 753 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 754 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 755 | "dev": true, 756 | "requires": { 757 | "define-properties": "^1.1.2", 758 | "function-bind": "^1.1.1", 759 | "has-symbols": "^1.0.0", 760 | "object-keys": "^1.0.11" 761 | } 762 | }, 763 | "object.getownpropertydescriptors": { 764 | "version": "2.1.0", 765 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", 766 | "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", 767 | "dev": true, 768 | "requires": { 769 | "define-properties": "^1.1.3", 770 | "es-abstract": "^1.17.0-next.1" 771 | } 772 | }, 773 | "on-finished": { 774 | "version": "2.3.0", 775 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 776 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 777 | "requires": { 778 | "ee-first": "1.1.1" 779 | } 780 | }, 781 | "once": { 782 | "version": "1.4.0", 783 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 784 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 785 | "dev": true, 786 | "requires": { 787 | "wrappy": "1" 788 | } 789 | }, 790 | "p-limit": { 791 | "version": "2.3.0", 792 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 793 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 794 | "dev": true, 795 | "requires": { 796 | "p-try": "^2.0.0" 797 | } 798 | }, 799 | "p-locate": { 800 | "version": "3.0.0", 801 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 802 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 803 | "dev": true, 804 | "requires": { 805 | "p-limit": "^2.0.0" 806 | } 807 | }, 808 | "p-try": { 809 | "version": "2.2.0", 810 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 811 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 812 | "dev": true 813 | }, 814 | "parseurl": { 815 | "version": "1.3.3", 816 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 817 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 818 | }, 819 | "path-exists": { 820 | "version": "3.0.0", 821 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 822 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 823 | "dev": true 824 | }, 825 | "path-is-absolute": { 826 | "version": "1.0.1", 827 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 828 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 829 | "dev": true 830 | }, 831 | "path-to-regexp": { 832 | "version": "0.1.7", 833 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 834 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 835 | }, 836 | "proxy-addr": { 837 | "version": "2.0.6", 838 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 839 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 840 | "requires": { 841 | "forwarded": "~0.1.2", 842 | "ipaddr.js": "1.9.1" 843 | } 844 | }, 845 | "qs": { 846 | "version": "6.7.0", 847 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 848 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 849 | }, 850 | "range-parser": { 851 | "version": "1.2.1", 852 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 853 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 854 | }, 855 | "raw-body": { 856 | "version": "2.4.0", 857 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 858 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 859 | "requires": { 860 | "bytes": "3.1.0", 861 | "http-errors": "1.7.2", 862 | "iconv-lite": "0.4.24", 863 | "unpipe": "1.0.0" 864 | } 865 | }, 866 | "require-directory": { 867 | "version": "2.1.1", 868 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 869 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 870 | "dev": true 871 | }, 872 | "require-main-filename": { 873 | "version": "2.0.0", 874 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 875 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 876 | "dev": true 877 | }, 878 | "safe-buffer": { 879 | "version": "5.1.2", 880 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 881 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 882 | }, 883 | "safer-buffer": { 884 | "version": "2.1.2", 885 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 886 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 887 | }, 888 | "semver": { 889 | "version": "5.7.1", 890 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 891 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 892 | "dev": true 893 | }, 894 | "send": { 895 | "version": "0.17.1", 896 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 897 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 898 | "requires": { 899 | "debug": "2.6.9", 900 | "depd": "~1.1.2", 901 | "destroy": "~1.0.4", 902 | "encodeurl": "~1.0.2", 903 | "escape-html": "~1.0.3", 904 | "etag": "~1.8.1", 905 | "fresh": "0.5.2", 906 | "http-errors": "~1.7.2", 907 | "mime": "1.6.0", 908 | "ms": "2.1.1", 909 | "on-finished": "~2.3.0", 910 | "range-parser": "~1.2.1", 911 | "statuses": "~1.5.0" 912 | }, 913 | "dependencies": { 914 | "ms": { 915 | "version": "2.1.1", 916 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 917 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 918 | } 919 | } 920 | }, 921 | "serve-static": { 922 | "version": "1.14.1", 923 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 924 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 925 | "requires": { 926 | "encodeurl": "~1.0.2", 927 | "escape-html": "~1.0.3", 928 | "parseurl": "~1.3.3", 929 | "send": "0.17.1" 930 | } 931 | }, 932 | "set-blocking": { 933 | "version": "2.0.0", 934 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 935 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 936 | "dev": true 937 | }, 938 | "setprototypeof": { 939 | "version": "1.1.1", 940 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 941 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 942 | }, 943 | "sprintf-js": { 944 | "version": "1.0.3", 945 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 946 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 947 | "dev": true 948 | }, 949 | "statuses": { 950 | "version": "1.5.0", 951 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 952 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 953 | }, 954 | "string-width": { 955 | "version": "2.1.1", 956 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 957 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 958 | "dev": true, 959 | "requires": { 960 | "is-fullwidth-code-point": "^2.0.0", 961 | "strip-ansi": "^4.0.0" 962 | } 963 | }, 964 | "string.prototype.trimend": { 965 | "version": "1.0.0", 966 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz", 967 | "integrity": "sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==", 968 | "dev": true, 969 | "requires": { 970 | "define-properties": "^1.1.3", 971 | "es-abstract": "^1.17.5" 972 | } 973 | }, 974 | "string.prototype.trimleft": { 975 | "version": "2.1.2", 976 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", 977 | "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", 978 | "dev": true, 979 | "requires": { 980 | "define-properties": "^1.1.3", 981 | "es-abstract": "^1.17.5", 982 | "string.prototype.trimstart": "^1.0.0" 983 | } 984 | }, 985 | "string.prototype.trimright": { 986 | "version": "2.1.2", 987 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", 988 | "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", 989 | "dev": true, 990 | "requires": { 991 | "define-properties": "^1.1.3", 992 | "es-abstract": "^1.17.5", 993 | "string.prototype.trimend": "^1.0.0" 994 | } 995 | }, 996 | "string.prototype.trimstart": { 997 | "version": "1.0.0", 998 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz", 999 | "integrity": "sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w==", 1000 | "dev": true, 1001 | "requires": { 1002 | "define-properties": "^1.1.3", 1003 | "es-abstract": "^1.17.5" 1004 | } 1005 | }, 1006 | "strip-ansi": { 1007 | "version": "4.0.0", 1008 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1009 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1010 | "dev": true, 1011 | "requires": { 1012 | "ansi-regex": "^3.0.0" 1013 | } 1014 | }, 1015 | "strip-json-comments": { 1016 | "version": "2.0.1", 1017 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1018 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1019 | "dev": true 1020 | }, 1021 | "supports-color": { 1022 | "version": "6.0.0", 1023 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", 1024 | "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", 1025 | "dev": true, 1026 | "requires": { 1027 | "has-flag": "^3.0.0" 1028 | } 1029 | }, 1030 | "toidentifier": { 1031 | "version": "1.0.0", 1032 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1033 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1034 | }, 1035 | "type-is": { 1036 | "version": "1.6.18", 1037 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1038 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1039 | "requires": { 1040 | "media-typer": "0.3.0", 1041 | "mime-types": "~2.1.24" 1042 | } 1043 | }, 1044 | "unpipe": { 1045 | "version": "1.0.0", 1046 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1047 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1048 | }, 1049 | "utils-merge": { 1050 | "version": "1.0.1", 1051 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1052 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1053 | }, 1054 | "vary": { 1055 | "version": "1.1.2", 1056 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1057 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1058 | }, 1059 | "which": { 1060 | "version": "1.3.1", 1061 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1062 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1063 | "dev": true, 1064 | "requires": { 1065 | "isexe": "^2.0.0" 1066 | } 1067 | }, 1068 | "which-module": { 1069 | "version": "2.0.0", 1070 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1071 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1072 | "dev": true 1073 | }, 1074 | "wide-align": { 1075 | "version": "1.1.3", 1076 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1077 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1078 | "dev": true, 1079 | "requires": { 1080 | "string-width": "^1.0.2 || 2" 1081 | } 1082 | }, 1083 | "wrap-ansi": { 1084 | "version": "5.1.0", 1085 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 1086 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 1087 | "dev": true, 1088 | "requires": { 1089 | "ansi-styles": "^3.2.0", 1090 | "string-width": "^3.0.0", 1091 | "strip-ansi": "^5.0.0" 1092 | }, 1093 | "dependencies": { 1094 | "ansi-regex": { 1095 | "version": "4.1.0", 1096 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1097 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1098 | "dev": true 1099 | }, 1100 | "string-width": { 1101 | "version": "3.1.0", 1102 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1103 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1104 | "dev": true, 1105 | "requires": { 1106 | "emoji-regex": "^7.0.1", 1107 | "is-fullwidth-code-point": "^2.0.0", 1108 | "strip-ansi": "^5.1.0" 1109 | } 1110 | }, 1111 | "strip-ansi": { 1112 | "version": "5.2.0", 1113 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1114 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1115 | "dev": true, 1116 | "requires": { 1117 | "ansi-regex": "^4.1.0" 1118 | } 1119 | } 1120 | } 1121 | }, 1122 | "wrappy": { 1123 | "version": "1.0.2", 1124 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1125 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1126 | "dev": true 1127 | }, 1128 | "y18n": { 1129 | "version": "4.0.0", 1130 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1131 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 1132 | "dev": true 1133 | }, 1134 | "yargs": { 1135 | "version": "13.3.2", 1136 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 1137 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 1138 | "dev": true, 1139 | "requires": { 1140 | "cliui": "^5.0.0", 1141 | "find-up": "^3.0.0", 1142 | "get-caller-file": "^2.0.1", 1143 | "require-directory": "^2.1.1", 1144 | "require-main-filename": "^2.0.0", 1145 | "set-blocking": "^2.0.0", 1146 | "string-width": "^3.0.0", 1147 | "which-module": "^2.0.0", 1148 | "y18n": "^4.0.0", 1149 | "yargs-parser": "^13.1.2" 1150 | }, 1151 | "dependencies": { 1152 | "ansi-regex": { 1153 | "version": "4.1.0", 1154 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1155 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1156 | "dev": true 1157 | }, 1158 | "string-width": { 1159 | "version": "3.1.0", 1160 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1161 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1162 | "dev": true, 1163 | "requires": { 1164 | "emoji-regex": "^7.0.1", 1165 | "is-fullwidth-code-point": "^2.0.0", 1166 | "strip-ansi": "^5.1.0" 1167 | } 1168 | }, 1169 | "strip-ansi": { 1170 | "version": "5.2.0", 1171 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1172 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1173 | "dev": true, 1174 | "requires": { 1175 | "ansi-regex": "^4.1.0" 1176 | } 1177 | } 1178 | } 1179 | }, 1180 | "yargs-parser": { 1181 | "version": "13.1.2", 1182 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 1183 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 1184 | "dev": true, 1185 | "requires": { 1186 | "camelcase": "^5.0.0", 1187 | "decamelize": "^1.2.0" 1188 | } 1189 | }, 1190 | "yargs-unparser": { 1191 | "version": "1.6.0", 1192 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", 1193 | "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", 1194 | "dev": true, 1195 | "requires": { 1196 | "flat": "^4.1.0", 1197 | "lodash": "^4.17.15", 1198 | "yargs": "^13.3.0" 1199 | } 1200 | } 1201 | } 1202 | } 1203 | -------------------------------------------------------------------------------- /functions/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcp-cicd-cloudfuncs", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@slack/logger": { 8 | "version": "2.0.0", 9 | "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-2.0.0.tgz", 10 | "integrity": "sha512-OkIJpiU2fz6HOJujhlhfIGrc8hB4ibqtf7nnbJQDerG0BqwZCfmgtK5sWzZ0TkXVRBKD5MpLrTmCYyMxoMCgPw==", 11 | "requires": { 12 | "@types/node": ">=8.9.0" 13 | } 14 | }, 15 | "@slack/types": { 16 | "version": "1.5.0", 17 | "resolved": "https://registry.npmjs.org/@slack/types/-/types-1.5.0.tgz", 18 | "integrity": "sha512-oCYgatJYxHf9wE3tKXzOLeeTsF0ghX1TIcguNfVmO2V6NDe+cHAzZRglEOmJLdRINDS5gscAgSkeZpDhpKBeUA==" 19 | }, 20 | "@slack/web-api": { 21 | "version": "5.8.0", 22 | "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-5.8.0.tgz", 23 | "integrity": "sha512-lUMFM9jtdn+9Q0kHLegf5RjIgQlmb1PGWwWdTsc9mQ8PJu2BogI5ZttG8/tA6r2bX/C4bgXhd0JJ4syUR0AAhQ==", 24 | "requires": { 25 | "@slack/logger": ">=1.0.0 <3.0.0", 26 | "@slack/types": "^1.2.1", 27 | "@types/is-stream": "^1.1.0", 28 | "@types/node": ">=8.9.0", 29 | "@types/p-queue": "^2.3.2", 30 | "axios": "^0.19.0", 31 | "eventemitter3": "^3.1.0", 32 | "form-data": "^2.5.0", 33 | "is-stream": "^1.1.0", 34 | "p-queue": "^2.4.2", 35 | "p-retry": "^4.0.0" 36 | } 37 | }, 38 | "@types/is-stream": { 39 | "version": "1.1.0", 40 | "resolved": "https://registry.npmjs.org/@types/is-stream/-/is-stream-1.1.0.tgz", 41 | "integrity": "sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==", 42 | "requires": { 43 | "@types/node": "*" 44 | } 45 | }, 46 | "@types/node": { 47 | "version": "13.11.1", 48 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", 49 | "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==" 50 | }, 51 | "@types/p-queue": { 52 | "version": "2.3.2", 53 | "resolved": "https://registry.npmjs.org/@types/p-queue/-/p-queue-2.3.2.tgz", 54 | "integrity": "sha512-eKAv5Ql6k78dh3ULCsSBxX6bFNuGjTmof5Q/T6PiECDq0Yf8IIn46jCyp3RJvCi8owaEmm3DZH1PEImjBMd/vQ==" 55 | }, 56 | "@types/retry": { 57 | "version": "0.12.0", 58 | "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", 59 | "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" 60 | }, 61 | "abort-controller": { 62 | "version": "3.0.0", 63 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 64 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 65 | "requires": { 66 | "event-target-shim": "^5.0.0" 67 | } 68 | }, 69 | "agent-base": { 70 | "version": "4.3.0", 71 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", 72 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", 73 | "requires": { 74 | "es6-promisify": "^5.0.0" 75 | } 76 | }, 77 | "ansi-colors": { 78 | "version": "3.2.3", 79 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", 80 | "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", 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 | "dev": true, 94 | "requires": { 95 | "color-convert": "^1.9.0" 96 | } 97 | }, 98 | "argparse": { 99 | "version": "1.0.10", 100 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 101 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 102 | "dev": true, 103 | "requires": { 104 | "sprintf-js": "~1.0.2" 105 | } 106 | }, 107 | "arrify": { 108 | "version": "2.0.1", 109 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 110 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" 111 | }, 112 | "asynckit": { 113 | "version": "0.4.0", 114 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 115 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 116 | }, 117 | "axios": { 118 | "version": "0.19.2", 119 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", 120 | "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", 121 | "requires": { 122 | "follow-redirects": "1.5.10" 123 | } 124 | }, 125 | "balanced-match": { 126 | "version": "1.0.0", 127 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 128 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 129 | "dev": true 130 | }, 131 | "base64-js": { 132 | "version": "1.3.1", 133 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 134 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 135 | }, 136 | "bignumber.js": { 137 | "version": "7.2.1", 138 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", 139 | "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" 140 | }, 141 | "brace-expansion": { 142 | "version": "1.1.11", 143 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 144 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 145 | "dev": true, 146 | "requires": { 147 | "balanced-match": "^1.0.0", 148 | "concat-map": "0.0.1" 149 | } 150 | }, 151 | "browser-stdout": { 152 | "version": "1.3.1", 153 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 154 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 155 | "dev": true 156 | }, 157 | "buffer-equal-constant-time": { 158 | "version": "1.0.1", 159 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 160 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 161 | }, 162 | "camelcase": { 163 | "version": "5.3.1", 164 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 165 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 166 | "dev": true 167 | }, 168 | "chalk": { 169 | "version": "2.4.2", 170 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 171 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 172 | "dev": true, 173 | "requires": { 174 | "ansi-styles": "^3.2.1", 175 | "escape-string-regexp": "^1.0.5", 176 | "supports-color": "^5.3.0" 177 | }, 178 | "dependencies": { 179 | "supports-color": { 180 | "version": "5.5.0", 181 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 182 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 183 | "dev": true, 184 | "requires": { 185 | "has-flag": "^3.0.0" 186 | } 187 | } 188 | } 189 | }, 190 | "cliui": { 191 | "version": "5.0.0", 192 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 193 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 194 | "dev": true, 195 | "requires": { 196 | "string-width": "^3.1.0", 197 | "strip-ansi": "^5.2.0", 198 | "wrap-ansi": "^5.1.0" 199 | }, 200 | "dependencies": { 201 | "ansi-regex": { 202 | "version": "4.1.0", 203 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 204 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 205 | "dev": true 206 | }, 207 | "string-width": { 208 | "version": "3.1.0", 209 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 210 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 211 | "dev": true, 212 | "requires": { 213 | "emoji-regex": "^7.0.1", 214 | "is-fullwidth-code-point": "^2.0.0", 215 | "strip-ansi": "^5.1.0" 216 | } 217 | }, 218 | "strip-ansi": { 219 | "version": "5.2.0", 220 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 221 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 222 | "dev": true, 223 | "requires": { 224 | "ansi-regex": "^4.1.0" 225 | } 226 | } 227 | } 228 | }, 229 | "color-convert": { 230 | "version": "1.9.3", 231 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 232 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 233 | "dev": true, 234 | "requires": { 235 | "color-name": "1.1.3" 236 | } 237 | }, 238 | "color-name": { 239 | "version": "1.1.3", 240 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 241 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 242 | "dev": true 243 | }, 244 | "combined-stream": { 245 | "version": "1.0.8", 246 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 247 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 248 | "requires": { 249 | "delayed-stream": "~1.0.0" 250 | } 251 | }, 252 | "concat-map": { 253 | "version": "0.0.1", 254 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 255 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 256 | "dev": true 257 | }, 258 | "debug": { 259 | "version": "3.2.6", 260 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 261 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 262 | "requires": { 263 | "ms": "^2.1.1" 264 | } 265 | }, 266 | "decamelize": { 267 | "version": "1.2.0", 268 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 269 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 270 | "dev": true 271 | }, 272 | "define-properties": { 273 | "version": "1.1.3", 274 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 275 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 276 | "dev": true, 277 | "requires": { 278 | "object-keys": "^1.0.12" 279 | } 280 | }, 281 | "delayed-stream": { 282 | "version": "1.0.0", 283 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 284 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 285 | }, 286 | "diff": { 287 | "version": "3.5.0", 288 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 289 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 290 | "dev": true 291 | }, 292 | "ecdsa-sig-formatter": { 293 | "version": "1.0.11", 294 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 295 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 296 | "requires": { 297 | "safe-buffer": "^5.0.1" 298 | } 299 | }, 300 | "emoji-regex": { 301 | "version": "7.0.3", 302 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 303 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 304 | "dev": true 305 | }, 306 | "es-abstract": { 307 | "version": "1.17.5", 308 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", 309 | "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", 310 | "dev": true, 311 | "requires": { 312 | "es-to-primitive": "^1.2.1", 313 | "function-bind": "^1.1.1", 314 | "has": "^1.0.3", 315 | "has-symbols": "^1.0.1", 316 | "is-callable": "^1.1.5", 317 | "is-regex": "^1.0.5", 318 | "object-inspect": "^1.7.0", 319 | "object-keys": "^1.1.1", 320 | "object.assign": "^4.1.0", 321 | "string.prototype.trimleft": "^2.1.1", 322 | "string.prototype.trimright": "^2.1.1" 323 | } 324 | }, 325 | "es-to-primitive": { 326 | "version": "1.2.1", 327 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 328 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 329 | "dev": true, 330 | "requires": { 331 | "is-callable": "^1.1.4", 332 | "is-date-object": "^1.0.1", 333 | "is-symbol": "^1.0.2" 334 | } 335 | }, 336 | "es6-promise": { 337 | "version": "4.2.8", 338 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", 339 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" 340 | }, 341 | "es6-promisify": { 342 | "version": "5.0.0", 343 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", 344 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", 345 | "requires": { 346 | "es6-promise": "^4.0.3" 347 | } 348 | }, 349 | "escape-string-regexp": { 350 | "version": "1.0.5", 351 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 352 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 353 | "dev": true 354 | }, 355 | "esprima": { 356 | "version": "4.0.1", 357 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 358 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 359 | "dev": true 360 | }, 361 | "event-target-shim": { 362 | "version": "5.0.1", 363 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 364 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" 365 | }, 366 | "eventemitter3": { 367 | "version": "3.1.2", 368 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", 369 | "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" 370 | }, 371 | "extend": { 372 | "version": "3.0.2", 373 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 374 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 375 | }, 376 | "fast-text-encoding": { 377 | "version": "1.0.0", 378 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", 379 | "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" 380 | }, 381 | "find-up": { 382 | "version": "3.0.0", 383 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 384 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 385 | "dev": true, 386 | "requires": { 387 | "locate-path": "^3.0.0" 388 | } 389 | }, 390 | "flat": { 391 | "version": "4.1.0", 392 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 393 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 394 | "dev": true, 395 | "requires": { 396 | "is-buffer": "~2.0.3" 397 | } 398 | }, 399 | "follow-redirects": { 400 | "version": "1.5.10", 401 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", 402 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", 403 | "requires": { 404 | "debug": "=3.1.0" 405 | }, 406 | "dependencies": { 407 | "debug": { 408 | "version": "3.1.0", 409 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 410 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 411 | "requires": { 412 | "ms": "2.0.0" 413 | } 414 | }, 415 | "ms": { 416 | "version": "2.0.0", 417 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 418 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 419 | } 420 | } 421 | }, 422 | "form-data": { 423 | "version": "2.5.1", 424 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", 425 | "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", 426 | "requires": { 427 | "asynckit": "^0.4.0", 428 | "combined-stream": "^1.0.6", 429 | "mime-types": "^2.1.12" 430 | } 431 | }, 432 | "fs.realpath": { 433 | "version": "1.0.0", 434 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 435 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 436 | "dev": true 437 | }, 438 | "function-bind": { 439 | "version": "1.1.1", 440 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 441 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 442 | "dev": true 443 | }, 444 | "gaxios": { 445 | "version": "2.0.1", 446 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.0.1.tgz", 447 | "integrity": "sha512-c1NXovTxkgRJTIgB2FrFmOFg4YIV6N/bAa4f/FZ4jIw13Ql9ya/82x69CswvotJhbV3DiGnlTZwoq2NVXk2Irg==", 448 | "requires": { 449 | "abort-controller": "^3.0.0", 450 | "extend": "^3.0.2", 451 | "https-proxy-agent": "^2.2.1", 452 | "node-fetch": "^2.3.0" 453 | } 454 | }, 455 | "gcp-metadata": { 456 | "version": "3.1.0", 457 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.1.0.tgz", 458 | "integrity": "sha512-TRvWwkzWLf9bn5+wgbyrnhRuIg3kqtyk+SzrbmUgLUfZOOD2+NBVXsjtkK/UfHEBl9KDZ5Q0NT+WhLSMSycFMw==", 459 | "requires": { 460 | "gaxios": "^2.0.1", 461 | "json-bigint": "^0.3.0" 462 | } 463 | }, 464 | "get-caller-file": { 465 | "version": "2.0.5", 466 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 467 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 468 | "dev": true 469 | }, 470 | "glob": { 471 | "version": "7.1.3", 472 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 473 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 474 | "dev": true, 475 | "requires": { 476 | "fs.realpath": "^1.0.0", 477 | "inflight": "^1.0.4", 478 | "inherits": "2", 479 | "minimatch": "^3.0.4", 480 | "once": "^1.3.0", 481 | "path-is-absolute": "^1.0.0" 482 | } 483 | }, 484 | "google-auth-library": { 485 | "version": "5.4.0", 486 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.4.0.tgz", 487 | "integrity": "sha512-sgWnedR+KePbxtxCaldcaTCtOV/hfUcuSXdb9BkkqYp1EadC4ST0KDxvpq20K2TnF9dGDykMBUqc2DoG6cUq9g==", 488 | "requires": { 489 | "arrify": "^2.0.0", 490 | "base64-js": "^1.3.0", 491 | "fast-text-encoding": "^1.0.0", 492 | "gaxios": "^2.0.0", 493 | "gcp-metadata": "^3.0.0", 494 | "gtoken": "^4.1.0", 495 | "jws": "^3.1.5", 496 | "lru-cache": "^5.0.0" 497 | } 498 | }, 499 | "google-p12-pem": { 500 | "version": "2.0.2", 501 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.2.tgz", 502 | "integrity": "sha512-UfnEARfJKI6pbmC1hfFFm+UAcZxeIwTiEcHfqKe/drMsXD/ilnVjF7zgOGpHXyhuvX6jNJK3S8A0hOQjwtFxEw==", 503 | "requires": { 504 | "node-forge": "^0.9.0" 505 | } 506 | }, 507 | "googleapis": { 508 | "version": "43.0.0", 509 | "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-43.0.0.tgz", 510 | "integrity": "sha512-4b38mlTdDCA3KiyRTQmfPpeTxznC5ufgqx3AvKaEIoVm+iWeVLfwYs++/+OcGJJriH9bcs0gPbU7CR8DU6Oevg==", 511 | "requires": { 512 | "google-auth-library": "^5.2.0", 513 | "googleapis-common": "^3.1.0" 514 | } 515 | }, 516 | "googleapis-common": { 517 | "version": "3.1.1", 518 | "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-3.1.1.tgz", 519 | "integrity": "sha512-sXNS9oJifZOk2Pa6SzxoSfv0Mj9y/qIOsVV7D8WHuH//90CXNnpR/nCYVa+KcPMDT9ONq21sbtvjfKATMV1Bug==", 520 | "requires": { 521 | "extend": "^3.0.2", 522 | "gaxios": "^2.0.1", 523 | "google-auth-library": "^5.2.0", 524 | "qs": "^6.7.0", 525 | "url-template": "^2.0.8", 526 | "uuid": "^3.3.2" 527 | } 528 | }, 529 | "growl": { 530 | "version": "1.10.5", 531 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 532 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 533 | "dev": true 534 | }, 535 | "gtoken": { 536 | "version": "4.1.0", 537 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.0.tgz", 538 | "integrity": "sha512-wqyn2gf5buzEZN4QNmmiiW2i2JkEdZnL7Z/9p44RtZqgt4077m4khRgAYNuu8cBwHWCc6MsP6eDUn/KkF6jFIw==", 539 | "requires": { 540 | "gaxios": "^2.0.0", 541 | "google-p12-pem": "^2.0.0", 542 | "jws": "^3.1.5", 543 | "mime": "^2.2.0" 544 | } 545 | }, 546 | "has": { 547 | "version": "1.0.3", 548 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 549 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 550 | "dev": true, 551 | "requires": { 552 | "function-bind": "^1.1.1" 553 | } 554 | }, 555 | "has-flag": { 556 | "version": "3.0.0", 557 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 558 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 559 | "dev": true 560 | }, 561 | "has-symbols": { 562 | "version": "1.0.1", 563 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 564 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", 565 | "dev": true 566 | }, 567 | "he": { 568 | "version": "1.2.0", 569 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 570 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 571 | "dev": true 572 | }, 573 | "https-proxy-agent": { 574 | "version": "2.2.4", 575 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", 576 | "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", 577 | "requires": { 578 | "agent-base": "^4.3.0", 579 | "debug": "^3.1.0" 580 | } 581 | }, 582 | "inflight": { 583 | "version": "1.0.6", 584 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 585 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 586 | "dev": true, 587 | "requires": { 588 | "once": "^1.3.0", 589 | "wrappy": "1" 590 | } 591 | }, 592 | "inherits": { 593 | "version": "2.0.4", 594 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 595 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 596 | "dev": true 597 | }, 598 | "is-buffer": { 599 | "version": "2.0.4", 600 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 601 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", 602 | "dev": true 603 | }, 604 | "is-callable": { 605 | "version": "1.1.5", 606 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", 607 | "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", 608 | "dev": true 609 | }, 610 | "is-date-object": { 611 | "version": "1.0.2", 612 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 613 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", 614 | "dev": true 615 | }, 616 | "is-fullwidth-code-point": { 617 | "version": "2.0.0", 618 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 619 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 620 | "dev": true 621 | }, 622 | "is-regex": { 623 | "version": "1.0.5", 624 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", 625 | "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", 626 | "dev": true, 627 | "requires": { 628 | "has": "^1.0.3" 629 | } 630 | }, 631 | "is-stream": { 632 | "version": "1.1.0", 633 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 634 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 635 | }, 636 | "is-symbol": { 637 | "version": "1.0.3", 638 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 639 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 640 | "dev": true, 641 | "requires": { 642 | "has-symbols": "^1.0.1" 643 | } 644 | }, 645 | "isexe": { 646 | "version": "2.0.0", 647 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 648 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 649 | "dev": true 650 | }, 651 | "js-yaml": { 652 | "version": "3.13.1", 653 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 654 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 655 | "dev": true, 656 | "requires": { 657 | "argparse": "^1.0.7", 658 | "esprima": "^4.0.0" 659 | } 660 | }, 661 | "json-bigint": { 662 | "version": "0.3.0", 663 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", 664 | "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", 665 | "requires": { 666 | "bignumber.js": "^7.0.0" 667 | } 668 | }, 669 | "jwa": { 670 | "version": "1.4.1", 671 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 672 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 673 | "requires": { 674 | "buffer-equal-constant-time": "1.0.1", 675 | "ecdsa-sig-formatter": "1.0.11", 676 | "safe-buffer": "^5.0.1" 677 | } 678 | }, 679 | "jws": { 680 | "version": "3.2.2", 681 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 682 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 683 | "requires": { 684 | "jwa": "^1.4.1", 685 | "safe-buffer": "^5.0.1" 686 | } 687 | }, 688 | "locate-path": { 689 | "version": "3.0.0", 690 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 691 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 692 | "dev": true, 693 | "requires": { 694 | "p-locate": "^3.0.0", 695 | "path-exists": "^3.0.0" 696 | } 697 | }, 698 | "lodash": { 699 | "version": "4.17.15", 700 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 701 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 702 | }, 703 | "log-symbols": { 704 | "version": "2.2.0", 705 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", 706 | "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", 707 | "dev": true, 708 | "requires": { 709 | "chalk": "^2.0.1" 710 | } 711 | }, 712 | "lru-cache": { 713 | "version": "5.1.1", 714 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 715 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 716 | "requires": { 717 | "yallist": "^3.0.2" 718 | } 719 | }, 720 | "mime": { 721 | "version": "2.4.4", 722 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", 723 | "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" 724 | }, 725 | "mime-db": { 726 | "version": "1.43.0", 727 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 728 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 729 | }, 730 | "mime-types": { 731 | "version": "2.1.26", 732 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 733 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 734 | "requires": { 735 | "mime-db": "1.43.0" 736 | } 737 | }, 738 | "minimatch": { 739 | "version": "3.0.4", 740 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 741 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 742 | "dev": true, 743 | "requires": { 744 | "brace-expansion": "^1.1.7" 745 | } 746 | }, 747 | "minimist": { 748 | "version": "1.2.5", 749 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 750 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 751 | "dev": true 752 | }, 753 | "mkdirp": { 754 | "version": "0.5.4", 755 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", 756 | "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", 757 | "dev": true, 758 | "requires": { 759 | "minimist": "^1.2.5" 760 | } 761 | }, 762 | "mocha": { 763 | "version": "6.2.3", 764 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", 765 | "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", 766 | "dev": true, 767 | "requires": { 768 | "ansi-colors": "3.2.3", 769 | "browser-stdout": "1.3.1", 770 | "debug": "3.2.6", 771 | "diff": "3.5.0", 772 | "escape-string-regexp": "1.0.5", 773 | "find-up": "3.0.0", 774 | "glob": "7.1.3", 775 | "growl": "1.10.5", 776 | "he": "1.2.0", 777 | "js-yaml": "3.13.1", 778 | "log-symbols": "2.2.0", 779 | "minimatch": "3.0.4", 780 | "mkdirp": "0.5.4", 781 | "ms": "2.1.1", 782 | "node-environment-flags": "1.0.5", 783 | "object.assign": "4.1.0", 784 | "strip-json-comments": "2.0.1", 785 | "supports-color": "6.0.0", 786 | "which": "1.3.1", 787 | "wide-align": "1.1.3", 788 | "yargs": "13.3.2", 789 | "yargs-parser": "13.1.2", 790 | "yargs-unparser": "1.6.0" 791 | }, 792 | "dependencies": { 793 | "ms": { 794 | "version": "2.1.1", 795 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 796 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 797 | "dev": true 798 | } 799 | } 800 | }, 801 | "ms": { 802 | "version": "2.1.2", 803 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 804 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 805 | }, 806 | "node-environment-flags": { 807 | "version": "1.0.5", 808 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", 809 | "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", 810 | "dev": true, 811 | "requires": { 812 | "object.getownpropertydescriptors": "^2.0.3", 813 | "semver": "^5.7.0" 814 | } 815 | }, 816 | "node-fetch": { 817 | "version": "2.6.0", 818 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 819 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 820 | }, 821 | "node-forge": { 822 | "version": "0.9.1", 823 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz", 824 | "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ==" 825 | }, 826 | "object-inspect": { 827 | "version": "1.7.0", 828 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 829 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", 830 | "dev": true 831 | }, 832 | "object-keys": { 833 | "version": "1.1.1", 834 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 835 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 836 | "dev": true 837 | }, 838 | "object.assign": { 839 | "version": "4.1.0", 840 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 841 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 842 | "dev": true, 843 | "requires": { 844 | "define-properties": "^1.1.2", 845 | "function-bind": "^1.1.1", 846 | "has-symbols": "^1.0.0", 847 | "object-keys": "^1.0.11" 848 | } 849 | }, 850 | "object.getownpropertydescriptors": { 851 | "version": "2.1.0", 852 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", 853 | "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", 854 | "dev": true, 855 | "requires": { 856 | "define-properties": "^1.1.3", 857 | "es-abstract": "^1.17.0-next.1" 858 | } 859 | }, 860 | "once": { 861 | "version": "1.4.0", 862 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 863 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 864 | "dev": true, 865 | "requires": { 866 | "wrappy": "1" 867 | } 868 | }, 869 | "p-limit": { 870 | "version": "2.3.0", 871 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 872 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 873 | "dev": true, 874 | "requires": { 875 | "p-try": "^2.0.0" 876 | } 877 | }, 878 | "p-locate": { 879 | "version": "3.0.0", 880 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 881 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 882 | "dev": true, 883 | "requires": { 884 | "p-limit": "^2.0.0" 885 | } 886 | }, 887 | "p-queue": { 888 | "version": "2.4.2", 889 | "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz", 890 | "integrity": "sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng==" 891 | }, 892 | "p-retry": { 893 | "version": "4.2.0", 894 | "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.2.0.tgz", 895 | "integrity": "sha512-jPH38/MRh263KKcq0wBNOGFJbm+U6784RilTmHjB/HM9kH9V8WlCpVUcdOmip9cjXOh6MxZ5yk1z2SjDUJfWmA==", 896 | "requires": { 897 | "@types/retry": "^0.12.0", 898 | "retry": "^0.12.0" 899 | } 900 | }, 901 | "p-try": { 902 | "version": "2.2.0", 903 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 904 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 905 | "dev": true 906 | }, 907 | "path-exists": { 908 | "version": "3.0.0", 909 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 910 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 911 | "dev": true 912 | }, 913 | "path-is-absolute": { 914 | "version": "1.0.1", 915 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 916 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 917 | "dev": true 918 | }, 919 | "qs": { 920 | "version": "6.9.0", 921 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.0.tgz", 922 | "integrity": "sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA==" 923 | }, 924 | "require-directory": { 925 | "version": "2.1.1", 926 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 927 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 928 | "dev": true 929 | }, 930 | "require-main-filename": { 931 | "version": "2.0.0", 932 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 933 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 934 | "dev": true 935 | }, 936 | "retry": { 937 | "version": "0.12.0", 938 | "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", 939 | "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" 940 | }, 941 | "safe-buffer": { 942 | "version": "5.2.0", 943 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 944 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 945 | }, 946 | "semver": { 947 | "version": "5.7.1", 948 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 949 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 950 | "dev": true 951 | }, 952 | "set-blocking": { 953 | "version": "2.0.0", 954 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 955 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 956 | "dev": true 957 | }, 958 | "sprintf-js": { 959 | "version": "1.0.3", 960 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 961 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 962 | "dev": true 963 | }, 964 | "string-width": { 965 | "version": "2.1.1", 966 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 967 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 968 | "dev": true, 969 | "requires": { 970 | "is-fullwidth-code-point": "^2.0.0", 971 | "strip-ansi": "^4.0.0" 972 | } 973 | }, 974 | "string.prototype.trimend": { 975 | "version": "1.0.1", 976 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", 977 | "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", 978 | "dev": true, 979 | "requires": { 980 | "define-properties": "^1.1.3", 981 | "es-abstract": "^1.17.5" 982 | } 983 | }, 984 | "string.prototype.trimleft": { 985 | "version": "2.1.2", 986 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", 987 | "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", 988 | "dev": true, 989 | "requires": { 990 | "define-properties": "^1.1.3", 991 | "es-abstract": "^1.17.5", 992 | "string.prototype.trimstart": "^1.0.0" 993 | } 994 | }, 995 | "string.prototype.trimright": { 996 | "version": "2.1.2", 997 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", 998 | "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", 999 | "dev": true, 1000 | "requires": { 1001 | "define-properties": "^1.1.3", 1002 | "es-abstract": "^1.17.5", 1003 | "string.prototype.trimend": "^1.0.0" 1004 | } 1005 | }, 1006 | "string.prototype.trimstart": { 1007 | "version": "1.0.1", 1008 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", 1009 | "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", 1010 | "dev": true, 1011 | "requires": { 1012 | "define-properties": "^1.1.3", 1013 | "es-abstract": "^1.17.5" 1014 | } 1015 | }, 1016 | "strip-ansi": { 1017 | "version": "4.0.0", 1018 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1019 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1020 | "dev": true, 1021 | "requires": { 1022 | "ansi-regex": "^3.0.0" 1023 | } 1024 | }, 1025 | "strip-json-comments": { 1026 | "version": "2.0.1", 1027 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1028 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1029 | "dev": true 1030 | }, 1031 | "supports-color": { 1032 | "version": "6.0.0", 1033 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", 1034 | "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", 1035 | "dev": true, 1036 | "requires": { 1037 | "has-flag": "^3.0.0" 1038 | } 1039 | }, 1040 | "url-template": { 1041 | "version": "2.0.8", 1042 | "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", 1043 | "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" 1044 | }, 1045 | "uuid": { 1046 | "version": "3.3.3", 1047 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 1048 | "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" 1049 | }, 1050 | "which": { 1051 | "version": "1.3.1", 1052 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1053 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1054 | "dev": true, 1055 | "requires": { 1056 | "isexe": "^2.0.0" 1057 | } 1058 | }, 1059 | "which-module": { 1060 | "version": "2.0.0", 1061 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1062 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1063 | "dev": true 1064 | }, 1065 | "wide-align": { 1066 | "version": "1.1.3", 1067 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1068 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1069 | "dev": true, 1070 | "requires": { 1071 | "string-width": "^1.0.2 || 2" 1072 | } 1073 | }, 1074 | "wrap-ansi": { 1075 | "version": "5.1.0", 1076 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 1077 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 1078 | "dev": true, 1079 | "requires": { 1080 | "ansi-styles": "^3.2.0", 1081 | "string-width": "^3.0.0", 1082 | "strip-ansi": "^5.0.0" 1083 | }, 1084 | "dependencies": { 1085 | "ansi-regex": { 1086 | "version": "4.1.0", 1087 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1088 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1089 | "dev": true 1090 | }, 1091 | "string-width": { 1092 | "version": "3.1.0", 1093 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1094 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1095 | "dev": true, 1096 | "requires": { 1097 | "emoji-regex": "^7.0.1", 1098 | "is-fullwidth-code-point": "^2.0.0", 1099 | "strip-ansi": "^5.1.0" 1100 | } 1101 | }, 1102 | "strip-ansi": { 1103 | "version": "5.2.0", 1104 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1105 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1106 | "dev": true, 1107 | "requires": { 1108 | "ansi-regex": "^4.1.0" 1109 | } 1110 | } 1111 | } 1112 | }, 1113 | "wrappy": { 1114 | "version": "1.0.2", 1115 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1116 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1117 | "dev": true 1118 | }, 1119 | "y18n": { 1120 | "version": "4.0.0", 1121 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1122 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 1123 | "dev": true 1124 | }, 1125 | "yallist": { 1126 | "version": "3.1.1", 1127 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 1128 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 1129 | }, 1130 | "yargs": { 1131 | "version": "13.3.2", 1132 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 1133 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 1134 | "dev": true, 1135 | "requires": { 1136 | "cliui": "^5.0.0", 1137 | "find-up": "^3.0.0", 1138 | "get-caller-file": "^2.0.1", 1139 | "require-directory": "^2.1.1", 1140 | "require-main-filename": "^2.0.0", 1141 | "set-blocking": "^2.0.0", 1142 | "string-width": "^3.0.0", 1143 | "which-module": "^2.0.0", 1144 | "y18n": "^4.0.0", 1145 | "yargs-parser": "^13.1.2" 1146 | }, 1147 | "dependencies": { 1148 | "ansi-regex": { 1149 | "version": "4.1.0", 1150 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1151 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1152 | "dev": true 1153 | }, 1154 | "string-width": { 1155 | "version": "3.1.0", 1156 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1157 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1158 | "dev": true, 1159 | "requires": { 1160 | "emoji-regex": "^7.0.1", 1161 | "is-fullwidth-code-point": "^2.0.0", 1162 | "strip-ansi": "^5.1.0" 1163 | } 1164 | }, 1165 | "strip-ansi": { 1166 | "version": "5.2.0", 1167 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1168 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1169 | "dev": true, 1170 | "requires": { 1171 | "ansi-regex": "^4.1.0" 1172 | } 1173 | } 1174 | } 1175 | }, 1176 | "yargs-parser": { 1177 | "version": "13.1.2", 1178 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 1179 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 1180 | "dev": true, 1181 | "requires": { 1182 | "camelcase": "^5.0.0", 1183 | "decamelize": "^1.2.0" 1184 | } 1185 | }, 1186 | "yargs-unparser": { 1187 | "version": "1.6.0", 1188 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", 1189 | "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", 1190 | "dev": true, 1191 | "requires": { 1192 | "flat": "^4.1.0", 1193 | "lodash": "^4.17.15", 1194 | "yargs": "^13.3.0" 1195 | } 1196 | } 1197 | } 1198 | } 1199 | --------------------------------------------------------------------------------