From 3b0cf1549ac1f17009016b05c34a5c9f599fe7f7 Mon Sep 17 00:00:00 2001 From: Sampsa Saarela Date: Thu, 25 Apr 2019 12:55:40 +0800 Subject: [PATCH 01/69] fetch exports from cloudformation if used Fn::ImportValue --- index.ts | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index ed8f0471..8168008d 100644 --- a/index.ts +++ b/index.ts @@ -527,14 +527,54 @@ class ServerlessCustomDomain { } } + /** + * Gets value by name from cloudformation exports + */ + public async getImportValue(importValueName, nextToken = null): Promise { + const params = nextToken ? { NextToken: nextToken } : {}; + const result = await this.cloudformation.listExports(params).promise(); + const importValue = result.Exports.find((val: any) => val.Name === importValueName); + if (importValue) { + return importValue.Value; + } + + if (result.NextToken) { + return this.getImportValue(importValueName, result.NextToken); + } + + return null; + } + /** * Gets rest API id from CloudFormation stack */ public async getRestApiId(): Promise { if (this.serverless.service.provider.apiGateway && this.serverless.service.provider.apiGateway.restApiId) { + const restApiId = this.serverless.service.provider.apiGateway.restApiId; + + if (typeof restApiId === "object" && restApiId["Fn::ImportValue"]) { + try { + const importValue = await this.getImportValue(restApiId["Fn::ImportValue"]); + if (importValue) { + return importValue; + } + + throw new Error(`Error: CloudFormation ImportValue not found + by ${restApiId["Fn::ImportValue"]}\n`); + } catch (err) { + this.logIfDebug(err); + throw new Error(`Error: Failed to find CloudFormation ImportValue + by ${restApiId["Fn::ImportValue"]}\n`); + } + } + + if (typeof restApiId === "object") { + throw new Error("Error: Unsupported restApiId object"); + } + this.serverless.cli.log(`Mapping custom domain to existing API ${this.serverless.service.provider.apiGateway.restApiId}.`); - return this.serverless.service.provider.apiGateway.restApiId; + return restApiId; } const stackName = this.serverless.service.provider.stackName || `${this.serverless.service.service}-${this.stage}`; From 896e1b239da3bd94a9061d0c76754812c737a66e Mon Sep 17 00:00:00 2001 From: Sampsa Saarela Date: Thu, 25 Apr 2019 13:26:16 +0800 Subject: [PATCH 02/69] fixed lint error --- index.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.ts b/index.ts index 8168008d..3614b188 100644 --- a/index.ts +++ b/index.ts @@ -550,31 +550,31 @@ class ServerlessCustomDomain { */ public async getRestApiId(): Promise { if (this.serverless.service.provider.apiGateway && this.serverless.service.provider.apiGateway.restApiId) { - const restApiId = this.serverless.service.provider.apiGateway.restApiId; - - if (typeof restApiId === "object" && restApiId["Fn::ImportValue"]) { + if (typeof this.serverless.service.provider.apiGateway.restApiId === "object" && + this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]) { try { - const importValue = await this.getImportValue(restApiId["Fn::ImportValue"]); + const importValueName = this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]; + const importValue = await this.getImportValue(importValueName); if (importValue) { return importValue; } throw new Error(`Error: CloudFormation ImportValue not found - by ${restApiId["Fn::ImportValue"]}\n`); + by ${this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]}\n`); } catch (err) { this.logIfDebug(err); throw new Error(`Error: Failed to find CloudFormation ImportValue - by ${restApiId["Fn::ImportValue"]}\n`); + by ${this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]}\n`); } } - if (typeof restApiId === "object") { + if (typeof this.serverless.service.provider.apiGateway.restApiId === "object") { throw new Error("Error: Unsupported restApiId object"); } this.serverless.cli.log(`Mapping custom domain to existing API ${this.serverless.service.provider.apiGateway.restApiId}.`); - return restApiId; + return this.serverless.service.provider.apiGateway.restApiId; } const stackName = this.serverless.service.provider.stackName || `${this.serverless.service.service}-${this.stage}`; From 9093e8c9b13f6a869873e515b2d7fc344be32f4d Mon Sep 17 00:00:00 2001 From: Sampsa Saarela Date: Thu, 25 Apr 2019 13:31:16 +0800 Subject: [PATCH 03/69] bumb version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d22bb3b..5248f774 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.2.1", + "version": "3.2.2", "engines": { "node": ">=4.0" }, From 2948c628a5cb9661e054aaf8098a888ddf214846 Mon Sep 17 00:00:00 2001 From: Gabriel Plassard Date: Mon, 24 Feb 2020 17:05:14 +0100 Subject: [PATCH 04/69] Use pagination when there are too many certificates fixes #314 --- index.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/index.ts b/index.ts index 9297286c..cceac0c3 100644 --- a/index.ts +++ b/index.ts @@ -260,13 +260,18 @@ class ServerlessCustomDomain { let certificateArn; // The arn of the choosen certificate let certificateName = this.serverless.service.custom.customDomain.certificateName; // The certificate name - let certData; try { - certData = await this.acm.listCertificates( - { CertificateStatuses: certStatuses }).promise(); + let certificates = []; + let nextToken; + do { + const certData = await this.acm.listCertificates( + { CertificateStatuses: certStatuses, NextToken: nextToken }).promise(); + certificates = certificates.concat(certData.CertificateSummaryList); + nextToken = certData.NextToken; + } while (nextToken); + // The more specific name will be the longest let nameLength = 0; - const certificates = certData.CertificateSummaryList; // Checks if a certificate name is given if (certificateName != null) { From 2547acec3134a4201f8759304accc54013e6fb67 Mon Sep 17 00:00:00 2001 From: David Rosson Date: Fri, 20 Mar 2020 09:33:58 +0200 Subject: [PATCH 05/69] Move the call to 'addOutputs' to its own lifecycle function, so it can be triggered before 'deploy' --- index.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 9297286c..4591e160 100644 --- a/index.ts +++ b/index.ts @@ -63,6 +63,7 @@ class ServerlessCustomDomain { this.hooks = { "after:deploy:deploy": this.hookWrapper.bind(this, this.setupBasePathMapping), "after:info:info": this.hookWrapper.bind(this, this.domainSummary), + "before:deploy:deploy": this.hookWrapper.bind(this, this.updateCloudFormationOutputs), "before:remove:remove": this.hookWrapper.bind(this, this.removeBasePathMapping), "create_domain:create": this.hookWrapper.bind(this, this.createDomain), "delete_domain:delete": this.hookWrapper.bind(this, this.deleteDomain), @@ -129,6 +130,14 @@ class ServerlessCustomDomain { this.serverless.cli.log(`Custom domain ${this.givenDomainName} was deleted.`); } + /** + * Lifecycle function to add domain info to the CloudFormation stack's Outputs + */ + public async updateCloudFormationOutputs(): Promise { + const domainInfo = await this.getDomainInfo(); + this.addOutputs(domainInfo); + } + /** * Lifecycle function to create basepath mapping * Wraps creation of basepath mapping and adds domain name info as output to cloudformation stack @@ -144,7 +153,6 @@ class ServerlessCustomDomain { await this.updateBasePathMapping(currentBasePath); } const domainInfo = await this.getDomainInfo(); - this.addOutputs(domainInfo); await this.printDomainSummary(domainInfo); } From 662a83945db3d1d97220b9e281eb116c3eaa4cfa Mon Sep 17 00:00:00 2001 From: David Rosson Date: Fri, 20 Mar 2020 09:34:43 +0200 Subject: [PATCH 06/69] Update the CloudFormation stack's 'Outputs' naming to align with the README and the 'Serverless Domain Manager Summary' output --- index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 4591e160..e58086e2 100644 --- a/index.ts +++ b/index.ts @@ -608,9 +608,12 @@ class ServerlessCustomDomain { if (!service.provider.compiledCloudFormationTemplate.Outputs) { service.provider.compiledCloudFormationTemplate.Outputs = {}; } - service.provider.compiledCloudFormationTemplate.Outputs.DomainName = { + service.provider.compiledCloudFormationTemplate.Outputs.DistributionDomainName = { Value: domainInfo.domainName, }; + service.provider.compiledCloudFormationTemplate.Outputs.DomainName = { + Value: this.givenDomainName, + }; if (domainInfo.hostedZoneId) { service.provider.compiledCloudFormationTemplate.Outputs.HostedZoneId = { Value: domainInfo.hostedZoneId, From c1285deebd0cdc5cf31ec6b79c2493b88bfb6b77 Mon Sep 17 00:00:00 2001 From: David Rosson Date: Fri, 20 Mar 2020 09:35:27 +0200 Subject: [PATCH 07/69] Insert a newline to improve appearance of 'Serverless Domain Manager Summary' output --- index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.ts b/index.ts index e58086e2..59c777c8 100644 --- a/index.ts +++ b/index.ts @@ -635,7 +635,7 @@ class ServerlessCustomDomain { * Prints out a summary of all domain manager related info */ private printDomainSummary(domainInfo: DomainInfo): void { - this.serverless.cli.consoleLog(chalk.yellow.underline("Serverless Domain Manager Summary")); + this.serverless.cli.consoleLog(chalk.yellow.underline("\nServerless Domain Manager Summary")); if (this.serverless.service.custom.customDomain.createRoute53Record !== false) { this.serverless.cli.consoleLog(chalk.yellow("Domain Name")); From f0c2f15f475730e4a477cf09e8baa3ffc728dd46 Mon Sep 17 00:00:00 2001 From: David Rosson Date: Fri, 20 Mar 2020 09:36:09 +0200 Subject: [PATCH 08/69] Add 'Distribution Domain Name' to the unit test description --- test/unit-tests/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 27bb5c0c..f31dc23b 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -170,7 +170,7 @@ describe("Custom Domain Plugin", () => { }); }); - it("Add Domain Name and HostedZoneId to stack output", () => { + it("Add Distribution Domain Name, Domain Name, and HostedZoneId to stack output", () => { const plugin = constructPlugin({ domainName: "test_domain", }); From 58fc87a71737d0d04f68175759a7a85f603f961b Mon Sep 17 00:00:00 2001 From: David Rosson Date: Fri, 20 Mar 2020 12:58:50 +0200 Subject: [PATCH 09/69] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4aa7992f..c918042e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.0", + "version": "3.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 102f8230..e7717b49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.1", + "version": "3.3.2", "engines": { "node": ">=4.0" }, From e31de1ac9e83384884bba1f17794dea01dc14b96 Mon Sep 17 00:00:00 2001 From: Hunter Date: Wed, 15 Apr 2020 13:40:33 -0500 Subject: [PATCH 10/69] add create domain to deploy --- index.ts | 10 +++ package-lock.json | 2 +- test/unit-tests/index.test.ts | 111 +++++++++++++++++++++++++++++++++- types.ts | 1 + 4 files changed, 122 insertions(+), 2 deletions(-) diff --git a/index.ts b/index.ts index 9297286c..bab4a2d0 100644 --- a/index.ts +++ b/index.ts @@ -136,6 +136,11 @@ class ServerlessCustomDomain { public async setupBasePathMapping(): Promise { // check if basepathmapping exists const restApiId = await this.getRestApiId(); + const createDomainName = this.serverless.service.custom.customDomain.createDomainName; + if (createDomainName === true) { + this.serverless.cli.log("Creating domain name before setting up base path mapping."); + await this.createDomain(); + } const currentBasePath = await this.getBasePathMapping(restApiId); // if basepath that matches restApiId exists, update; else, create if (!currentBasePath) { @@ -154,6 +159,11 @@ class ServerlessCustomDomain { */ public async removeBasePathMapping(): Promise { await this.deleteBasePathMapping(); + const createDomainName = this.serverless.service.custom.customDomain.createDomainName; + if (createDomainName === true) { + this.serverless.cli.log("Deleting domain name after removing base path mapping."); + await this.deleteDomain(); + } } /** diff --git a/package-lock.json b/package-lock.json index 4aa7992f..e438a93c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.0", + "version": "3.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 27bb5c0c..d37ee13d 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -5,7 +5,6 @@ import spies = require("chai-spies"); import "mocha"; import DomainInfo = require("../../DomainInfo"); import ServerlessCustomDomain = require("../../index"); -import { ServerlessInstance, ServerlessOptions } from "../../types"; const expect = chai.expect; chai.use(spies); @@ -71,6 +70,7 @@ const constructPlugin = (customDomainOptions) => { hostedZonePrivate: customDomainOptions.hostedZonePrivate, securityPolicy: customDomainOptions.securityPolicy, stage: customDomainOptions.stage, + createDomainName: customDomainOptions.createDomainName }, }, provider: { @@ -1175,4 +1175,113 @@ describe("Custom Domain Plugin", () => { consoleOutput = []; }); }); + + describe("create domain name deploy", () => { + it("Should be disabled by default", () => { + const plugin = constructPlugin({ domainName: "test_domain" }); + plugin.initializeVariables(); + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.undefined; + }); + + it("setUpBasePathMapping should call createDomain when createDomainName is true", async () => { + AWS.mock("APIGateway", "getDomainName", (params, callback) => { + callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); + }); + AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { + callback(null, { items: [] }); + }); + AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { + callback(null, params); + }); + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "ApiGatewayRestApi", + PhysicalResourceId: "test_rest_api_id", + }, + }); + }); + const plugin = constructPlugin({ domainName: "test_domain", createDomainName: true }); + plugin.initializeVariables(); + plugin.apigateway = new aws.APIGateway(); + plugin.cloudformation = new aws.CloudFormation(); + plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + const spy = chai.spy.on(plugin, "createDomain"); + + await plugin.setupBasePathMapping(); + + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.true; + expect(spy).to.have.been.called.once; + }); + + it("setUpBasePathMapping should not call createDomain when createDomainName is not true", async () => { + AWS.mock("APIGateway", "getDomainName", (params, callback) => { + callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); + }); + AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { + callback(null, { items: [] }); + }); + AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { + callback(null, params); + }); + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "ApiGatewayRestApi", + PhysicalResourceId: "test_rest_api_id", + }, + }); + }); + const plugin = constructPlugin({ domainName: "test_domain", createDomainName: false }); + plugin.initializeVariables(); + plugin.apigateway = new aws.APIGateway(); + plugin.cloudformation = new aws.CloudFormation(); + plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + const spy = chai.spy.on(plugin, "createDomain"); + + await plugin.setupBasePathMapping(); + + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.false; + expect(spy).to.not.have.been.called; + }); + + it("removeBasePathMapping should call deleteDomain when createDomainName is true", async () => { + AWS.mock("APIGateway", "deleteBasePathMapping", (params, callback) => { + callback(null, params); + }); + AWS.mock("APIGateway", "getDomainName", (params, callback) => { + callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); + }); + AWS.mock("APIGateway", "deleteDomainName", (params, callback) => { + callback(null, params); + }); + const plugin = constructPlugin({ domainName: "test_domain", createDomainName: true, createRoute53Record: false }); + plugin.initializeVariables(); + plugin.apigateway = new aws.APIGateway(); + plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + const spy = chai.spy.on(plugin, "deleteDomain"); + + await plugin.removeBasePathMapping(); + + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.true; + expect(spy).to.have.been.called.once; + }); + + it("removeBasePathMapping should not call deleteDomain when createDomainName is not true", async () => { + const plugin = constructPlugin({ createDomainName: false }); + plugin.initializeVariables(); + const spy = chai.spy.on(plugin, "deleteDomain"); + + await plugin.removeBasePathMapping(); + + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.false; + expect(spy).to.not.have.been.called; + }); + + afterEach(() => { + consoleOutput = []; + }); + }); }); diff --git a/types.ts b/types.ts index 5d612493..749f16e2 100644 --- a/types.ts +++ b/types.ts @@ -24,6 +24,7 @@ export interface ServerlessInstance { // tslint:disable-line hostedZonePrivate: boolean | undefined, enabled: boolean | string | undefined, securityPolicy: string | undefined, + createDomainName: boolean | undefined, }, }, }; From 7ecb23fd12b98da92b046ce439819ead45e9577e Mon Sep 17 00:00:00 2001 From: Hunter Date: Wed, 15 Apr 2020 13:41:41 -0500 Subject: [PATCH 11/69] update version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e438a93c..c918042e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.1", + "version": "3.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 102f8230..e7717b49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.1", + "version": "3.3.2", "engines": { "node": ">=4.0" }, From 6b107d324de49d70ec66a4538ba00a78318e55a8 Mon Sep 17 00:00:00 2001 From: Hunter Date: Wed, 15 Apr 2020 13:54:42 -0500 Subject: [PATCH 12/69] fix lint errors --- test/unit-tests/index.test.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index d37ee13d..5a446639 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -62,6 +62,7 @@ const constructPlugin = (customDomainOptions) => { basePath: customDomainOptions.basePath, certificateArn: customDomainOptions.certificateArn, certificateName: customDomainOptions.certificateName, + createDomainName: customDomainOptions.createDomainName, createRoute53Record: customDomainOptions.createRoute53Record, domainName: customDomainOptions.domainName, enabled: customDomainOptions.enabled, @@ -70,7 +71,6 @@ const constructPlugin = (customDomainOptions) => { hostedZonePrivate: customDomainOptions.hostedZonePrivate, securityPolicy: customDomainOptions.securityPolicy, stage: customDomainOptions.stage, - createDomainName: customDomainOptions.createDomainName }, }, provider: { @@ -1180,9 +1180,9 @@ describe("Custom Domain Plugin", () => { it("Should be disabled by default", () => { const plugin = constructPlugin({ domainName: "test_domain" }); plugin.initializeVariables(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.undefined; + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(undefined); }); - + it("setUpBasePathMapping should call createDomain when createDomainName is true", async () => { AWS.mock("APIGateway", "getDomainName", (params, callback) => { callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); @@ -1211,8 +1211,8 @@ describe("Custom Domain Plugin", () => { await plugin.setupBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.true; - expect(spy).to.have.been.called.once; + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(true); + expect(spy).to.have.been.called(); }); it("setUpBasePathMapping should not call createDomain when createDomainName is not true", async () => { @@ -1234,7 +1234,7 @@ describe("Custom Domain Plugin", () => { }, }); }); - const plugin = constructPlugin({ domainName: "test_domain", createDomainName: false }); + const plugin = constructPlugin({ createDomainName: false, domainName: "test_domain" }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); plugin.cloudformation = new aws.CloudFormation(); @@ -1243,8 +1243,8 @@ describe("Custom Domain Plugin", () => { await plugin.setupBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.false; - expect(spy).to.not.have.been.called; + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(false); + expect(spy).to.not.have.been.called(); }); it("removeBasePathMapping should call deleteDomain when createDomainName is true", async () => { @@ -1257,7 +1257,7 @@ describe("Custom Domain Plugin", () => { AWS.mock("APIGateway", "deleteDomainName", (params, callback) => { callback(null, params); }); - const plugin = constructPlugin({ domainName: "test_domain", createDomainName: true, createRoute53Record: false }); + const plugin = constructPlugin({ createDomainName: true, createRoute53Record: false, domainName: "test_domain" }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; @@ -1265,8 +1265,8 @@ describe("Custom Domain Plugin", () => { await plugin.removeBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.true; - expect(spy).to.have.been.called.once; + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(true); + expect(spy).to.have.been.called(); }); it("removeBasePathMapping should not call deleteDomain when createDomainName is not true", async () => { @@ -1276,8 +1276,8 @@ describe("Custom Domain Plugin", () => { await plugin.removeBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.be.false; - expect(spy).to.not.have.been.called; + expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(false); + expect(spy).to.not.have.been.called(); }); afterEach(() => { From b7bff0c73ebaf1e91a418292e4bb72a0bf7e6d9b Mon Sep 17 00:00:00 2001 From: Hunter Date: Fri, 17 Apr 2020 08:47:18 -0500 Subject: [PATCH 13/69] add to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 70333413..4a96cbdf 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 + createCustomDomain: false ``` | Parameter Name | Default Value | Description | @@ -85,6 +86,7 @@ custom: | hostedZonePrivate | | If hostedZonePrivate is set to `true` then only private hosted zones will be used for route 53 records. If it is set to `false` then only public hosted zones will be used for route53 records. Setting this parameter is specially useful if you have multiple hosted zones with the same domain name (e.g. a public and a private one) | | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| +| createCustomDomain | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | ## Running From 2c660f2b737cfd624b5ad840f69575580acd73e7 Mon Sep 17 00:00:00 2001 From: Hunter Date: Fri, 17 Apr 2020 08:48:41 -0500 Subject: [PATCH 14/69] fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a96cbdf..4e2af041 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 - createCustomDomain: false + createDomainName: false ``` | Parameter Name | Default Value | Description | @@ -86,7 +86,7 @@ custom: | hostedZonePrivate | | If hostedZonePrivate is set to `true` then only private hosted zones will be used for route 53 records. If it is set to `false` then only public hosted zones will be used for route53 records. Setting this parameter is specially useful if you have multiple hosted zones with the same domain name (e.g. a public and a private one) | | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| -| createCustomDomain | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | +| createDomainName | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | ## Running From 66a014ab62559ee38ca43f4695271defe36456e7 Mon Sep 17 00:00:00 2001 From: Johnathan Constance Date: Mon, 20 Apr 2020 11:23:11 -0400 Subject: [PATCH 15/69] Reminder to Allow Edits From Maintainers --- .github/PULL_REQUEST_TEMPLATE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 121a4095..ff89b601 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,3 +8,5 @@ Fixes #0000 * Change 1 * Change 2 + + From 9da58ac7c54e950afb4b44ae9a49e4449df302f8 Mon Sep 17 00:00:00 2001 From: Johnathan Constance Date: Tue, 21 Apr 2020 00:31:21 -0400 Subject: [PATCH 16/69] Only Deploy if Version is Updated We want to move to a model where we don't require committers to bump the version number themselves, as this makes merging in the PRs annoying. So instead, let's only deploy if the version number in package.json has changed. Also fixed some annoying whitespace inconsistency. --- .travis.yml | 17 +++++++++++------ scripts/versionCheck.sh | 19 ------------------- 2 files changed, 11 insertions(+), 25 deletions(-) delete mode 100644 scripts/versionCheck.sh diff --git a/.travis.yml b/.travis.yml index 14fb2308..4f768b5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,20 @@ language: node_js node_js: -- 10.4.0 + - 10.4.0 before_install: - npm i -g npm@6.4.1 install: -- npm install + - npm install script: -- npm run lint -- bash scripts/versionCheck.sh $TRAVIS_BRANCH $TRAVIS_PULL_REQUEST -- npm test + - npm run lint + - npm test before_deploy: -- npm run build + # Only deploy if the version number has changed + - | + if git diff --unified=0 $TRAVIS_COMMIT_RANGE package.json | grep version ; then + export VERSION_CHANGED="yes" + npm run build + fi deploy: skip_cleanup: true provider: npm @@ -18,3 +22,4 @@ deploy: api_key: $NPM_KEY on: branch: master + condition: "$VERSION_CHANGED == 'yes'" diff --git a/scripts/versionCheck.sh b/scripts/versionCheck.sh deleted file mode 100644 index 130650b8..00000000 --- a/scripts/versionCheck.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -set -e # halt script on error - -TARGET_BRANCH=$1 -IS_PULL_REQUEST=$2 # false if not a pull request, - -# Makes sure travis checks version only if doing a pull request -if [ "$IS_PULL_REQUEST" != "false" ] - then - PACKAGE_VERSION=$(grep version package.json | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d ':space:') && echo "Package Version: $PACKAGE_VERSION" - CURRENT_PACKAGE_VERSION=$(git show 'origin/'"$TARGET_BRANCH"':package.json' | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d ':space:') && echo "Latest Version: $CURRENT_PACKAGE_VERSION" - - if [ "$CURRENT_PACKAGE_VERSION" = "$PACKAGE_VERSION" ] - then - echo "Failure reason: Version number should be bumped." - exit 1 - fi -fi From 272e1b7c3af2718b435f8b8b6a45f986c783f591 Mon Sep 17 00:00:00 2001 From: Johnathan Constance Date: Tue, 21 Apr 2020 01:23:01 -0400 Subject: [PATCH 17/69] Move this up so it actually gets set --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f768b5d..4e7c8d72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,11 @@ language: node_js node_js: - 10.4.0 before_install: + # Only deploy if the version number has changed + - | + if git diff --unified=0 $TRAVIS_COMMIT_RANGE package.json | grep version ; then + export VERSION_CHANGED="yes" + fi - npm i -g npm@6.4.1 install: - npm install @@ -9,12 +14,7 @@ script: - npm run lint - npm test before_deploy: - # Only deploy if the version number has changed - - | - if git diff --unified=0 $TRAVIS_COMMIT_RANGE package.json | grep version ; then - export VERSION_CHANGED="yes" - npm run build - fi + - npm run build deploy: skip_cleanup: true provider: npm From d9a49f4cce417371061a376613d8fb9db8cab5bf Mon Sep 17 00:00:00 2001 From: Jason Venable Date: Sun, 16 Feb 2020 21:45:52 -0500 Subject: [PATCH 18/69] Add support for HTTP and WebSocket Domain Names --- DomainConfig.ts | 100 +++++ DomainInfo.ts | 18 +- Globals.ts | 23 ++ README.md | 56 ++- index.ts | 723 ++++++++++++++++++++-------------- package-lock.json | 105 +++-- test/unit-tests/index.test.ts | 614 +++++++++++++++++++++-------- types.ts | 2 + 8 files changed, 1155 insertions(+), 486 deletions(-) create mode 100644 DomainConfig.ts create mode 100644 Globals.ts diff --git a/DomainConfig.ts b/DomainConfig.ts new file mode 100644 index 00000000..5a67ed01 --- /dev/null +++ b/DomainConfig.ts @@ -0,0 +1,100 @@ +/** + * Wrapper class for Custom Domain information + */ + +import Globals from "./Globals"; +import DomainInfo = require("./DomainInfo"); +import * as AWS from "aws-sdk"; // imported for Types + +class DomainConfig { + + public givenDomainName: string; + public basePath: string | undefined; + public stage: string | undefined; + public certificateName: string | undefined; + public certificateArn: string | undefined; + public createRoute53Record: boolean | undefined; + public endpointType: string | undefined; + public apiType: string | undefined; + public hostedZoneId: string | undefined; + public hostedZonePrivate: boolean | undefined; + public enabled: boolean | string | undefined; + public securityPolicy: string | undefined; + + public domainInfo: DomainInfo | undefined; + public apiId: string | undefined; + public apiMapping: AWS.ApiGatewayV2.GetApiMappingResponse; + public allowPathMatching: boolean | false; + + constructor(config: any) { + + this.enabled = this.evaluateEnabled(config.enabled); + this.givenDomainName = config.domainName; + this.hostedZonePrivate = config.hostedZonePrivate; + this.certificateArn = config.certificateArn; + this.certificateName = config.certificateName; + this.createRoute53Record = config.createRoute53Record; + this.hostedZoneId = config.hostedZoneId; + this.hostedZonePrivate = config.hostedZonePrivate; + this.allowPathMatching = config.allowPathMatching; + + let basePath = config.basePath; + if (basePath == null || basePath.trim() === "") { + basePath = "(none)"; + } + this.basePath = basePath; + + let stage = config.stage; + if (typeof stage === "undefined") { + stage = Globals.options.stage || Globals.serverless.service.provider.stage; + } + this.stage = stage; + + const endpointTypeWithDefault = config.endpointType || Globals.endpointTypes.edge; + const endpointTypeToUse = Globals.endpointTypes[endpointTypeWithDefault.toLowerCase()]; + if (!endpointTypeToUse) { + throw new Error(`${endpointTypeWithDefault} is not supported endpointType, use edge or regional.`); + } + this.endpointType = endpointTypeToUse; + + const apiTypeWithDefault = config.apiType || Globals.apiTypes.rest; + const apiTypeToUse = Globals.apiTypes[apiTypeWithDefault.toLowerCase()]; + if (!apiTypeToUse) { + throw new Error(`${apiTypeWithDefault} is not supported api type, use REST, HTTP or WEBSOCKET.`); + } + this.apiType = apiTypeToUse; + + const securityPolicyDefault = config.securityPolicy || Globals.tlsVersions.tls_1_2; + const tlsVersionToUse = Globals.tlsVersions[securityPolicyDefault.toLowerCase()]; + if (!tlsVersionToUse) { + throw new Error(`${securityPolicyDefault} is not a supported securityPolicy, use tls_1_0 or tls_1_2.`); + } + this.securityPolicy = tlsVersionToUse; + } + + /** + * Determines whether this plug-in is enabled. + * + * This method reads the customDomain property "enabled" to see if this plug-in should be enabled. + * If the property's value is undefined, a default value of true is assumed (for backwards + * compatibility). + * If the property's value is provided, this should be boolean, otherwise an exception is thrown. + * If no customDomain object exists, an exception is thrown. + */ + public evaluateEnabled(enabled: any): boolean { + // const enabled = this.serverless.service.custom.customDomain.enabled; + if (enabled === undefined) { + return true; + } + if (typeof enabled === "boolean") { + return enabled; + } else if (typeof enabled === "string" && enabled === "true") { + return true; + } else if (typeof enabled === "string" && enabled === "false") { + return false; + } + throw new Error(`serverless-domain-manager: Ambiguous enablement boolean: "${enabled}"`); + } +} + +export = DomainConfig; diff --git a/DomainInfo.ts b/DomainInfo.ts index 113bb75d..7b40fc26 100644 --- a/DomainInfo.ts +++ b/DomainInfo.ts @@ -18,11 +18,19 @@ class DomainInfo { private defaultSecurityPolicy: string = "TLS_1_2"; constructor(data: any) { - this.domainName = data.distributionDomainName || data.regionalDomainName; - this.hostedZoneId = data.distributionHostedZoneId || - data.regionalHostedZoneId || - this.defaultHostedZoneId; - this.securityPolicy = data.securityPolicy || this.defaultSecurityPolicy; + this.domainName = data.distributionDomainName + || data.regionalDomainName + || data.DomainNameConfigurations && data.DomainNameConfigurations[0].ApiGatewayDomainName + || data.DomainName; + + this.hostedZoneId = data.distributionHostedZoneId + || data.regionalHostedZoneId + || data.DomainNameConfigurations && data.DomainNameConfigurations[0].HostedZoneId + || this.defaultHostedZoneId; + + this.securityPolicy = data.securityPolicy + || data.DomainNameConfigurations && data.DomainNameConfigurations[0].SecurityPolicy + || this.defaultSecurityPolicy; } } diff --git a/Globals.ts b/Globals.ts new file mode 100644 index 00000000..d95ee9de --- /dev/null +++ b/Globals.ts @@ -0,0 +1,23 @@ +import { ServerlessInstance, ServerlessOptions } from "./types"; + +export default class Globals { + + public static serverless: ServerlessInstance; + public static options: ServerlessOptions; + + public static endpointTypes = { + edge: "EDGE", + regional: "REGIONAL", + }; + + public static apiTypes = { + http: "HTTP", + rest: "REST", + websocket: "WEBSOCKET", + }; + + public static tlsVersions = { + tls_1_0: "TLS_1_0", + tls_1_2: "TLS_1_2", + }; +} diff --git a/README.md b/README.md index 70333413..a3b12207 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ plugins: - serverless-domain-manager ``` -Add the plugin configuration (example for `serverless.foo.com/api`). +Add the plugin configuration (example for `serverless.foo.com/api`). For a single domain and API type the following sturcture can be used. ```yaml custom: @@ -70,6 +70,38 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 + apiType: rest +``` + +Multiple API types mapped to different domains can also be supported with the follow structure. The key is the API Gateway API type. + +```yaml +custom: + customDomain: + rest: + domainName: rest.serverless.foo.com + stage: ci + basePath: api + certificateName: '*.foo.com' + createRoute53Record: true + endpointType: 'regional' + securityPolicy: tls_1_2 + http: + domainName: http.serverless.foo.com + stage: ci + basePath: api + certificateName: '*.foo.com' + createRoute53Record: true + endpointType: 'regional' + securityPolicy: tls_1_2 + websocket: + domainName: ws.serverless.foo.com + stage: ci + basePath: api + certificateName: '*.foo.com' + createRoute53Record: true + endpointType: 'regional' + securityPolicy: tls_1_2 ``` | Parameter Name | Default Value | Description | @@ -81,10 +113,13 @@ custom: | certificateArn | `(none)` | The arn of a specific certificate from Certificate Manager to use with this API. | | createRoute53Record | `true` | Toggles whether or not the plugin will create an A Alias and AAAA Alias records in Route53 mapping the `domainName` to the generated distribution domain name. If false, does not create a record. | | endpointType | edge | Defines the endpoint type, accepts `regional` or `edge`. | +| apiType | rest | Defines the api type, accepts `rest`, `http` or `websocket`. | | hostedZoneId | | If hostedZoneId is set the route53 record set will be created in the matching zone, otherwise the hosted zone will be figured out from the domainName (hosted zone with matching domain). | | hostedZonePrivate | | If hostedZonePrivate is set to `true` then only private hosted zones will be used for route 53 records. If it is set to `false` then only public hosted zones will be used for route53 records. Setting this parameter is specially useful if you have multiple hosted zones with the same domain name (e.g. a public and a private one) | | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| +allowPathMatching | false | When updating an existing api mapping this will match on the basePath instead of the API ID to find existing mappings for an udpate. This should ony be used when changing API types. For example, migrating a REST API to an HTTP API. See Changing API Types for moe information. | + ## Running @@ -139,6 +174,25 @@ npm install ## Writing Integration Tests Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `integration.test.js`. +## Changing API Types +AWS API Gateway has three different API types: REST, HTTP, and WebSocket. Special steps need to be taken when migrating from one api type to another. A common migration will be from a REST API to an HTTP API given the potential cost savings. Below are the steps required to change from REST to HTTP. A similar process can be applied for other API type migrations. + +**REST to HTTP** +1) Confirm the Domain name is a Regional domain name. Edge domains are not supported by AWS for HTTP APIs. See this [guide for migrating an edge-optimized custom domain name to regional]( +https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-regional-api-custom-domain-migrate.html). +2) Wait for all DNS changes to take effect/propagate and ensure all traffic is being routed to the regional domain name before proceeding. +3) Make sure you have setup new or modified existing routes to use [httpApi event](https://serverless.com/framework/docs/providers/aws/events/http-api) in your serverless.yml file. +4) Make the following changes to the `customDomain` properties in the serverless.yml confg: + ```yaml + endpointType: regional + apiType: http + allowPathMatching: true # Only for one deploy + ``` +5) Run `sls deploy` +6) Remove the `allowPathMatching` option, it should only be used once when migrating a base path from one API type to another. + +NOTE: Always test this process in a lower level staging or development environment before performing it in production. + # Known Issues * (5/23/2017) CloudFormation does not support changing the base path from empty to something or vice a versa. You must run `sls remove` to remove the base path mapping. diff --git a/index.ts b/index.ts index 6cf8a81d..f3b034ef 100644 --- a/index.ts +++ b/index.ts @@ -2,24 +2,17 @@ import chalk from "chalk"; import DomainInfo = require("./DomainInfo"); +import DomainConfig = require("./DomainConfig"); +import Globals from "./Globals"; import { ServerlessInstance, ServerlessOptions } from "./types"; -const endpointTypes = { - edge: "EDGE", - regional: "REGIONAL", -}; - -const tlsVersions = { - tls_1_0: "TLS_1_0", - tls_1_2: "TLS_1_2", -}; - const certStatuses = ["PENDING_VALIDATION", "ISSUED", "INACTIVE"]; class ServerlessCustomDomain { // AWS SDK resources public apigateway: any; + public apigatewayV2: any; public route53: any; public acm: any; public acmRegion: string; @@ -32,17 +25,14 @@ class ServerlessCustomDomain { public hooks: object; // Domain Manager specific properties - public enabled: boolean; - public givenDomainName: string; - public hostedZonePrivate: boolean; - public basePath: string; - private endpointType: string; - private stage: string; - private securityPolicy: string; + public domains: DomainConfig[] = []; constructor(serverless: ServerlessInstance, options: ServerlessOptions) { this.serverless = serverless; + Globals.serverless = serverless; + this.options = options; + Globals.options = options; this.commands = { create_domain: { @@ -61,12 +51,12 @@ class ServerlessCustomDomain { }, }; this.hooks = { - "after:deploy:deploy": this.hookWrapper.bind(this, this.setupBasePathMapping), - "after:info:info": this.hookWrapper.bind(this, this.domainSummary), + "after:deploy:deploy": this.hookWrapper.bind(this, this.setupBasePathMappings), + "after:info:info": this.hookWrapper.bind(this, this.domainSummaries), "before:deploy:deploy": this.hookWrapper.bind(this, this.updateCloudFormationOutputs), - "before:remove:remove": this.hookWrapper.bind(this, this.removeBasePathMapping), - "create_domain:create": this.hookWrapper.bind(this, this.createDomain), - "delete_domain:delete": this.hookWrapper.bind(this, this.deleteDomain), + "before:remove:remove": this.hookWrapper.bind(this, this.removeBasePathMappings), + "create_domain:create": this.hookWrapper.bind(this, this.createDomains), + "delete_domain:delete": this.hookWrapper.bind(this, this.deleteDomains), }; } @@ -75,199 +65,255 @@ class ServerlessCustomDomain { * @param lifecycleFunc lifecycle function that actually does desired action */ public async hookWrapper(lifecycleFunc: any) { + this.initializeVariables(); - if (!this.enabled) { - this.serverless.cli.log("serverless-domain-manager: Custom domain is disabled."); - return; - } else { - return await lifecycleFunc.call(this); - } + + return await lifecycleFunc.call(this); } /** * Lifecycle function to create a domain * Wraps creating a domain and resource record set */ - public async createDomain(): Promise { - let domainInfo; - try { - domainInfo = await this.getDomainInfo(); - } catch (err) { - if (err.message !== `Error: ${this.givenDomainName} not found.`) { - throw err; + public async createDomains(): Promise { + + await this.getDomainInfo(); + + await Promise.all(this.domains.map(async (domain) => { + try { + if (!domain.domainInfo) { + + domain.certificateArn = await this.getCertArn(domain); + + await this.createCustomDomain(domain); + + await this.changeResourceRecordSet("UPSERT", domain); + + this.serverless.cli.log( + `Custom domain ${domain.givenDomainName} was created. + New domains may take up to 40 minutes to be initialized.`, + ); + } else { + this.serverless.cli.log(`Custom domain ${domain.givenDomainName} already exists.`); + } + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Unable to craete domain ${domain.givenDomainName}`); } - } - if (!domainInfo) { - const certArn = await this.getCertArn(); - domainInfo = await this.createCustomDomain(certArn); - await this.changeResourceRecordSet("UPSERT", domainInfo); - this.serverless.cli.log( - `Custom domain ${this.givenDomainName} was created. - New domains may take up to 40 minutes to be initialized.`, - ); - } else { - this.serverless.cli.log(`Custom domain ${this.givenDomainName} already exists.`); - } + })); } /** * Lifecycle function to delete a domain * Wraps deleting a domain and resource record set */ - public async deleteDomain(): Promise { - let domainInfo; - try { - domainInfo = await this.getDomainInfo(); - } catch (err) { - if (err.message === `Error: ${this.givenDomainName} not found.`) { - this.serverless.cli.log(`Unable to delete custom domain ${this.givenDomainName}.`); - return; + public async deleteDomains(): Promise { + + await this.getDomainInfo(); + + await Promise.all(this.domains.map(async (domain) => { + try { + if (domain.domainInfo) { + await this.deleteCustomDomain(domain); + await this.changeResourceRecordSet("DELETE", domain); + domain.domainInfo = undefined; + this.serverless.cli.log(`Custom domain ${domain.givenDomainName} was deleted.`); + } else { + this.serverless.cli.log(`Custom domain ${domain.givenDomainName} does not exists.`); + } + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Unable to delete domain ${domain.givenDomainName}`); } - throw err; - } - await this.deleteCustomDomain(); - await this.changeResourceRecordSet("DELETE", domainInfo); - this.serverless.cli.log(`Custom domain ${this.givenDomainName} was deleted.`); + })); } /** * Lifecycle function to add domain info to the CloudFormation stack's Outputs */ public async updateCloudFormationOutputs(): Promise { - const domainInfo = await this.getDomainInfo(); - this.addOutputs(domainInfo); + + await this.getDomainInfo(); + + await Promise.all(this.domains.map(async (domain) => { + this.addOutputs(domain); + })); } /** * Lifecycle function to create basepath mapping * Wraps creation of basepath mapping and adds domain name info as output to cloudformation stack */ - public async setupBasePathMapping(): Promise { - // check if basepathmapping exists - const restApiId = await this.getRestApiId(); - const currentBasePath = await this.getBasePathMapping(restApiId); - // if basepath that matches restApiId exists, update; else, create - if (!currentBasePath) { - await this.createBasePathMapping(restApiId); - } else { - await this.updateBasePathMapping(currentBasePath); - } - const domainInfo = await this.getDomainInfo(); - await this.printDomainSummary(domainInfo); + public async setupBasePathMappings(): Promise { + await Promise.all(this.domains.map(async (domain) => { + try { + domain.apiId = await this.getApiId(domain); + + domain.apiMapping = await this.getBasePathMapping(domain); + + if (!domain.apiMapping) { + await this.createBasePathMapping(domain); + } else { + await this.updateBasePathMapping(domain); + } + + await this.getDomainInfo(); + // this.addOutputs(domain); + + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Unable to setup base domain mappings for ${domain.givenDomainName}`); + } + })).then(() => { + // Print summary upon completion + this.domains.forEach((domain) => { + this.printDomainSummary(domain); + }); + }); } /** * Lifecycle function to delete basepath mapping * Wraps deletion of basepath mapping */ - public async removeBasePathMapping(): Promise { - await this.deleteBasePathMapping(); + public async removeBasePathMappings(): Promise { + await Promise.all(this.domains.map(async (domain) => { + try { + domain.apiId = await this.getApiId(domain); + + // Unable to find the correspond API, manuall clean up will be required + if (!domain.apiId) { + this.serverless.cli.log(`Unable to find corresponding API for ${domain.givenDomainName}, + API Mappings may need to be manually removed.`, "Serverless Domain Manager"); + } else { + domain.apiMapping = await this.getBasePathMapping(domain); + await this.deleteBasePathMapping(domain); + } + } catch (err) { + if (err.message.indexOf("Failed to find CloudFormation") > -1) { + this.serverless.cli.log(`Unable to find Cloudformation Stack for ${domain.givenDomainName}, + API Mappings may need to be manually removed.`, "Serverless Domain Manager"); + } else { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Unable to remove base bath mappings for domain ${domain.givenDomainName}`); + } + } + })); } /** * Lifecycle function to print domain summary * Wraps printing of all domain manager related info */ - public async domainSummary(): Promise { - const domainInfo = await this.getDomainInfo(); - if (domainInfo) { - this.printDomainSummary(domainInfo); - } else { - this.serverless.cli.log("Unable to print Serverless Domain Manager Summary"); - } + public async domainSummaries(): Promise { + await this.getDomainInfo(); + + this.domains.forEach((domain) => { + if (domain.domainInfo) { + this.printDomainSummary(domain); + } else { + this.serverless.cli.log( + `Unable to print Serverless Domain Manager Summary for ${domain.givenDomainName}`, + ); + } + }); } /** * Goes through custom domain property and initializes local variables and cloudformation template */ public initializeVariables(): void { - this.enabled = this.evaluateEnabled(); - if (this.enabled) { - const credentials = this.serverless.providers.aws.getCredentials(); - credentials.region = this.serverless.providers.aws.getRegion(); - - this.serverless.providers.aws.sdk.config.update({maxRetries: 20}); - this.apigateway = new this.serverless.providers.aws.sdk.APIGateway(credentials); - this.route53 = new this.serverless.providers.aws.sdk.Route53(credentials); - this.cloudformation = new this.serverless.providers.aws.sdk.CloudFormation(credentials); - - this.givenDomainName = this.serverless.service.custom.customDomain.domainName; - this.hostedZonePrivate = this.serverless.service.custom.customDomain.hostedZonePrivate; - let basePath = this.serverless.service.custom.customDomain.basePath; - if (basePath == null || basePath.trim() === "") { - basePath = "(none)"; - } - this.basePath = basePath; - let stage = this.serverless.service.custom.customDomain.stage; - if (typeof stage === "undefined") { - stage = this.options.stage || this.serverless.service.provider.stage; - } - this.stage = stage; - const endpointTypeWithDefault = this.serverless.service.custom.customDomain.endpointType || - endpointTypes.edge; - const endpointTypeToUse = endpointTypes[endpointTypeWithDefault.toLowerCase()]; - if (!endpointTypeToUse) { - throw new Error(`${endpointTypeWithDefault} is not supported endpointType, use edge or regional.`); - } - this.endpointType = endpointTypeToUse; + // Make sure customDomain configuration exists, stop if not + if (typeof this.serverless.service.custom === "undefined" + || typeof this.serverless.service.custom.customDomain === "undefined") { + throw new Error("serverless-domain-manager: Plugin configuration is missing."); + } + + const credentials = this.serverless.providers.aws.getCredentials(); + credentials.region = this.serverless.providers.aws.getRegion(); - const securityPolicyDefault = this.serverless.service.custom.customDomain.securityPolicy || - tlsVersions.tls_1_2; - const tlsVersionToUse = tlsVersions[securityPolicyDefault.toLowerCase()]; - if (!tlsVersionToUse) { - throw new Error(`${securityPolicyDefault} is not a supported securityPolicy, use tls_1_0 or tls_1_2.`); + this.serverless.providers.aws.sdk.config.update({ maxRetries: 20 }); + this.apigateway = new this.serverless.providers.aws.sdk.APIGateway(credentials); + this.apigatewayV2 = new this.serverless.providers.aws.sdk.ApiGatewayV2(credentials); + this.route53 = new this.serverless.providers.aws.sdk.Route53(credentials); + this.cloudformation = new this.serverless.providers.aws.sdk.CloudFormation(credentials); + + // Loop over the domain configurations and popluates the domains array with DomainConfigs + this.domains = []; + + // If the key of the item in config is an api type it is using per api type domain structure + if (Globals.apiTypes[Object.keys(this.serverless.service.custom.customDomain)[0]]) { + for (const configApiType in this.serverless.service.custom.customDomain) { + if (Globals.apiTypes[configApiType]) { // If statement check to follow tslint + this.serverless.service.custom.customDomain[configApiType].apiType = configApiType; + this.domains.push(new DomainConfig(this.serverless.service.custom.customDomain[configApiType])); + } else { + throw Error(`Error: Invalud API Type, ${configApiType}`); + } } - this.securityPolicy = tlsVersionToUse; + } else { // Default to single domain config + this.domains.push(new DomainConfig(this.serverless.service.custom.customDomain)); + } - this.acmRegion = this.endpointType === endpointTypes.regional ? + // Filter inactive domains + this.domains = this.domains.filter((domain) => domain.enabled); + + // Set ACM Region on the domain configs + for (const dc of this.domains) { + this.acmRegion = dc.endpointType === Globals.endpointTypes.regional ? this.serverless.providers.aws.getRegion() : "us-east-1"; const acmCredentials = Object.assign({}, credentials, { region: this.acmRegion }); this.acm = new this.serverless.providers.aws.sdk.ACM(acmCredentials); } + + // Validate the domain configuraitons + this.validateDomainConfigs(); } /** - * Determines whether this plug-in is enabled. - * - * This method reads the customDomain property "enabled" to see if this plug-in should be enabled. - * If the property's value is undefined, a default value of true is assumed (for backwards - * compatibility). - * If the property's value is provided, this should be boolean, otherwise an exception is thrown. - * If no customDomain object exists, an exception is thrown. + * Validates domain configs to make sure they are valid, ie HTTP api cannot be used with EDGE domain */ - public evaluateEnabled(): boolean { - if (typeof this.serverless.service.custom === "undefined" - || typeof this.serverless.service.custom.customDomain === "undefined") { - throw new Error("serverless-domain-manager: Plugin configuration is missing."); - } + public validateDomainConfigs() { + this.domains.forEach((domain) => { - const enabled = this.serverless.service.custom.customDomain.enabled; - if (enabled === undefined) { - return true; - } - if (typeof enabled === "boolean") { - return enabled; - } else if (typeof enabled === "string" && enabled === "true") { - return true; - } else if (typeof enabled === "string" && enabled === "false") { - return false; - } - throw new Error(`serverless-domain-manager: Ambiguous enablement boolean: "${enabled}"`); + // Show warning if allowPathMatching is set to true + if (domain.allowPathMatching) { + this.serverless.cli.log(`WARNING: "allowPathMatching" is set for ${domain.givenDomainName}. + This should only be used when migrating a path to a different API type. e.g. REST to HTTP.`); + } + + if (domain.apiType === Globals.apiTypes.rest) { + // Currently no validation for REST API types + + } else if (domain.apiType === Globals.apiTypes.http) { // Validation for http apis + // HTTP Apis do not support edge domains + if (domain.endpointType === Globals.endpointTypes.edge) { + throw Error(`Error: 'edge' endpointType is not compatible with HTTP APIs`); + } + + } else if (domain.apiType === Globals.apiTypes.websocket) { // Validation for WebSocket apis + // Websocket Apis do not support edge domains + if (domain.endpointType === Globals.endpointTypes.edge) { + throw Error(`Error: 'edge' endpointType is not compatible with WebSocket APIs`); + } + } + }); } /** * Gets Certificate ARN that most closely matches domain name OR given Cert ARN if provided */ - public async getCertArn(): Promise { - if (this.serverless.service.custom.customDomain.certificateArn) { - this.serverless.cli.log( - `Selected specific certificateArn ${this.serverless.service.custom.customDomain.certificateArn}`); - return this.serverless.service.custom.customDomain.certificateArn; + public async getCertArn(domain: DomainConfig): Promise { + if (domain.certificateArn) { + this.serverless.cli.log(`Selected specific certificateArn ${domain.certificateArn}`); + return domain.certificateArn; } let certificateArn; // The arn of the choosen certificate - let certificateName = this.serverless.service.custom.customDomain.certificateName; // The certificate name + + let certificateName = domain.certificateName; // The certificate name + try { let certificates = []; let nextToken; @@ -289,7 +335,7 @@ class ServerlessCustomDomain { certificateArn = foundCertificate.CertificateArn; } } else { - certificateName = this.givenDomainName; + certificateName = domain.givenDomainName; certificates.forEach((certificate) => { let certificateListName = certificate.DomainName; // Looks for wild card and takes it out when checking @@ -306,7 +352,7 @@ class ServerlessCustomDomain { }); } } catch (err) { - this.logIfDebug(err); + this.logIfDebug(err, domain.givenDomainName); throw Error(`Error: Could not list certificates in Certificate Manager.\n${err}`); } if (certificateArn == null) { @@ -316,68 +362,87 @@ class ServerlessCustomDomain { } /** - * Gets domain info as DomainInfo object if domain exists, otherwise returns false + * Populates the DomainInfo object on the Domains if custom domain in aws exists */ - public async getDomainInfo(): Promise { - let domainInfo; - try { - domainInfo = await this.apigateway.getDomainName({ domainName: this.givenDomainName }).promise(); - return new DomainInfo(domainInfo); - } catch (err) { - this.logIfDebug(err); - if (err.code === "NotFoundException") { - throw new Error(`Error: ${this.givenDomainName} not found.`); + public async getDomainInfo(): Promise { + await Promise.all(this.domains.map(async (domain) => { + try { + const domainInfo = await this.apigatewayV2.getDomainName({ + DomainName: domain.givenDomainName, + }).promise(); + + domain.domainInfo = new DomainInfo(domainInfo); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + if (err.code !== "NotFoundException") { + throw new Error(`Error: Unable to fetch information about ${domain.givenDomainName}`); + } } - throw new Error(`Error: Unable to fetch information about ${this.givenDomainName}`); - } + })); } /** * Creates Custom Domain Name through API Gateway * @param certificateArn: Certificate ARN to use for custom domain */ - public async createCustomDomain(certificateArn: string): Promise { - // Set up parameters - const params = { - certificateArn, - domainName: this.givenDomainName, - endpointConfiguration: { - types: [this.endpointType], - }, - regionalCertificateArn: certificateArn, - securityPolicy: this.securityPolicy, - }; - if (this.endpointType === endpointTypes.edge) { - params.regionalCertificateArn = undefined; - } else if (this.endpointType === endpointTypes.regional) { - params.certificateArn = undefined; - } + public async createCustomDomain(domain: DomainConfig): Promise { - // Make API call let createdDomain = {}; - try { - createdDomain = await this.apigateway.createDomainName(params).promise(); - } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Failed to create custom domain ${this.givenDomainName}\n`); + + // For EDGE domain name, create with APIGateway (v1) + if (domain.endpointType === Globals.endpointTypes.edge) { + // Set up parameters + const params = { + certificateArn: domain.certificateArn, + domainName: domain.givenDomainName, + endpointConfiguration: { + types: [domain.endpointType], + }, + securityPolicy: domain.securityPolicy, + }; + + // Make API call to create domain + try { + // If creating REST api use v1 of api gateway, else use v2 for HTTP and Websocket + createdDomain = await this.apigateway.createDomainName(params).promise(); + domain.domainInfo = new DomainInfo(createdDomain); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Failed to create custom domain ${domain.givenDomainName}\n`); + } + + } else { // For Regional domain name create with ApiGatewayV2 + const params = { + DomainName: domain.givenDomainName, + DomainNameConfigurations: [{ + CertificateArn: domain.certificateArn, + EndpointType: domain.endpointType, + SecurityPolicy: domain.securityPolicy, + }], + }; + + // Make API call to create domain + try { + // If creating REST api use v1 of api gateway, else use v2 for HTTP and Websocket + createdDomain = await this.apigatewayV2.createDomainName(params).promise(); + domain.domainInfo = new DomainInfo(createdDomain); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Failed to create custom domain ${domain.givenDomainName}\n`); + } } - return new DomainInfo(createdDomain); } /** * Delete Custom Domain Name through API Gateway */ - public async deleteCustomDomain(): Promise { - const params = { - domainName: this.givenDomainName, - }; - + public async deleteCustomDomain(domain: DomainConfig): Promise { // Make API call try { - await this.apigateway.deleteDomainName(params).promise(); + await this.apigatewayV2.deleteDomainName({DomainName: domain.givenDomainName}).promise(); } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Failed to delete custom domain ${this.givenDomainName}\n`); + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Failed to delete custom domain ${domain.givenDomainName}\n`); } } @@ -386,28 +451,28 @@ class ServerlessCustomDomain { * @param action: String descriptor of change to be made. Valid actions are ['UPSERT', 'DELETE'] * @param domain: DomainInfo object containing info about custom domain */ - public async changeResourceRecordSet(action: string, domain: DomainInfo): Promise { + public async changeResourceRecordSet(action: string, domain: DomainConfig): Promise { if (action !== "UPSERT" && action !== "DELETE") { throw new Error(`Error: Invalid action "${action}" when changing Route53 Record. Action must be either UPSERT or DELETE.\n`); } - const createRoute53Record = this.serverless.service.custom.customDomain.createRoute53Record; + const createRoute53Record = domain.createRoute53Record; if (createRoute53Record !== undefined && createRoute53Record === false) { - this.serverless.cli.log("Skipping creation of Route53 record."); + this.serverless.cli.log(`Skipping ${action === "DELETE" ? "removal" : "creation"} of Route53 record.`); return; } // Set up parameters - const route53HostedZoneId = await this.getRoute53HostedZoneId(); + const route53HostedZoneId = await this.getRoute53HostedZoneId(domain); const Changes = ["A", "AAAA"].map((Type) => ({ Action: action, ResourceRecordSet: { AliasTarget: { - DNSName: domain.domainName, + DNSName: domain.domainInfo.domainName, EvaluateTargetHealth: false, - HostedZoneId: domain.hostedZoneId, + HostedZoneId: domain.domainInfo.hostedZoneId, }, - Name: this.givenDomainName, + Name: domain.givenDomainName, Type, }, })); @@ -422,30 +487,30 @@ class ServerlessCustomDomain { try { await this.route53.changeResourceRecordSets(params).promise(); } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Failed to ${action} A Alias for ${this.givenDomainName}\n`); + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Failed to ${action} A Alias for ${domain.givenDomainName}\n`); } } /** * Gets Route53 HostedZoneId from user or from AWS */ - public async getRoute53HostedZoneId(): Promise { - if (this.serverless.service.custom.customDomain.hostedZoneId) { + public async getRoute53HostedZoneId(domain: DomainConfig): Promise { + if (domain.hostedZoneId) { this.serverless.cli.log( `Selected specific hostedZoneId ${this.serverless.service.custom.customDomain.hostedZoneId}`); - return this.serverless.service.custom.customDomain.hostedZoneId; + return domain.hostedZoneId; } - const filterZone = this.hostedZonePrivate !== undefined; - if (filterZone && this.hostedZonePrivate) { + const filterZone = domain.hostedZonePrivate !== undefined; + if (filterZone && domain.hostedZonePrivate) { this.serverless.cli.log("Filtering to only private zones."); - } else if (filterZone && !this.hostedZonePrivate) { + } else if (filterZone && !domain.hostedZonePrivate) { this.serverless.cli.log("Filtering to only public zones."); } let hostedZoneData; - const givenDomainNameReverse = this.givenDomainName.split(".").reverse(); + const givenDomainNameReverse = domain.givenDomainName.split(".").reverse(); try { hostedZoneData = await this.route53.listHostedZones({}).promise(); @@ -457,7 +522,7 @@ class ServerlessCustomDomain { } else { hostedZoneName = hostedZone.Name; } - if (!filterZone || this.hostedZonePrivate === hostedZone.Config.PrivateZone) { + if (!filterZone || domain.hostedZonePrivate === hostedZone.Config.PrivateZone) { const hostedZoneNameReverse = hostedZoneName.split(".").reverse(); if (givenDomainNameReverse.length === 1 @@ -483,93 +548,145 @@ class ServerlessCustomDomain { return hostedZoneId.substring(startPos, endPos); } } catch (err) { - this.logIfDebug(err); + this.logIfDebug(err, domain.givenDomainName); throw new Error(`Error: Unable to list hosted zones in Route53.\n${err}`); } - throw new Error(`Error: Could not find hosted zone "${this.givenDomainName}"`); + throw new Error(`Error: Could not find hosted zone "${domain.givenDomainName}"`); } - public async getBasePathMapping(restApiId: string): Promise { + public async getBasePathMapping(domain: DomainConfig): Promise { const params = { - domainName: this.givenDomainName, + DomainName: domain.givenDomainName, }; - let basepathInfo; - let currentBasePath; try { - basepathInfo = await this.apigateway.getBasePathMappings(params).promise(); - } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Unable to get BasePathMappings for ${this.givenDomainName}`); - } - if (basepathInfo.items !== undefined && basepathInfo.items instanceof Array) { - for (const basepathObj of basepathInfo.items) { - if (basepathObj.restApiId === restApiId) { - currentBasePath = basepathObj.basePath; - break; + const mappings = await this.apigatewayV2.getApiMappings(params).promise(); + + if (mappings.Items.length === 0) { + return; + } else { + for (const mapping of mappings.Items) { + if (mapping.ApiId === domain.apiId + || (mapping.ApiMappingKey === domain.basePath && domain.allowPathMatching) ) { + return mapping; + } } } + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Unable to get API Mappings for ${domain.givenDomainName}`); } - return currentBasePath; } /** * Creates basepath mapping */ - public async createBasePathMapping(restApiId: string): Promise { - const params = { - basePath: this.basePath, - domainName: this.givenDomainName, - restApiId, - stage: this.stage, - }; - // Make API call - try { - await this.apigateway.createBasePathMapping(params).promise(); - this.serverless.cli.log("Created basepath mapping."); - } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Unable to create basepath mapping.\n`); + public async createBasePathMapping(domain: DomainConfig): Promise { + // Use APIGateway (v1) for EDGE domains + if (domain.endpointType === Globals.endpointTypes.edge) { + const params = { + basePath: domain.basePath, + domainName: domain.givenDomainName, + restApiId: domain.apiId, + stage: domain.stage, + }; + // Make API call + try { + await this.apigateway.createBasePathMapping(params).promise(); + this.serverless.cli.log(`Created API mapping '${domain.basePath}' for ${domain.givenDomainName}`); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: ${domain.givenDomainName}: Unable to create basepath mapping.\n`); + } + + } else { // Use ApiGatewayV2 for Regional domains + const params = { + ApiId: domain.apiId, + ApiMappingKey: domain.basePath, + DomainName: domain.givenDomainName, + Stage: domain.apiType === Globals.apiTypes.http ? "$default" : domain.stage, + }; + // Make API call + try { + await this.apigatewayV2.createApiMapping(params).promise(); + this.serverless.cli.log(`Created API mapping '${domain.basePath}' for ${domain.givenDomainName}`); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: ${domain.givenDomainName}: Unable to create basepath mapping.\n`); + } } } /** * Updates basepath mapping */ - public async updateBasePathMapping(oldBasePath: string): Promise { - const params = { - basePath: oldBasePath, - domainName: this.givenDomainName, - patchOperations: [ - { - op: "replace", - path: "/basePath", - value: this.basePath, - }, - ], - }; - // Make API call - try { - await this.apigateway.updateBasePathMapping(params).promise(); - this.serverless.cli.log("Updated basepath mapping."); - } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Unable to update basepath mapping.\n`); + public async updateBasePathMapping(domain: DomainConfig): Promise { + // Use APIGateway (v1) for EDGE domains + if (domain.endpointType === Globals.endpointTypes.edge) { + const params = { + basePath: domain.apiMapping.ApiMappingKey, + domainName: domain.givenDomainName, + patchOperations: [ + { + op: "replace", + path: "/basePath", + value: domain.basePath, + }, + ], + }; + + // Make API call + try { + await this.apigateway.updateBasePathMapping(params).promise(); + this.serverless.cli.log(`Updated API mapping from '${domain.apiMapping.ApiMappingKey}' + to '${domain.basePath}' for ${domain.givenDomainName}`); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: ${domain.givenDomainName}: Unable to update basepath mapping.\n`); + } + + } else { // Use ApiGatewayV2 for Regional domains + + const params = { + ApiId: domain.apiId, + ApiMappingId: domain.apiMapping.ApiMappingId, + ApiMappingKey: domain.basePath, + DomainName: domain.givenDomainName, + Stage: domain.apiType === Globals.apiTypes.http ? "$default" : domain.stage, + }; + + // Make API call + try { + await this.apigatewayV2.updateApiMapping(params).promise(); + this.serverless.cli.log(`Updated API mapping to '${domain.basePath}' for ${domain.givenDomainName}`); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: ${domain.givenDomainName}: Unable to update basepath mapping.\n`); + } } } /** * Gets rest API id from CloudFormation stack */ - public async getRestApiId(): Promise { + public async getApiId(domain: DomainConfig): Promise { if (this.serverless.service.provider.apiGateway && this.serverless.service.provider.apiGateway.restApiId) { this.serverless.cli.log(`Mapping custom domain to existing API ${this.serverless.service.provider.apiGateway.restApiId}.`); return this.serverless.service.provider.apiGateway.restApiId; } + const stackName = this.serverless.service.provider.stackName || - `${this.serverless.service.service}-${this.stage}`; + `${this.serverless.service.service}-${domain.stage}`; + + let LogicalResourceId = "ApiGatewayRestApi"; + if (domain.apiType === Globals.apiTypes.http) { + LogicalResourceId = "HttpApi"; + } else if (domain.apiType === Globals.apiTypes.websocket) { + LogicalResourceId = "WebsocketsApi"; + } + const params = { - LogicalResourceId: "ApiGatewayRestApi", + LogicalResourceId, StackName: stackName, }; @@ -577,51 +694,72 @@ class ServerlessCustomDomain { try { response = await this.cloudformation.describeStackResource(params).promise(); } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Failed to find CloudFormation resources for ${this.givenDomainName}\n`); + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Error: Failed to find CloudFormation resources for ${domain.givenDomainName}\n`); } - const restApiId = response.StackResourceDetail.PhysicalResourceId; - if (!restApiId) { - throw new Error(`Error: No RestApiId associated with CloudFormation stack ${stackName}`); + + const apiId = response.StackResourceDetail.PhysicalResourceId; + if (!apiId) { + throw new Error(`Error: No ApiId associated with CloudFormation stack ${stackName}`); } - return restApiId; + return apiId; } /** * Deletes basepath mapping */ - public async deleteBasePathMapping(): Promise { + public async deleteBasePathMapping(domain: DomainConfig): Promise { const params = { - basePath: this.basePath, - domainName: this.givenDomainName, + ApiMappingId: domain.apiMapping.ApiMappingId, + DomainName: domain.givenDomainName, }; + // Make API call try { - await this.apigateway.deleteBasePathMapping(params).promise(); + await this.apigatewayV2.deleteApiMapping(params).promise(); this.serverless.cli.log("Removed basepath mapping."); } catch (err) { - this.logIfDebug(err); - this.serverless.cli.log("Unable to remove basepath mapping."); + this.logIfDebug(err, domain.givenDomainName); + this.serverless.cli.log(`Unable to remove basepath mapping for ${domain.givenDomainName}`); } } /** * Adds the domain name and distribution domain name to the CloudFormation outputs */ - public addOutputs(domainInfo: DomainInfo): void { + public addOutputs(domain: DomainConfig): void { const service = this.serverless.service; if (!service.provider.compiledCloudFormationTemplate.Outputs) { service.provider.compiledCloudFormationTemplate.Outputs = {}; } - service.provider.compiledCloudFormationTemplate.Outputs.DistributionDomainName = { - Value: domainInfo.domainName, + + // Defaults for REST and backwards compatibility + let distributionDomainNameOutputKey = "DistributionDomainName"; + let domainNameOutputKey = "DomainName"; + let hostedZoneIdOutputKey = "HostedZoneId"; + + if (domain.apiType === Globals.apiTypes.http) { + distributionDomainNameOutputKey += "Http"; + domainNameOutputKey += "Http"; + hostedZoneIdOutputKey += "Http"; + + } else if (domain.apiType === Globals.apiTypes.websocket) { + distributionDomainNameOutputKey += "Websocket"; + domainNameOutputKey += "Websocket"; + hostedZoneIdOutputKey += "Websocket"; + } + + service.provider.compiledCloudFormationTemplate.Outputs[distributionDomainNameOutputKey] = { + Value: domain.domainInfo.domainName, }; - service.provider.compiledCloudFormationTemplate.Outputs.DomainName = { - Value: this.givenDomainName, + + service.provider.compiledCloudFormationTemplate.Outputs[domainNameOutputKey] = { + Value: domain.givenDomainName, }; - if (domainInfo.hostedZoneId) { - service.provider.compiledCloudFormationTemplate.Outputs.HostedZoneId = { - Value: domainInfo.hostedZoneId, + + if (domain.domainInfo.hostedZoneId) { + service.provider.compiledCloudFormationTemplate.Outputs[hostedZoneIdOutputKey] = { + Value: domain.domainInfo.hostedZoneId, }; } } @@ -630,26 +768,23 @@ class ServerlessCustomDomain { * Logs message if SLS_DEBUG is set * @param message message to be printed */ - public logIfDebug(message: any): void { + public logIfDebug(message: any, domain?: string): void { if (process.env.SLS_DEBUG) { - this.serverless.cli.log(message, "Serverless Domain Manager"); + this.serverless.cli.log(`Error: ${domain ? domain + ": " : ""} ${message}`, "Serverless Domain Manager"); } } /** * Prints out a summary of all domain manager related info */ - private printDomainSummary(domainInfo: DomainInfo): void { - this.serverless.cli.consoleLog(chalk.yellow.underline("\nServerless Domain Manager Summary")); - if (this.serverless.service.custom.customDomain.createRoute53Record !== false) { - this.serverless.cli.consoleLog(chalk.yellow("Domain Name")); - this.serverless.cli.consoleLog(` ${this.givenDomainName}`); - } + private printDomainSummary(domain: DomainConfig): void { + this.serverless.cli.consoleLog(chalk.yellow.underline("\nServerless Domain Manager Summary")); this.serverless.cli.consoleLog(chalk.yellow("Distribution Domain Name")); - this.serverless.cli.consoleLog(` Target Domain: ${domainInfo.domainName}`); - this.serverless.cli.consoleLog(` Hosted Zone Id: ${domainInfo.hostedZoneId}`); + this.serverless.cli.consoleLog(` Domain Name: ${domain.givenDomainName}`); + this.serverless.cli.consoleLog(` Target Domain: ${domain.domainInfo.domainName}`); + this.serverless.cli.consoleLog(` Hosted Zone Id: ${domain.domainInfo.hostedZoneId}`); } } diff --git a/package-lock.json b/package-lock.json index c918042e..9b598098 100644 --- a/package-lock.json +++ b/package-lock.json @@ -671,23 +671,28 @@ } }, "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" } }, "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -1032,9 +1037,9 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, "hasha": { @@ -1121,15 +1126,15 @@ "dev": true }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", "dev": true }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, "is-fullwidth-code-point": { @@ -1145,12 +1150,12 @@ "dev": true }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "dev": true, "requires": { - "has": "^1.0.1" + "has": "^1.0.3" } }, "is-stream": { @@ -1160,12 +1165,12 @@ "dev": true }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "^1.0.1" } }, "is-typedarray": { @@ -1766,20 +1771,38 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } @@ -2370,6 +2393,26 @@ } } }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index f31dc23b..cf310f96 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -4,6 +4,8 @@ import chai = require("chai"); import spies = require("chai-spies"); import "mocha"; import DomainInfo = require("../../DomainInfo"); +import DomainConfig = require("../../DomainConfig"); +import Globals from "../../Globals"; import ServerlessCustomDomain = require("../../index"); import { ServerlessInstance, ServerlessOptions } from "../../types"; @@ -49,6 +51,7 @@ const constructPlugin = (customDomainOptions) => { sdk: { ACM: aws.ACM, APIGateway: aws.APIGateway, + ApiGatewayV2: aws.ApiGatewayV2, CloudFormation: aws.CloudFormation, Route53: aws.Route53, config: { @@ -60,6 +63,7 @@ const constructPlugin = (customDomainOptions) => { service: { custom: { customDomain: { + apiType: customDomainOptions.apiType, basePath: customDomainOptions.basePath, certificateArn: customDomainOptions.certificateArn, certificateName: customDomainOptions.certificateName, @@ -116,24 +120,68 @@ describe("Custom Domain Plugin", () => { } expect(errored).to.equal(true); }); + + it("Unsupported api type throw exception", () => { + const plugin = constructPlugin({ apiType: "notSupported" }); + + let errored = false; + try { + plugin.initializeVariables(); + } catch (err) { + errored = true; + expect(err.message).to.equal("notSupported is not supported api type, use REST, HTTP or WEBSOCKET."); + } + expect(errored).to.equal(true); + }); + + it("Unsupported HTTP EDGE endpoint configuration", () => { + const plugin = constructPlugin({ apiType: "http" }); + + let errored = false; + try { + plugin.initializeVariables(); + } catch (err) { + errored = true; + expect(err.message).to.equal("Error: 'edge' endpointType is not compatible with HTTP APIs"); + } + expect(errored).to.equal(true); + }); + + it("Unsupported WS EDGE endpoint configuration", () => { + const plugin = constructPlugin({ apiType: "websocket" }); + + let errored = false; + try { + plugin.initializeVariables(); + } catch (err) { + errored = true; + expect(err.message).to.equal("Error: 'edge' endpointType is not compatible with WebSocket APIs"); + } + expect(errored).to.equal(true); + }); + }); describe("Set Domain Name and Base Path", () => { - it("Creates basepath mapping", async () => { + it("Creates basepath mapping for edge REST api", async () => { AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { callback(null, params); }); const plugin = constructPlugin({ basePath: "test_basepath", domainName: "test_domain", + endpointType: "edge", }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - plugin.basePath = plugin.serverless.service.custom.customDomain.basePath; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + dc.apiId = "test_rest_api_id"; + const spy = chai.spy.on(plugin.apigateway, "createBasePathMapping"); - await plugin.createBasePathMapping("test_rest_api_id"); + await plugin.createBasePathMapping(dc); + expect(spy).to.have.been.called.with({ basePath: "test_basepath", domainName: "test_domain", @@ -142,7 +190,35 @@ describe("Custom Domain Plugin", () => { }); }); - it("Updates basepath mapping", async () => { + it("Creates basepath mapping for regional HTTP/Websocket api", async () => { + AWS.mock("ApiGatewayV2", "createApiMapping", (params, callback) => { + callback(null, params); + }); + const plugin = constructPlugin({ + apiType: "http", + basePath: "test_basepath", + domainName: "test_domain", + endpointType: "regional", + }); + plugin.initializeVariables(); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.apiId = "test_rest_api_id"; + + const spy = chai.spy.on(plugin.apigatewayV2, "createApiMapping"); + + await plugin.createBasePathMapping(dc); + expect(spy).to.have.been.called.with({ + ApiId: "test_rest_api_id", + ApiMappingKey: "test_basepath", + DomainName: "test_domain", + Stage: "$default", + }); + }); + + it("Updates basepath mapping for a edge REST api", async () => { AWS.mock("APIGateway", "updateBasePathMapping", (params, callback) => { callback(null, params); }); @@ -151,12 +227,16 @@ describe("Custom Domain Plugin", () => { domainName: "test_domain", }); plugin.initializeVariables(); + plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - plugin.basePath = plugin.serverless.service.custom.customDomain.basePath; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.apiMapping = {ApiMappingKey: "old_basepath"}; + const spy = chai.spy.on(plugin.apigateway, "updateBasePathMapping"); - await plugin.updateBasePathMapping("old_basepath"); + await plugin.updateBasePathMapping(dc); expect(spy).to.have.been.called.with({ basePath: "old_basepath", domainName: "test_domain", @@ -170,15 +250,93 @@ describe("Custom Domain Plugin", () => { }); }); + it("Updates basepath mapping for regional HTTP/WS api", async () => { + AWS.mock("ApiGatewayV2", "updateApiMapping", (params, callback) => { + callback(null, params); + }); + const plugin = constructPlugin({ + apiType: "http", + basePath: "test_basepath", + domainName: "test_domain", + endpointType: "regional", + }); + plugin.initializeVariables(); + + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + dc.apiId = "test_api_id", + dc.apiMapping = {ApiMappingId: "test_mapping_id"}; + + const spy = chai.spy.on(plugin.apigatewayV2, "updateApiMapping"); + + await plugin.updateBasePathMapping(dc); + expect(spy).to.have.been.called.with({ + ApiId: "test_api_id", + ApiMappingId: "test_mapping_id", + ApiMappingKey: dc.basePath, + DomainName: dc.givenDomainName, + Stage: "$default", + }); + }); + + it("Remove basepath mappings", async () => { + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "ApiGatewayRestApi", + PhysicalResourceId: "test_rest_api_id", + }, + }); + }); + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { + callback(null, { + Items: [ + { ApiId: "test_rest_api_id", MappingKey: "test", ApiMappingId: "test_mapping_id", Stage: "test" }, + ], + }); + }); + AWS.mock("ApiGatewayV2", "deleteApiMapping", (params, callback) => { + callback(null, params); + }); + + const plugin = constructPlugin({ + basePath: "test_basepath", + domainName: "test_domain", + restApiId: "test_rest_api_id", + }); + plugin.initializeVariables(); + + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + plugin.cloudformation = new aws.CloudFormation(); + + plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; + + const spy = chai.spy.on(plugin.apigatewayV2, "deleteApiMapping"); + + await plugin.removeBasePathMappings(); + expect(spy).to.have.been.called.with({ + ApiMappingId: "test_mapping_id", + DomainName: "test_domain", + }); + }); + it("Add Distribution Domain Name, Domain Name, and HostedZoneId to stack output", () => { const plugin = constructPlugin({ domainName: "test_domain", }); - plugin.addOutputs(new DomainInfo({ + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.domainInfo = new DomainInfo({ distributionDomainName: "fake_dist_name", distributionHostedZoneId: "fake_zone_id", domainName: "fake_domain", - })); + }); + + plugin.addOutputs(dc); + const cfTemplat = plugin.serverless.service.provider.compiledCloudFormationTemplate.Outputs; expect(cfTemplat).to.not.equal(undefined); }); @@ -194,10 +352,14 @@ describe("Custom Domain Plugin", () => { }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.apiId = "test_rest_api_id"; + const spy = chai.spy.on(plugin.apigateway, "createBasePathMapping"); - await plugin.createBasePathMapping("test_rest_api_id"); + await plugin.createBasePathMapping(dc); expect(spy).to.have.been.called.with({ basePath: "(none)", domainName: "test_domain", @@ -217,10 +379,14 @@ describe("Custom Domain Plugin", () => { }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.apiId = "test_rest_api_id"; + const spy = chai.spy.on(plugin.apigateway, "createBasePathMapping"); - await plugin.createBasePathMapping("test_rest_api_id"); + await plugin.createBasePathMapping(dc); expect(spy).to.have.been.called.with({ basePath: "(none)", domainName: "test_domain", @@ -239,10 +405,14 @@ describe("Custom Domain Plugin", () => { }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.apiId = "test_rest_api_id"; + const spy = chai.spy.on(plugin.apigateway, "createBasePathMapping"); - await plugin.createBasePathMapping("test_rest_api_id"); + await plugin.createBasePathMapping(dc); expect(spy).to.have.been.called.with({ basePath: "(none)", domainName: "test_domain", @@ -262,10 +432,14 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); plugin.cloudformation = new aws.CloudFormation(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.apiId = "test_rest_api_id"; + const spy = chai.spy.on(plugin.apigateway, "createBasePathMapping"); - await plugin.createBasePathMapping("test_rest_api_id"); + await plugin.createBasePathMapping(dc); expect(spy).to.have.been.called.with({ basePath: "(none)", domainName: "test_domain", @@ -291,7 +465,9 @@ describe("Custom Domain Plugin", () => { const plugin = constructPlugin(options); plugin.acm = new aws.ACM(); - const result = await plugin.getCertArn(); + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const result = await plugin.getCertArn(dc); expect(result).to.equal("test_given_arn"); }); @@ -302,7 +478,9 @@ describe("Custom Domain Plugin", () => { const plugin = constructPlugin({ certificateName: "cert_name" }); plugin.acm = new aws.ACM(); - const result = await plugin.getCertArn(); + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const result = await plugin.getCertArn(dc); expect(result).to.equal("test_given_cert_name"); }); @@ -313,13 +491,36 @@ describe("Custom Domain Plugin", () => { }); const plugin = constructPlugin({ domainName: "test_domain"}); + plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - const result = await plugin.createCustomDomain("fake_cert"); + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.certificateArn = "fake_cert"; + + await plugin.createCustomDomain(dc); + + expect(dc.domainInfo.domainName).to.equal("foo"); + expect(dc.domainInfo.securityPolicy).to.equal("TLS_1_2"); + }); + + it("Create an HTTP domain name", async () => { + AWS.mock("ApiGatewayV2", "createDomainName", (params, callback) => { + callback(null, { DomainName: "foo", DomainNameConfigurations: [{SecurityPolicy: "TLS_1_2"}]}); + }); + + const plugin = constructPlugin({ domainName: "test_domain", apiType: "http", endpointType: "regional"}); + plugin.initializeVariables(); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.certificateArn = "fake_cert"; - expect(result.domainName).to.equal("foo"); - expect(result.securityPolicy).to.equal("TLS_1_2"); + await plugin.createCustomDomain(dc); + + expect(dc.domainInfo.domainName).to.equal("foo"); + expect(dc.domainInfo.securityPolicy).to.equal("TLS_1_2"); }); it("Create a domain name with specific TLS version", async () => { @@ -328,13 +529,17 @@ describe("Custom Domain Plugin", () => { }); const plugin = constructPlugin({ domainName: "test_domain", securityPolicy: "tls_1_2"}); + plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - const result = await plugin.createCustomDomain("fake_cert"); + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); - expect(result.domainName).to.equal("foo"); - expect(result.securityPolicy).to.equal("TLS_1_2"); + dc.certificateArn = "fake_cert"; + + await plugin.createCustomDomain(dc); + + expect(dc.domainInfo.domainName).to.equal("foo"); + expect(dc.domainInfo.securityPolicy).to.equal("TLS_1_2"); }); it("Create a new A Alias Record", async () => { @@ -346,19 +551,21 @@ describe("Custom Domain Plugin", () => { callback(null, params); }); - const plugin = constructPlugin({ basePath: "test_basepath" }); + const plugin = constructPlugin({ basePath: "test_basepath", domainName: "test_domain" }); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "test_domain"; - const spy = chai.spy.on(plugin.route53, "changeResourceRecordSets"); - const domain = new DomainInfo( + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + dc.domainInfo = new DomainInfo( { distributionDomainName: "test_distribution_name", distributionHostedZoneId: "test_id", }, ); - await plugin.changeResourceRecordSet("UPSERT", domain); + const spy = chai.spy.on(plugin.route53, "changeResourceRecordSets"); + + await plugin.changeResourceRecordSet("UPSERT", dc); const expectedParams = { ChangeBatch: { @@ -400,7 +607,10 @@ describe("Custom Domain Plugin", () => { createRoute53Record: false, domainName: "test_domain", }); - const result = await plugin.changeResourceRecordSet("UPSERT", new DomainInfo({})); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const result = await plugin.changeResourceRecordSet("UPSERT", dc); expect(result).to.equal(undefined); }); @@ -411,11 +621,11 @@ describe("Custom Domain Plugin", () => { }); describe("Gets existing basepath mappings correctly", () => { - it("Returns undefined if no basepaths map to current restApiId", async () => { - AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { + it("Returns undefined if no basepaths map to current api", async () => { + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { callback(null, { - items: [ - { basePath: "(none)", restApiId: "test_rest_api_id_one", stage: "test" }, + Items: [ + { ApiId: "someother_api_id", MappingKey: "test", ApiMappingId: "test_rest_api_id_one", Stage: "test" }, ], }); }); @@ -423,33 +633,42 @@ describe("Custom Domain Plugin", () => { const plugin = constructPlugin({ domainName: "test_domain", }); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - plugin.basePath = plugin.serverless.service.custom.customDomain.basePath; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + dc.apiMapping = {ApiMappingId: "api_id"}; + plugin.initializeVariables(); - const result = await plugin.getBasePathMapping("test_rest_api_id_two"); + const result = await plugin.getBasePathMapping(dc); expect(result).to.equal(undefined); }); - it("Returns current api", async () => { - AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { + it("Returns current api mapping", async () => { + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { callback(null, { - items: [ - { basePath: "api", restApiId: "test_rest_api_id", stage: "test" }, + Items: [ + { ApiId: "test_rest_api_id", ApiMappingKey: "api", ApiMappingId: "fake_id", Stage: "test" }, ], }); }); const plugin = constructPlugin({ + apiType: Globals.apiTypes.rest, basePath: "api", domainName: "test_domain", }); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - plugin.basePath = plugin.serverless.service.custom.customDomain.basePath; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + dc.apiId = "test_rest_api_id"; + plugin.initializeVariables(); - const result = await plugin.getBasePathMapping("test_rest_api_id"); - expect(result).to.equal("api"); + const result = await plugin.getBasePathMapping(dc); + expect(result).to.eql({ + ApiId: "test_rest_api_id", + ApiMappingId: "fake_id", + ApiMappingKey: "api", + Stage: "test" }); }); afterEach(() => { @@ -458,8 +677,8 @@ describe("Custom Domain Plugin", () => { }); }); - describe("Gets Rest API correctly", () => { - it("Fetches restApiId correctly when no ApiGateway specified", async () => { + describe("Gets Rest API id correctly", () => { + it("Gets REST API id correctly when no ApiGateway specified", async () => { AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { callback(null, { StackResourceDetail: @@ -473,10 +692,82 @@ describe("Custom Domain Plugin", () => { basePath: "test_basepath", domainName: "test_domain", }); + plugin.initializeVariables(); plugin.cloudformation = new aws.CloudFormation(); - const result = await plugin.getRestApiId(); + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const spy = chai.spy.on(plugin.cloudformation, "describeStackResource"); + + const result = await plugin.getApiId(dc); + expect(result).to.equal("test_rest_api_id"); + expect(spy).to.have.been.called.with({ + LogicalResourceId: "ApiGatewayRestApi", + StackName: "custom-stage-name", + }); + }); + + it("Gets HTTP API id correctly when no ApiGateway specified", async () => { + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "HttpApi", + PhysicalResourceId: "test_http_api_id", + }, + }); + }); + const plugin = constructPlugin({ + apiType: "http", + basePath: "test_basepath", + domainName: "test_domain", + endpointType: "regional", + }); + plugin.initializeVariables(); + plugin.cloudformation = new aws.CloudFormation(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const spy = chai.spy.on(plugin.cloudformation, "describeStackResource"); + + const result = await plugin.getApiId(dc); + expect(result).to.equal("test_http_api_id"); + expect(spy).to.have.been.called.with({ + LogicalResourceId: "HttpApi", + StackName: "custom-stage-name", + }); + }); + + it("Gets Websocket API id correctly when no ApiGateway specified", async () => { + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "WebsocketsApi", + PhysicalResourceId: "test_ws_api_id", + }, + }); + }); + const plugin = constructPlugin({ + apiType: "websocket", + basePath: "test_basepath", + domainName: "test_domain", + endpointType: "regional", + }); + plugin.initializeVariables(); + plugin.cloudformation = new aws.CloudFormation(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const spy = chai.spy.on(plugin.cloudformation, "describeStackResource"); + + const result = await plugin.getApiId(dc); + expect(result).to.equal("test_ws_api_id"); + expect(spy).to.have.been.called.with({ + LogicalResourceId: "WebsocketsApi", + StackName: "custom-stage-name", + }); }); it("serverless.yml defines explicitly the apiGateway", async () => { @@ -497,11 +788,14 @@ describe("Custom Domain Plugin", () => { plugin.cloudformation = new aws.CloudFormation(); plugin.serverless.service.provider.apiGateway.restApiId = "custom_test_rest_api_id"; - const result = await plugin.getRestApiId(); + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const result = await plugin.getApiId(dc); expect(result).to.equal("custom_test_rest_api_id"); }); afterEach(() => { + AWS.restore(); consoleOutput = []; }); }); @@ -517,11 +811,12 @@ describe("Custom Domain Plugin", () => { domainName: "test_domain", }); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - const result = await plugin.getDomainInfo(); + await plugin.getDomainInfo(); - expect(result.domainName).to.equal("test_domain"); + plugin.domains.forEach((domain) => { + expect(domain.domainInfo.domainName).to.equal("test_domain"); + }); }); it("Delete A Alias Record", async () => { @@ -538,15 +833,17 @@ describe("Custom Domain Plugin", () => { domainName: "test_domain", }); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + const spy = chai.spy.on(plugin.route53, "changeResourceRecordSets"); - const domain = new DomainInfo({ + dc.domainInfo = new DomainInfo({ distributionDomainName: "test_distribution_name", distributionHostedZoneId: "test_id", }); - await plugin.changeResourceRecordSet("DELETE", domain); + await plugin.changeResourceRecordSet("DELETE", dc); const expectedParams = { ChangeBatch: { Changes: [ @@ -584,7 +881,7 @@ describe("Custom Domain Plugin", () => { }); it("Delete the domain name", async () => { - AWS.mock("APIGateway", "deleteDomainName", (params, callback) => { + AWS.mock("ApiGatewayV2", "deleteDomainName", (params, callback) => { callback(null, {}); }); @@ -592,13 +889,15 @@ describe("Custom Domain Plugin", () => { basePath: "test_basepath", domainName: "test_domain", }); - plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - const spy = chai.spy.on(plugin.apigateway, "deleteDomainName"); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + + const spy = chai.spy.on(plugin.apigatewayV2, "deleteDomainName"); - await plugin.deleteCustomDomain(); + await plugin.deleteCustomDomain(dc); expect(spy).to.be.called.with({ - domainName: "test_domain", + DomainName: "test_domain", }); }); @@ -610,11 +909,12 @@ describe("Custom Domain Plugin", () => { describe("Hook Methods", () => { it("setupBasePathMapping", async () => { - AWS.mock("APIGateway", "getDomainName", (params, callback) => { - callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, {DomainName: "test_domain", + DomainNameConfigurations: [{ApiGatewayDomainName: "fake_dist_name"}]}); }); - AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { - callback(null, { items: [] }); + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { + callback(null, { Items: [] }); }); AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { callback(null, params); @@ -631,20 +931,20 @@ describe("Custom Domain Plugin", () => { const plugin = constructPlugin({ domainName: "test_domain"}); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); plugin.cloudformation = new aws.CloudFormation(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; const spy = chai.spy.on(plugin, "createBasePathMapping"); - await plugin.setupBasePathMapping(); + await plugin.setupBasePathMappings(); expect(spy).to.be.called(); }); it("deleteDomain", async () => { - AWS.mock("APIGateway", "getDomainName", (params, callback) => { - callback(null, { distributionDomainName: "test_distribution", regionalHostedZoneId: "test_id" }); + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, {DomainName: "test_domain", DomainNameConfigurations: [{HostedZoneId: "test_id"}]}); }); - AWS.mock("APIGateway", "deleteDomainName", (params, callback) => { + AWS.mock("ApiGatewayV2", "deleteDomainName", (params, callback) => { callback(null, {}); }); AWS.mock("Route53", "listHostedZones", (params, callback) => { @@ -657,14 +957,15 @@ describe("Custom Domain Plugin", () => { const plugin = constructPlugin({ domainName: "test_domain"}); plugin.apigateway = new aws.APIGateway(); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - await plugin.deleteDomain(); - expect(consoleOutput[0]).to.equal(`Custom domain ${plugin.givenDomainName} was deleted.`); + plugin.initializeVariables(); + + await plugin.deleteDomains(); + expect(consoleOutput[0]).to.equal(`Custom domain ${plugin.domains[0].givenDomainName} was deleted.`); }); it("createDomain if one does not exist before", async () => { AWS.mock("ACM", "listCertificates", certTestData); - AWS.mock("APIGateway", "getDomainName", (params, callback) => { + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { callback({ code: "NotFoundException" }, {}); }); AWS.mock("APIGateway", "createDomainName", (params, callback) => { @@ -681,16 +982,18 @@ describe("Custom Domain Plugin", () => { plugin.apigateway = new aws.APIGateway(); plugin.route53 = new aws.Route53(); plugin.acm = new aws.ACM(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - await plugin.createDomain(); - expect(consoleOutput[0]).to.equal(`Custom domain ${plugin.givenDomainName} was created. - New domains may take up to 40 minutes to be initialized.`); + + plugin.initializeVariables(); + await plugin.createDomains(); + + expect(consoleOutput[0]).to.equal(`Custom domain ${plugin.domains[0].givenDomainName} was created. + New domains may take up to 40 minutes to be initialized.`); }); it("Does not create domain if one existed before", async () => { AWS.mock("ACM", "listCertificates", certTestData); - AWS.mock("APIGateway", "getDomainName", (params, callback) => { - callback(null, { distributionDomainName: "foo", regionalHostedZoneId: "test_id" }); + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, {DomainName: "test_domain", DomainNameConfigurations: [{HostedZoneId: "test_id"}]}); }); AWS.mock("APIGateway", "createDomainName", (params, callback) => { callback(null, { distributionDomainName: "foo", regionalHostedZoneId: "test_id" }); @@ -706,9 +1009,9 @@ describe("Custom Domain Plugin", () => { plugin.apigateway = new aws.APIGateway(); plugin.route53 = new aws.Route53(); plugin.acm = new aws.ACM(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; - await plugin.createDomain(); - expect(consoleOutput[0]).to.equal(`Custom domain ${plugin.givenDomainName} already exists.`); + plugin.initializeVariables(); + await plugin.createDomains(); + expect(consoleOutput[0]).to.equal(`Custom domain test_domain already exists.`); }); afterEach(() => { @@ -730,11 +1033,10 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "ccc.bbb.aaa.com"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "ccc.bbb.aaa.com"; - - const result = await plugin.getRoute53HostedZoneId(); + plugin.initializeVariables(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_2"); }); @@ -750,11 +1052,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "test.ccc.bbb.aaa.com"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "test.ccc.bbb.aaa.com"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_1"); }); @@ -770,11 +1072,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "test.ccc.bbb.aaa.com"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "test.ccc.bbb.aaa.com"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_2"); }); @@ -789,11 +1091,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "bar.foo.bbb.fr"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "bar.foo.bbb.fr"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_1"); }); @@ -807,11 +1109,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "test.a.aaa.com"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "test.a.aaa.com"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_0"); }); @@ -827,11 +1129,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "bar.foo.bbb.fr"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "bar.foo.bbb.fr"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_3"); }); @@ -847,11 +1149,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "bar.foo.bbb.fr"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "bar.foo.bbb.fr"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_3"); }); @@ -866,11 +1168,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "bar.foo.bbb.fr"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "bar.foo.bbb.fr"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_3"); }); @@ -883,12 +1185,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "aaa.com", hostedZonePrivate: true}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "aaa.com"; - plugin.hostedZonePrivate = true; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_0"); }); @@ -901,11 +1202,11 @@ describe("Custom Domain Plugin", () => { }); }); - const plugin = constructPlugin({}); + const plugin = constructPlugin({domainName: "aaa.com"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = "aaa.com"; + plugin.initializeVariables(); - const result = await plugin.getRoute53HostedZoneId(); + const result = await plugin.getRoute53HostedZoneId(plugin.domains[0]); expect(result).to.equal("test_id_0"); }); @@ -925,8 +1226,9 @@ describe("Custom Domain Plugin", () => { }; const plugin = constructPlugin(options); plugin.acm = new aws.ACM(); + plugin.initializeVariables(); - return plugin.getCertArn().then(() => { + return plugin.getCertArn(plugin.domains[0]).then(() => { throw new Error("Test has failed. getCertArn did not catch errors."); }).catch((err) => { const expectedErrorMessage = "Error: Could not find the certificate does_not_exist."; @@ -941,9 +1243,9 @@ describe("Custom Domain Plugin", () => { const plugin = constructPlugin({ domainName: "test_domain"}); plugin.route53 = new aws.Route53(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + plugin.initializeVariables(); - return plugin.getRoute53HostedZoneId().then(() => { + return plugin.getRoute53HostedZoneId(plugin.domains[0]).then(() => { throw new Error("Test has failed, getHostedZone did not catch errors."); }).catch((err) => { const expectedErrorMessage = "Error: Could not find hosted zone \"test_domain\""; @@ -957,9 +1259,9 @@ describe("Custom Domain Plugin", () => { }); const plugin = constructPlugin({ domainName: "test_domain"}); plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + plugin.initializeVariables(); - return plugin.domainSummary().then(() => { + return plugin.domainSummaries().then(() => { // check if distribution domain name is printed }).catch((err) => { const expectedErrorMessage = `Error: Unable to fetch information about test_domain`; @@ -969,17 +1271,17 @@ describe("Custom Domain Plugin", () => { it("Should log if SLS_DEBUG is set", async () => { const plugin = constructPlugin({ domainName: "test_domain" }); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + plugin.initializeVariables(); // set sls debug to true process.env.SLS_DEBUG = "True"; plugin.logIfDebug("test message"); - expect(consoleOutput).to.contain("test message"); + expect(consoleOutput[0]).to.contain("test message"); }); it("Should not log if SLS_DEBUG is not set", async () => { const plugin = constructPlugin({ domainName: "test_domain" }); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + plugin.initializeVariables(); plugin.logIfDebug("test message"); expect(consoleOutput).to.not.contain("test message"); @@ -994,19 +1296,18 @@ describe("Custom Domain Plugin", () => { describe("Summary Printing", () => { it("Prints Summary", async () => { - AWS.mock("APIGateway", "getDomainName", (params, callback) => { + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { callback(null, { domainName: params, distributionDomainName: "test_distributed_domain_name" }); }); const plugin = constructPlugin({domainName: "test_domain"}); - plugin.apigateway = new aws.APIGateway(); - plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + plugin.initializeVariables(); - await plugin.domainSummary(); + await plugin.domainSummaries(); expect(consoleOutput[0]).to.contain("Serverless Domain Manager Summary"); - expect(consoleOutput[1]).to.contain("Domain Name"); + expect(consoleOutput[1]).to.contain("Distribution Domain Name"); expect(consoleOutput[2]).to.contain("test_domain"); - expect(consoleOutput[3]).to.contain("Distribution Domain Name"); - expect(consoleOutput[4]).to.contain("test_distributed_domain_name"); + expect(consoleOutput[3]).to.contain("test_distributed_domain_name"); }); afterEach(() => { @@ -1024,7 +1325,10 @@ describe("Custom Domain Plugin", () => { const returnedCreds = plugin.apigateway.config.credentials; expect(returnedCreds.accessKeyId).to.equal(testCreds.accessKeyId); expect(returnedCreds.sessionToken).to.equal(testCreds.sessionToken); - expect(plugin.enabled).to.equal(true); + expect(plugin.domains).length.to.be.greaterThan(0); + for (const domain of plugin.domains) { + expect(domain.enabled).to.equal(true); + } }); it("Should enable the plugin when passing a true parameter with type boolean", () => { @@ -1035,7 +1339,10 @@ describe("Custom Domain Plugin", () => { const returnedCreds = plugin.apigateway.config.credentials; expect(returnedCreds.accessKeyId).to.equal(testCreds.accessKeyId); expect(returnedCreds.sessionToken).to.equal(testCreds.sessionToken); - expect(plugin.enabled).to.equal(true); + expect(plugin.domains).length.to.be.greaterThan(0); + for (const domain of plugin.domains) { + expect(domain.enabled).to.equal(true); + } }); it("Should enable the plugin when passing a true parameter with type string", () => { @@ -1046,7 +1353,10 @@ describe("Custom Domain Plugin", () => { const returnedCreds = plugin.apigateway.config.credentials; expect(returnedCreds.accessKeyId).to.equal(testCreds.accessKeyId); expect(returnedCreds.sessionToken).to.equal(testCreds.sessionToken); - expect(plugin.enabled).to.equal(true); + expect(plugin.domains).length.to.be.greaterThan(0); + for (const domain of plugin.domains) { + expect(domain.enabled).to.equal(true); + } }); it("Should disable the plugin when passing a false parameter with type boolean", () => { @@ -1054,7 +1364,7 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); - expect(plugin.enabled).to.equal(false); + expect(plugin.domains.length).to.equal(0); }); it("Should disable the plugin when passing a false parameter with type string", () => { @@ -1062,56 +1372,50 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); - expect(plugin.enabled).to.equal(false); + expect(plugin.domains.length).to.equal(0); }); it("createDomain should do nothing when domain manager is disabled", async () => { const plugin = constructPlugin({ enabled: false }); - const result = await plugin.hookWrapper(plugin.createDomain); + await plugin.hookWrapper(plugin.createDomains); - expect(plugin.enabled).to.equal(false); - expect(result).to.equal(undefined); + expect(plugin.domains.length).to.equal(0); }); it("deleteDomain should do nothing when domain manager is disabled", async () => { const plugin = constructPlugin({ enabled: false }); - const result = await plugin.hookWrapper(plugin.deleteDomain); + await plugin.hookWrapper(plugin.deleteDomains); - expect(plugin.enabled).to.equal(false); - expect(result).to.equal(undefined); + expect(plugin.domains.length).to.equal(0); }); it("setUpBasePathMapping should do nothing when domain manager is disabled", async () => { const plugin = constructPlugin({ enabled: false }); - const result = await plugin.hookWrapper(plugin.setupBasePathMapping); + await plugin.hookWrapper(plugin.setupBasePathMappings); - expect(plugin.enabled).to.equal(false); - expect(result).to.equal(undefined); + expect(plugin.domains.length).to.equal(0); }); it("removeBasePathMapping should do nothing when domain manager is disabled", async () => { const plugin = constructPlugin({ enabled: false }); - const result = await plugin.hookWrapper(plugin.removeBasePathMapping); + await plugin.hookWrapper(plugin.removeBasePathMappings); - expect(plugin.enabled).to.equal(false); - expect(result).to.equal(undefined); + expect(plugin.domains.length).to.equal(0); }); it("domainSummary should do nothing when domain manager is disabled", async () => { const plugin = constructPlugin({ enabled: false }); - const result = await plugin.hookWrapper(plugin.domainSummary); + await plugin.hookWrapper(plugin.domainSummaries); - expect(plugin.enabled).to.equal(false); - expect(result).to.equal(undefined); + expect(plugin.domains.length).to.equal(0); }); it("Should throw an Error when passing a parameter that is not boolean", () => { - const stringWithValueYes = "yes"; const plugin = constructPlugin({ enabled: 0 }); let errored = false; diff --git a/types.ts b/types.ts index 5d612493..0e8c089c 100644 --- a/types.ts +++ b/types.ts @@ -20,6 +20,7 @@ export interface ServerlessInstance { // tslint:disable-line certificateArn: string | undefined, createRoute53Record: boolean | undefined, endpointType: string | undefined, + apiType: string | undefined, hostedZoneId: string | undefined, hostedZonePrivate: boolean | undefined, enabled: boolean | string | undefined, @@ -31,6 +32,7 @@ export interface ServerlessInstance { // tslint:disable-line aws: { sdk: { APIGateway: any, + ApiGatewayV2: any, Route53: any, CloudFormation: any, ACM: any, From 7f6ef9350e36104818980cbcfd374f150efc026f Mon Sep 17 00:00:00 2001 From: Jason Venable Date: Fri, 1 May 2020 23:31:41 -0400 Subject: [PATCH 19/69] Fix typos and clean up comments --- README.md | 4 ++-- index.ts | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a3b12207..c2680eaf 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ plugins: - serverless-domain-manager ``` -Add the plugin configuration (example for `serverless.foo.com/api`). For a single domain and API type the following sturcture can be used. +Add the plugin configuration (example for `serverless.foo.com/api`). For a single domain and API type the following structure can be used. ```yaml custom: @@ -118,7 +118,7 @@ custom: | hostedZonePrivate | | If hostedZonePrivate is set to `true` then only private hosted zones will be used for route 53 records. If it is set to `false` then only public hosted zones will be used for route53 records. Setting this parameter is specially useful if you have multiple hosted zones with the same domain name (e.g. a public and a private one) | | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| -allowPathMatching | false | When updating an existing api mapping this will match on the basePath instead of the API ID to find existing mappings for an udpate. This should ony be used when changing API types. For example, migrating a REST API to an HTTP API. See Changing API Types for moe information. | +allowPathMatching | false | When updating an existing api mapping this will match on the basePath instead of the API ID to find existing mappings for an upsate. This should only be used when changing API types. For example, migrating a REST API to an HTTP API. See Changing API Types for more information. | ## Running diff --git a/index.ts b/index.ts index f3b034ef..96a48ee6 100644 --- a/index.ts +++ b/index.ts @@ -119,7 +119,7 @@ class ServerlessCustomDomain { domain.domainInfo = undefined; this.serverless.cli.log(`Custom domain ${domain.givenDomainName} was deleted.`); } else { - this.serverless.cli.log(`Custom domain ${domain.givenDomainName} does not exists.`); + this.serverless.cli.log(`Custom domain ${domain.givenDomainName} does not exist.`); } } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -158,7 +158,6 @@ class ServerlessCustomDomain { } await this.getDomainInfo(); - // this.addOutputs(domain); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -181,7 +180,7 @@ class ServerlessCustomDomain { try { domain.apiId = await this.getApiId(domain); - // Unable to find the correspond API, manuall clean up will be required + // Unable to find the corresponding API, manual clean up will be required if (!domain.apiId) { this.serverless.cli.log(`Unable to find corresponding API for ${domain.givenDomainName}, API Mappings may need to be manually removed.`, "Serverless Domain Manager"); @@ -403,7 +402,7 @@ class ServerlessCustomDomain { // Make API call to create domain try { - // If creating REST api use v1 of api gateway, else use v2 for HTTP and Websocket + // Creating EDGE domain so use APIGateway (v1) service createdDomain = await this.apigateway.createDomainName(params).promise(); domain.domainInfo = new DomainInfo(createdDomain); } catch (err) { @@ -423,7 +422,7 @@ class ServerlessCustomDomain { // Make API call to create domain try { - // If creating REST api use v1 of api gateway, else use v2 for HTTP and Websocket + // Creating Regional domain so use ApiGatewayV2 createdDomain = await this.apigatewayV2.createDomainName(params).promise(); domain.domainInfo = new DomainInfo(createdDomain); } catch (err) { From df0d80b171f2455ff56284037097720bdfd5c18a Mon Sep 17 00:00:00 2001 From: Jason Venable Date: Fri, 1 May 2020 23:40:37 -0400 Subject: [PATCH 20/69] Make evaluateEnabled() in DomainConfig private --- DomainConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DomainConfig.ts b/DomainConfig.ts index 5a67ed01..1b707a2e 100644 --- a/DomainConfig.ts +++ b/DomainConfig.ts @@ -81,7 +81,7 @@ class DomainConfig { * If the property's value is provided, this should be boolean, otherwise an exception is thrown. * If no customDomain object exists, an exception is thrown. */ - public evaluateEnabled(enabled: any): boolean { + private evaluateEnabled(enabled: any): boolean { // const enabled = this.serverless.service.custom.customDomain.enabled; if (enabled === undefined) { return true; From 5a87e435b2e28be82ba2d637941bcb440871ea73 Mon Sep 17 00:00:00 2001 From: Jason Venable Date: Mon, 4 May 2020 23:08:14 -0400 Subject: [PATCH 21/69] Fix more typos --- index.ts | 10 +++++----- test/unit-tests/index.test.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/index.ts b/index.ts index 96a48ee6..535eaf84 100644 --- a/index.ts +++ b/index.ts @@ -98,7 +98,7 @@ class ServerlessCustomDomain { } } catch (err) { this.logIfDebug(err, domain.givenDomainName); - throw new Error(`Error: Unable to craete domain ${domain.givenDomainName}`); + throw new Error(`Error: Unable to create domain ${domain.givenDomainName}`); } })); } @@ -238,7 +238,7 @@ class ServerlessCustomDomain { this.route53 = new this.serverless.providers.aws.sdk.Route53(credentials); this.cloudformation = new this.serverless.providers.aws.sdk.CloudFormation(credentials); - // Loop over the domain configurations and popluates the domains array with DomainConfigs + // Loop over the domain configurations and populate the domains array with DomainConfigs this.domains = []; // If the key of the item in config is an api type it is using per api type domain structure @@ -248,7 +248,7 @@ class ServerlessCustomDomain { this.serverless.service.custom.customDomain[configApiType].apiType = configApiType; this.domains.push(new DomainConfig(this.serverless.service.custom.customDomain[configApiType])); } else { - throw Error(`Error: Invalud API Type, ${configApiType}`); + throw Error(`Error: Invalid API Type, ${configApiType}`); } } } else { // Default to single domain config @@ -266,7 +266,7 @@ class ServerlessCustomDomain { this.acm = new this.serverless.providers.aws.sdk.ACM(acmCredentials); } - // Validate the domain configuraitons + // Validate the domain configurations this.validateDomainConfigs(); } @@ -309,7 +309,7 @@ class ServerlessCustomDomain { return domain.certificateArn; } - let certificateArn; // The arn of the choosen certificate + let certificateArn; // The arn of the selected certificate let certificateName = domain.certificateName; // The certificate name diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index cf310f96..803a2e61 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -337,8 +337,8 @@ describe("Custom Domain Plugin", () => { plugin.addOutputs(dc); - const cfTemplat = plugin.serverless.service.provider.compiledCloudFormationTemplate.Outputs; - expect(cfTemplat).to.not.equal(undefined); + const cfTemplate = plugin.serverless.service.provider.compiledCloudFormationTemplate.Outputs; + expect(cfTemplate).to.not.equal(undefined); }); it("(none) is added if basepath is an empty string", async () => { From 3eca83b8b56cf54d9ac2b1de58a844a9377436ca Mon Sep 17 00:00:00 2001 From: Jason Venable Date: Mon, 4 May 2020 23:45:45 -0400 Subject: [PATCH 22/69] =?UTF-8?q?Don=E2=80=99t=20throw=20hard=20error=20if?= =?UTF-8?q?=20base=20path=20mappings=20can=E2=80=99t=20be=20removed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 535eaf84..06e05002 100644 --- a/index.ts +++ b/index.ts @@ -194,7 +194,8 @@ class ServerlessCustomDomain { API Mappings may need to be manually removed.`, "Serverless Domain Manager"); } else { this.logIfDebug(err, domain.givenDomainName); - throw new Error(`Error: Unable to remove base bath mappings for domain ${domain.givenDomainName}`); + this.serverless.cli.log(`Error: Unable to remove base bath mappings + for domain ${domain.givenDomainName}`); } } })); From 56f128c01d43b060e4e5aae32444846a77bda061 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 5 May 2020 12:53:21 -0500 Subject: [PATCH 23/69] change config to autoDomain --- README.md | 4 ++-- index.ts | 8 ++++---- test/unit-tests/index.test.ts | 28 ++++++++++++++-------------- types.ts | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 4e2af041..c5f1fa64 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 - createDomainName: false + autoDomain: false ``` | Parameter Name | Default Value | Description | @@ -86,7 +86,7 @@ custom: | hostedZonePrivate | | If hostedZonePrivate is set to `true` then only private hosted zones will be used for route 53 records. If it is set to `false` then only public hosted zones will be used for route53 records. Setting this parameter is specially useful if you have multiple hosted zones with the same domain name (e.g. a public and a private one) | | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| -| createDomainName | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | +| autoDomain | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | ## Running diff --git a/index.ts b/index.ts index 64dba5ec..d025cef8 100644 --- a/index.ts +++ b/index.ts @@ -145,8 +145,8 @@ class ServerlessCustomDomain { public async setupBasePathMapping(): Promise { // check if basepathmapping exists const restApiId = await this.getRestApiId(); - const createDomainName = this.serverless.service.custom.customDomain.createDomainName; - if (createDomainName === true) { + const autoDomain = this.serverless.service.custom.customDomain.autoDomain; + if (autoDomain === true) { this.serverless.cli.log("Creating domain name before setting up base path mapping."); await this.createDomain(); } @@ -167,8 +167,8 @@ class ServerlessCustomDomain { */ public async removeBasePathMapping(): Promise { await this.deleteBasePathMapping(); - const createDomainName = this.serverless.service.custom.customDomain.createDomainName; - if (createDomainName === true) { + const autoDomain = this.serverless.service.custom.customDomain.autoDomain; + if (autoDomain === true) { this.serverless.cli.log("Deleting domain name after removing base path mapping."); await this.deleteDomain(); } diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 73329a22..0ba25d2d 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -59,10 +59,10 @@ const constructPlugin = (customDomainOptions) => { service: { custom: { customDomain: { + autoDomain: customDomainOptions.autoDomain, basePath: customDomainOptions.basePath, certificateArn: customDomainOptions.certificateArn, certificateName: customDomainOptions.certificateName, - createDomainName: customDomainOptions.createDomainName, createRoute53Record: customDomainOptions.createRoute53Record, domainName: customDomainOptions.domainName, enabled: customDomainOptions.enabled, @@ -1180,10 +1180,10 @@ describe("Custom Domain Plugin", () => { it("Should be disabled by default", () => { const plugin = constructPlugin({ domainName: "test_domain" }); plugin.initializeVariables(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(undefined); + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(undefined); }); - it("setUpBasePathMapping should call createDomain when createDomainName is true", async () => { + it("setUpBasePathMapping should call createDomain when autoDomain is true", async () => { AWS.mock("APIGateway", "getDomainName", (params, callback) => { callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); }); @@ -1202,7 +1202,7 @@ describe("Custom Domain Plugin", () => { }, }); }); - const plugin = constructPlugin({ domainName: "test_domain", createDomainName: true }); + const plugin = constructPlugin({ domainName: "test_domain", autoDomain: true }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); plugin.cloudformation = new aws.CloudFormation(); @@ -1211,11 +1211,11 @@ describe("Custom Domain Plugin", () => { await plugin.setupBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(true); + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); expect(spy).to.have.been.called(); }); - it("setUpBasePathMapping should not call createDomain when createDomainName is not true", async () => { + it("setUpBasePathMapping should not call createDomain when autoDomain is not true", async () => { AWS.mock("APIGateway", "getDomainName", (params, callback) => { callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); }); @@ -1234,7 +1234,7 @@ describe("Custom Domain Plugin", () => { }, }); }); - const plugin = constructPlugin({ createDomainName: false, domainName: "test_domain" }); + const plugin = constructPlugin({ autoDomain: false, domainName: "test_domain" }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); plugin.cloudformation = new aws.CloudFormation(); @@ -1243,11 +1243,11 @@ describe("Custom Domain Plugin", () => { await plugin.setupBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(false); + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); expect(spy).to.not.have.been.called(); }); - it("removeBasePathMapping should call deleteDomain when createDomainName is true", async () => { + it("removeBasePathMapping should call deleteDomain when autoDomain is true", async () => { AWS.mock("APIGateway", "deleteBasePathMapping", (params, callback) => { callback(null, params); }); @@ -1257,7 +1257,7 @@ describe("Custom Domain Plugin", () => { AWS.mock("APIGateway", "deleteDomainName", (params, callback) => { callback(null, params); }); - const plugin = constructPlugin({ createDomainName: true, createRoute53Record: false, domainName: "test_domain" }); + const plugin = constructPlugin({ autoDomain: true, createRoute53Record: false, domainName: "test_domain" }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; @@ -1265,18 +1265,18 @@ describe("Custom Domain Plugin", () => { await plugin.removeBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(true); + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); expect(spy).to.have.been.called(); }); - it("removeBasePathMapping should not call deleteDomain when createDomainName is not true", async () => { - const plugin = constructPlugin({ createDomainName: false }); + it("removeBasePathMapping should not call deleteDomain when autoDomain is not true", async () => { + const plugin = constructPlugin({ autoDomain: false }); plugin.initializeVariables(); const spy = chai.spy.on(plugin, "deleteDomain"); await plugin.removeBasePathMapping(); - expect(plugin.serverless.service.custom.customDomain.createDomainName).to.equal(false); + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); expect(spy).to.not.have.been.called(); }); diff --git a/types.ts b/types.ts index 749f16e2..9406cd1f 100644 --- a/types.ts +++ b/types.ts @@ -24,7 +24,7 @@ export interface ServerlessInstance { // tslint:disable-line hostedZonePrivate: boolean | undefined, enabled: boolean | string | undefined, securityPolicy: string | undefined, - createDomainName: boolean | undefined, + autoDomain: boolean | undefined, }, }, }; From 2ee26449dcd776e94798f64839a8fc9b045201cd Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 5 May 2020 12:55:53 -0500 Subject: [PATCH 24/69] rename --- test/unit-tests/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 0ba25d2d..2e7dc092 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -1176,7 +1176,7 @@ describe("Custom Domain Plugin", () => { }); }); - describe("create domain name deploy", () => { + describe("autoDomain deploy", () => { it("Should be disabled by default", () => { const plugin = constructPlugin({ domainName: "test_domain" }); plugin.initializeVariables(); From ab724d7f5a18ea49f39d23fb00bd67a797c18e75 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Wed, 6 May 2020 00:27:34 -0400 Subject: [PATCH 25/69] Update version and readme for version 4 release --- CHANGELOG.md | 9 +++++++-- README.md | 2 -- package.json | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb9857a..fca1c6f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [4.0.0] - Unreleased + +### Added +- Add support for WebSocket and HTTP APIs. A domain name can be created for each API type (Rest, WebSocket, HTTP) +for up to 3 domain names in a single Serverless config. Thanks @TehNrd ([#319](https://github.com/amplify-education/serverless-domain-manager/pull/319)) + ## [3.2.7] - 2019-08-02 @@ -72,7 +77,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed - Support for migrating CNAMEs to A Alias Records - - In 1.0, we only created CNAME records. In 2.0 we deprecated CNAME creation and started creating A Alias records and migrated CNAME records to A Alias records. Now in 3.0, we only create A Alias records. +- In 1.0, we only created CNAME records. In 2.0 we deprecated CNAME creation and started creating A Alias records and migrated CNAME records to A Alias records. Now in 3.0, we only create A Alias records. ## [2.6.13] - 2019-01-25 diff --git a/README.md b/README.md index c2680eaf..702d32e9 100644 --- a/README.md +++ b/README.md @@ -140,8 +140,6 @@ serverless delete_domain # How it works Creating the custom domain takes advantage of Amazon's Certificate Manager to assign a certificate to the given domain name. Based on already created certificate names, the plugin will search for the certificate that resembles the custom domain's name the most and assign the ARN to that domain name. The plugin then creates the proper A Alias and AAAA Alias records for the domain through Route 53. Once the domain name is set it takes up to 40 minutes before it is initialized. After the certificate is initialized, `sls deploy` will create the base path mapping and assign the lambda to the custom domain name through CloudFront. All resources are created independent of CloudFormation. However, deploying will also output the domain name and distribution domain name to the CloudFormation stack outputs under the keys `DomainName` and `DistributionDomainName`, respectively. -Note: In 1.0, we only created CNAME records. In 2.0 we deprecated CNAME creation and started creating A Alias records and migrated CNAME records to A Alias records. Now in 3.0, we only create A Alias records. Starting in version 3.2, we create AAAA Alias records as well. - ### Behavior Change in Version 3 In version 3, we decided to create/update/delete all resources through the API. Previously, only the basepath mapping was managed through CloudFormation. We moved away from creating anything through the stack for two reasons. diff --git a/package.json b/package.json index e7717b49..9ee9ad6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.2", + "version": "4.0.0", "engines": { "node": ">=4.0" }, From 32d9299fc87f1d9fdb0cd5494af784b3d3ae7527 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Wed, 6 May 2020 00:28:11 -0400 Subject: [PATCH 26/69] run npm audit fix --- package-lock.json | 210 ++++++++++++++-------------------------------- package.json | 2 +- 2 files changed, 65 insertions(+), 147 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9b598098..27e58dec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "3.3.2", + "version": "4.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -184,12 +184,6 @@ "dev": true, "optional": true }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -306,44 +300,6 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -396,6 +352,12 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "caching-transform": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", @@ -488,12 +450,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", - "dev": true - }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -835,30 +791,6 @@ "locate-path": "^3.0.0" } }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", - "dev": true, - "requires": { - "glob": "~5.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -964,17 +896,24 @@ "dev": true }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", "dev": true, "requires": { + "minimist": "^1.2.5", "neo-async": "^2.6.0", - "optimist": "^0.6.1", "source-map": "^0.6.1", - "uglify-js": "^3.1.4" + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" }, "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1022,15 +961,6 @@ "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1063,6 +993,12 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1357,12 +1293,12 @@ } }, "istanbul-reports": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", - "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", "dev": true, "requires": { - "handlebars": "^4.1.2" + "html-escaper": "^2.0.0" } }, "jmespath": { @@ -1370,12 +1306,6 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -1759,7 +1689,7 @@ "dependencies": { "uuid": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "resolved": false, "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true } @@ -1816,24 +1746,6 @@ "wrappy": "1" } }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -2291,9 +2203,9 @@ } }, "spawn-wrap": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", - "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", "dev": true, "requires": { "foreground-child": "^1.5.6", @@ -2413,15 +2325,6 @@ "function-bind": "^1.1.1" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -2511,20 +2414,32 @@ "dev": true }, "tslint": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.1.0.tgz", - "integrity": "sha1-UaR7rutYlW/NYXvSzwDi7w7qLtk=", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { - "babel-code-frame": "^6.22.0", - "colors": "^1.1.2", - "diff": "^3.2.0", - "findup-sync": "~0.3.0", + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", "glob": "^7.1.1", - "optimist": "~0.6.0", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", "resolve": "^1.3.2", "semver": "^5.3.0", - "tsutils": "^1.4.0" + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } } }, "tslint-microsoft-contrib": { @@ -2548,10 +2463,13 @@ } }, "tsutils": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", - "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", - "dev": true + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } }, "tunnel-agent": { "version": "0.6.0", @@ -2793,9 +2711,9 @@ } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/package.json b/package.json index 9ee9ad6e..25e6b9dd 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "request-promise-native": "^1.0.5", "shelljs": "^0.8.3", "ts-node": "^8.0.1", - "tslint": "^5.1.0", + "tslint": "^5.20.1", "tslint-microsoft-contrib": "^6.0.0", "typescript": "^3.2.2", "wrappy": "^1.0.2" From 6a0cd100c5e320e1b91101e4a9ec3074636597e6 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Wed, 6 May 2020 00:32:27 -0400 Subject: [PATCH 27/69] fix lint errors --- DomainConfig.ts | 4 ++-- index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DomainConfig.ts b/DomainConfig.ts index 1b707a2e..09363675 100644 --- a/DomainConfig.ts +++ b/DomainConfig.ts @@ -2,9 +2,9 @@ * Wrapper class for Custom Domain information */ -import Globals from "./Globals"; -import DomainInfo = require("./DomainInfo"); import * as AWS from "aws-sdk"; // imported for Types +import DomainInfo = require("./DomainInfo"); +import Globals from "./Globals"; class DomainConfig { diff --git a/index.ts b/index.ts index 06e05002..71c6157d 100644 --- a/index.ts +++ b/index.ts @@ -1,8 +1,8 @@ "use strict"; import chalk from "chalk"; -import DomainInfo = require("./DomainInfo"); import DomainConfig = require("./DomainConfig"); +import DomainInfo = require("./DomainInfo"); import Globals from "./Globals"; import { ServerlessInstance, ServerlessOptions } from "./types"; From 35161f335855da0ef7671c9cc55fd7ea66c892e3 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Wed, 6 May 2020 00:53:37 -0400 Subject: [PATCH 28/69] undo indent change --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fca1c6f9..42d2671a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,7 +77,7 @@ for up to 3 domain names in a single Serverless config. Thanks @TehNrd ([#319](h ### Removed - Support for migrating CNAMEs to A Alias Records -- In 1.0, we only created CNAME records. In 2.0 we deprecated CNAME creation and started creating A Alias records and migrated CNAME records to A Alias records. Now in 3.0, we only create A Alias records. + - In 1.0, we only created CNAME records. In 2.0 we deprecated CNAME creation and started creating A Alias records and migrated CNAME records to A Alias records. Now in 3.0, we only create A Alias records. ## [2.6.13] - 2019-01-25 From 882e50777f1064fe716591952f0f68019c169385 Mon Sep 17 00:00:00 2001 From: Hunter Date: Wed, 6 May 2020 12:28:16 -0500 Subject: [PATCH 29/69] move to before deploy so updateCloudFormationOutputs can getDomainInfo --- index.ts | 12 +++++------ test/unit-tests/index.test.ts | 38 ++++------------------------------- 2 files changed, 10 insertions(+), 40 deletions(-) diff --git a/index.ts b/index.ts index d025cef8..ec71538b 100644 --- a/index.ts +++ b/index.ts @@ -131,9 +131,14 @@ class ServerlessCustomDomain { } /** - * Lifecycle function to add domain info to the CloudFormation stack's Outputs + * Lifecycle function to createDomain before deploy and add domain info to the CloudFormation stack's Outputs */ public async updateCloudFormationOutputs(): Promise { + const autoDomain = this.serverless.service.custom.customDomain.autoDomain; + if (autoDomain === true) { + this.serverless.cli.log("Creating domain name before deploy."); + await this.createDomain(); + } const domainInfo = await this.getDomainInfo(); this.addOutputs(domainInfo); } @@ -145,11 +150,6 @@ class ServerlessCustomDomain { public async setupBasePathMapping(): Promise { // check if basepathmapping exists const restApiId = await this.getRestApiId(); - const autoDomain = this.serverless.service.custom.customDomain.autoDomain; - if (autoDomain === true) { - this.serverless.cli.log("Creating domain name before setting up base path mapping."); - await this.createDomain(); - } const currentBasePath = await this.getBasePathMapping(restApiId); // if basepath that matches restApiId exists, update; else, create if (!currentBasePath) { diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 2e7dc092..6691d802 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -1183,25 +1183,10 @@ describe("Custom Domain Plugin", () => { expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(undefined); }); - it("setUpBasePathMapping should call createDomain when autoDomain is true", async () => { + it("updateCloudFormationOutputs should call createDomain when autoDomain is true", async () => { AWS.mock("APIGateway", "getDomainName", (params, callback) => { callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); }); - AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { - callback(null, { items: [] }); - }); - AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { - callback(null, params); - }); - AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { - callback(null, { - StackResourceDetail: - { - LogicalResourceId: "ApiGatewayRestApi", - PhysicalResourceId: "test_rest_api_id", - }, - }); - }); const plugin = constructPlugin({ domainName: "test_domain", autoDomain: true }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); @@ -1209,31 +1194,16 @@ describe("Custom Domain Plugin", () => { plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; const spy = chai.spy.on(plugin, "createDomain"); - await plugin.setupBasePathMapping(); + await plugin.updateCloudFormationOutputs(); expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); expect(spy).to.have.been.called(); }); - it("setUpBasePathMapping should not call createDomain when autoDomain is not true", async () => { + it("updateCloudFormationOutputs should not call createDomain when autoDomain is not true", async () => { AWS.mock("APIGateway", "getDomainName", (params, callback) => { callback(null, { domainName: "fake_domain", distributionDomainName: "fake_dist_name" }); }); - AWS.mock("APIGateway", "getBasePathMappings", (params, callback) => { - callback(null, { items: [] }); - }); - AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { - callback(null, params); - }); - AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { - callback(null, { - StackResourceDetail: - { - LogicalResourceId: "ApiGatewayRestApi", - PhysicalResourceId: "test_rest_api_id", - }, - }); - }); const plugin = constructPlugin({ autoDomain: false, domainName: "test_domain" }); plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); @@ -1241,7 +1211,7 @@ describe("Custom Domain Plugin", () => { plugin.givenDomainName = plugin.serverless.service.custom.customDomain.domainName; const spy = chai.spy.on(plugin, "createDomain"); - await plugin.setupBasePathMapping(); + await plugin.updateCloudFormationOutputs(); expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); expect(spy).to.not.have.been.called(); From cb59d5c9fa06179f71a4a7e089cd1e3a98c6ce8f Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Wed, 6 May 2020 15:03:38 -0400 Subject: [PATCH 30/69] update date of 4.0.0 release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d2671a..6a052911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [4.0.0] - Unreleased +## [4.0.0] - 2020-05-06 ### Added - Add support for WebSocket and HTTP APIs. A domain name can be created for each API type (Rest, WebSocket, HTTP) From 8ec5fc3d09fd422783cab6d01e50e64989ab1b18 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Wed, 6 May 2020 15:12:41 -0400 Subject: [PATCH 31/69] backfill changelog --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a052911..ba9341dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add support for WebSocket and HTTP APIs. A domain name can be created for each API type (Rest, WebSocket, HTTP) for up to 3 domain names in a single Serverless config. Thanks @TehNrd ([#319](https://github.com/amplify-education/serverless-domain-manager/pull/319)) +## [3.3.2] - 2020-04-21 + +### Changed +- Fix CloudFormation stack's Outputs. Thanks @davidrosson ([#320](https://github.com/amplify-education/serverless-domain-manager/pull/320)) +- Use pagination when there are too many certificates. Thanks @cbm-gplassard ([#315](https://github.com/amplify-education/serverless-domain-manager/pull/315)) + +## [3.3.1] - 2020-01-16 + +### Changed +- Fix AWS SDK initialization after internal change in serverless. Thanks @medikoo ([#307](https://github.com/amplify-education/serverless-domain-manager/pull/307)) + +## [3.3.0] - 2019-08-12 + +### Added +- Add ability to choose TLS version. Thanks @drexler ([#240](https://github.com/amplify-education/serverless-domain-manager/pull/240)) ## [3.2.7] - 2019-08-02 From d9b81a0b05e19499fbda836f68c4234fbdc3b1d2 Mon Sep 17 00:00:00 2001 From: Fabian Cook Date: Sat, 9 May 2020 16:20:10 +1200 Subject: [PATCH 32/69] Fixes #332 --- index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 71c6157d..a052f601 100644 --- a/index.ts +++ b/index.ts @@ -623,7 +623,7 @@ class ServerlessCustomDomain { // Use APIGateway (v1) for EDGE domains if (domain.endpointType === Globals.endpointTypes.edge) { const params = { - basePath: domain.apiMapping.ApiMappingKey, + basePath: domain.apiMapping.ApiMappingKey || '(none)', domainName: domain.givenDomainName, patchOperations: [ { From 7076ff0a9b1fe8d69726d3db481339445fd304e6 Mon Sep 17 00:00:00 2001 From: Fabian Cook Date: Sun, 10 May 2020 15:58:09 +1200 Subject: [PATCH 33/69] Correct linting --- index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.ts b/index.ts index a052f601..c1004eb5 100644 --- a/index.ts +++ b/index.ts @@ -623,7 +623,7 @@ class ServerlessCustomDomain { // Use APIGateway (v1) for EDGE domains if (domain.endpointType === Globals.endpointTypes.edge) { const params = { - basePath: domain.apiMapping.ApiMappingKey || '(none)', + basePath: domain.apiMapping.ApiMappingKey || "(none)", domainName: domain.givenDomainName, patchOperations: [ { From 7fe5068ecc33630574d6bb2e00dcbc3939e90a19 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Mon, 11 May 2020 12:14:04 -0400 Subject: [PATCH 34/69] fix integration tests and make them run faster --- package-lock.json | 369 ++++++++++++++++-- package.json | 2 +- .../basepath-mapping/serverless.yml | 8 +- .../create-domain-idempotent/serverless.yml | 8 +- .../deploy-idempotent/serverless.yml | 8 +- .../integration-tests/disabled/serverless.yml | 8 +- .../enabled-basepath/serverless.yml | 8 +- .../enabled-custom-apigateway/serverless.yml | 8 +- .../enabled-default/serverless.yml | 8 +- .../enabled-regional-basepath/serverless.yml | 9 +- .../serverless.yml | 9 +- .../serverless.yml | 9 +- .../enabled-stage-basepath/serverless.yml | 8 +- test/integration-tests/integration.test.js | 175 ++------- .../null-basepath-mapping/serverless.yml | 8 +- test/integration-tests/test-utilities.js | 24 +- .../two-three-migration-basepath/handler.js | 16 - .../serverless.yml | 20 - .../two-three-migration-default/handler.js | 16 - .../serverless.yml | 19 - 20 files changed, 452 insertions(+), 288 deletions(-) delete mode 100644 test/integration-tests/two-three-migration-basepath/handler.js delete mode 100644 test/integration-tests/two-three-migration-basepath/serverless.yml delete mode 100644 test/integration-tests/two-three-migration-default/handler.js delete mode 100644 test/integration-tests/two-three-migration-default/serverless.yml diff --git a/package-lock.json b/package-lock.json index 27e58dec..9d0f12c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -184,6 +184,18 @@ "dev": true, "optional": true }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -192,6 +204,16 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "append-transform": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", @@ -320,6 +342,12 @@ "tweetnacl": "^0.14.3" } }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -330,6 +358,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -409,6 +446,22 @@ "supports-color": "^5.3.0" } }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -525,12 +578,12 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "decamelize": { @@ -771,6 +824,15 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -791,6 +853,15 @@ "locate-path": "^3.0.0" } }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -833,6 +904,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -877,6 +955,15 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -982,9 +1069,9 @@ } }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "hosted-git-info": { @@ -1061,6 +1148,21 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, "is-callable": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", @@ -1073,6 +1175,12 @@ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -1085,6 +1193,21 @@ "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", "dev": true }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", @@ -1425,6 +1548,28 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, "lolex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", @@ -1525,60 +1670,77 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz", + "integrity": "sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==", "dev": true, "requires": { + "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", + "chokidar": "3.3.0", + "debug": "3.2.6", "diff": "3.5.0", "escape-string-regexp": "1.0.5", - "glob": "7.1.2", + "find-up": "3.0.0", + "glob": "7.1.3", "growl": "1.10.5", - "he": "1.1.1", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" }, "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "has-flag": "^3.0.0" } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } } } @@ -1590,9 +1752,9 @@ "dev": true }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "neo-async": { @@ -1613,6 +1775,24 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -1645,6 +1825,12 @@ } } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -1737,6 +1923,16 @@ "has": "^1.0.3" } }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1888,6 +2084,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -1985,6 +2187,15 @@ "read-pkg": "^3.0.0" } }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -2325,6 +2536,15 @@ "function-bind": "^1.1.1" } }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -2337,6 +2557,12 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2363,6 +2589,15 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -2614,6 +2849,27 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -2720,6 +2976,37 @@ "decamelize": "^1.2.0" } }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + } + } + }, "yn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", diff --git a/package.json b/package.json index 25e6b9dd..d6978b79 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "chai": "^3.5.0", "chai-spies": "^1.0.0", "istanbul": "^0.4.5", - "mocha": "^5.2.0", + "mocha": "^7.1.2", "mocha-param": "^2.0.0", "nyc": "^14.1.1", "randomstring": "^1.1.5", diff --git a/test/integration-tests/basepath-mapping/serverless.yml b/test/integration-tests/basepath-mapping/serverless.yml index bbfd38a6..e8b7c45d 100644 --- a/test/integration-tests/basepath-mapping/serverless.yml +++ b/test/integration-tests/basepath-mapping/serverless.yml @@ -1,8 +1,8 @@ # Enabled and testing basepath mapping -service: basepath-mapping +service: basepath-mapping-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 stage: test functions: @@ -19,3 +19,7 @@ custom: customDomain: domainName: basepath-mapping-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: 'api' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/create-domain-idempotent/serverless.yml b/test/integration-tests/create-domain-idempotent/serverless.yml index b0a4e43c..23535d93 100644 --- a/test/integration-tests/create-domain-idempotent/serverless.yml +++ b/test/integration-tests/create-domain-idempotent/serverless.yml @@ -1,8 +1,8 @@ # Creating a domain should be idempotent -service: create-domain-idempotent +service: create-domain-idempotent-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 stage: test functions: @@ -19,3 +19,7 @@ custom: customDomain: domainName: create-domain-idempotent-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: '' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/deploy-idempotent/serverless.yml b/test/integration-tests/deploy-idempotent/serverless.yml index e404d9fb..ee7a505d 100644 --- a/test/integration-tests/deploy-idempotent/serverless.yml +++ b/test/integration-tests/deploy-idempotent/serverless.yml @@ -1,8 +1,8 @@ # Deploying should be idempotent -service: deploy-idempotent +service: deploy-idempotent-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 stage: test functions: @@ -19,3 +19,7 @@ custom: customDomain: domainName: deploy-idempotent-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: '' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/disabled/serverless.yml b/test/integration-tests/disabled/serverless.yml index 30ae630b..e0b7a533 100644 --- a/test/integration-tests/disabled/serverless.yml +++ b/test/integration-tests/disabled/serverless.yml @@ -1,8 +1,8 @@ # Disabled -service: domain-manager-disabled +service: domain-manager-disabled-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 functions: helloWorld: @@ -18,3 +18,7 @@ custom: customDomain: domainName: disabled-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} enabled: false + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-basepath/serverless.yml b/test/integration-tests/enabled-basepath/serverless.yml index b00d7b93..ca940cc1 100644 --- a/test/integration-tests/enabled-basepath/serverless.yml +++ b/test/integration-tests/enabled-basepath/serverless.yml @@ -1,8 +1,8 @@ # Enabled with custom basepath -service: enabled-basepath +service: enabled-basepath-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 functions: helloWorld: @@ -18,3 +18,7 @@ custom: customDomain: domainName: enabled-basepath-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: 'api' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-custom-apigateway/serverless.yml b/test/integration-tests/enabled-custom-apigateway/serverless.yml index 0a8ab84f..86e848b9 100644 --- a/test/integration-tests/enabled-custom-apigateway/serverless.yml +++ b/test/integration-tests/enabled-custom-apigateway/serverless.yml @@ -1,8 +1,8 @@ # Enabled with default values -service: enabled-custom-apigateway +service: enabled-custom-apigateway-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 apiGateway: restApiId: ${env:REST_API_ID} @@ -21,3 +21,7 @@ plugins: custom: customDomain: domainName: enabled-custom-apigateway-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-default/serverless.yml b/test/integration-tests/enabled-default/serverless.yml index 4a958c50..7a45a8a3 100644 --- a/test/integration-tests/enabled-default/serverless.yml +++ b/test/integration-tests/enabled-default/serverless.yml @@ -1,8 +1,8 @@ # Enabled with default values -service: enabled-default +service: enabled-default-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 functions: helloWorld: @@ -17,3 +17,7 @@ plugins: custom: customDomain: domainName: enabled-default-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-regional-basepath/serverless.yml b/test/integration-tests/enabled-regional-basepath/serverless.yml index e92dd62f..09de2585 100644 --- a/test/integration-tests/enabled-regional-basepath/serverless.yml +++ b/test/integration-tests/enabled-regional-basepath/serverless.yml @@ -1,9 +1,10 @@ # Enabled with regional endpoint, custom basePath -service: enabled-regional-basepath +service: enabled-regional-basepath-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 + endpointType: regional functions: helloWorld: handler: handler.helloWorld @@ -19,3 +20,7 @@ custom: domainName: enabled-regional-basepath-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: 'api' endpointType: regional + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-regional-empty-basepath/serverless.yml b/test/integration-tests/enabled-regional-empty-basepath/serverless.yml index c137f2b9..6ecbba34 100644 --- a/test/integration-tests/enabled-regional-empty-basepath/serverless.yml +++ b/test/integration-tests/enabled-regional-empty-basepath/serverless.yml @@ -1,9 +1,10 @@ # Enabled with regional endpoint and empty basepath -service: enabled-regional-empty-basepath +service: enabled-regional-empty-basepath-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 + endpointType: regional functions: helloWorld: handler: handler.helloWorld @@ -19,3 +20,7 @@ custom: domainName: enabled-regional-empty-basepath-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: '' endpointType: regional + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-regional-stage-basepath/serverless.yml b/test/integration-tests/enabled-regional-stage-basepath/serverless.yml index 65998c6e..eadc7ba4 100644 --- a/test/integration-tests/enabled-regional-stage-basepath/serverless.yml +++ b/test/integration-tests/enabled-regional-stage-basepath/serverless.yml @@ -1,10 +1,11 @@ # Enabled with regional endpoint, custom stage, empty basepath -service: enabled-regional-stage-basepath +service: enabled-regional-stage-basepath-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 stage: test + endpointType: regional functions: helloWorld: handler: handler.helloWorld @@ -21,3 +22,7 @@ custom: stage: test basePath: '' endpointType: regional + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/enabled-stage-basepath/serverless.yml b/test/integration-tests/enabled-stage-basepath/serverless.yml index e40396f5..9e8d4ca9 100644 --- a/test/integration-tests/enabled-stage-basepath/serverless.yml +++ b/test/integration-tests/enabled-stage-basepath/serverless.yml @@ -1,8 +1,8 @@ # Enabled with custom stage and empty basepath -service: enabled-stage-basepath +service: enabled-stage-basepath-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 stage: test functions: @@ -20,3 +20,7 @@ custom: domainName: enabled-stage-basepath-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} stage: test basePath: '' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/integration.test.js b/test/integration-tests/integration.test.js index 30d4c020..a8e5402a 100644 --- a/test/integration-tests/integration.test.js +++ b/test/integration-tests/integration.test.js @@ -8,7 +8,11 @@ const randomstring = require("randomstring"); const expect = chai.expect; const TEST_DOMAIN = process.env.TEST_DOMAIN; -const SIX_HOURS = 6 * 60 * 60 * 1000; // 6 hours in milliseconds +if(!TEST_DOMAIN) { + throw new Error('TEST_DOMAIN environment variable not set') +} + +const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds const RANDOM_STRING = randomstring.generate({ length: 5, charset: "alphanumeric", @@ -85,10 +89,10 @@ const testCases = [ describe("Integration Tests", function () { // eslint-disable-line func-names - this.timeout(SIX_HOURS); // 6 hours to allow for dns to propogate + this.timeout(FIFTEEN_MINUTES); describe("Domain Manager Is Enabled", function () { // eslint-disable-line func-names - this.timeout(SIX_HOURS); + this.timeout(FIFTEEN_MINUTES); itParam("${value.testDescription}", testCases, async (value) => { // eslint-disable-line no-template-curly-in-string let restApiInfo; @@ -108,9 +112,6 @@ describe("Integration Tests", function () { // eslint-disable-line func-names const endpoint = await utilities.getEndpointType(value.testDomain); expect(endpoint).to.equal(value.testEndpoint); - - const status = await utilities.curlUrl(value.testURL); - expect(status).to.equal(200); } await utilities.destroyResources(value.testDomain, RANDOM_STRING); if (value.createApiGateway) { @@ -119,123 +120,89 @@ describe("Integration Tests", function () { // eslint-disable-line func-names }); }); - describe("Domain Manager Is Not Enabled", function () { // eslint-disable-line func-names - this.timeout(5 * 60 * 1000); // 5 minutes in milliseconds - const testName = "disabled"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - before(async () => { - const created = await utilities.createResources(testName, testURL, RANDOM_STRING, false); - if (!created) { - throw new utilities.CreationError("Resources failed to create."); - } - }); - - it("Does not create a domain", async () => { - const data = await utilities.curlUrl(`https://${testURL}/hello-world`); - expect(data).to.equal(null); - }); - - after(async () => { - await utilities.destroyResources(testURL, RANDOM_STRING); - }); - }); - describe("Basepath Mapping Is Empty", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds + this.timeout(FIFTEEN_MINUTES); const testName = "null-basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - before(async () => { + it("Creates a basepath mapping", async () => { // Perform sequence of commands to replicate basepath mapping issue - // Sleep for a min b/w commands in order to avoid rate limiting. + // Sleep for half a min between commands in order to avoid rate limiting. await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - }); - it("Creates a basepath mapping", async () => { const basePath = await utilities.getBasePath(testURL); expect(basePath).to.equal("(none)"); - }); - after(async () => { await utilities.destroyResources(testURL, RANDOM_STRING); }); }); describe("Basepath Mapping Is Set", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds + this.timeout(FIFTEEN_MINUTES); const testName = "basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - before(async () => { + it("Creates a basepath mapping", async () => { // Perform sequence of commands to replicate basepath mapping issue - // Sleep for a min b/w commands in order to avoid rate limiting. + // Sleep for half a min between commands in order to avoid rate limiting. await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - }); - it("Creates a basepath mapping", async () => { const basePath = await utilities.getBasePath(testURL); expect(basePath).to.equal("api"); - }); - after(async () => { await utilities.destroyResources(testURL, RANDOM_STRING); }); }); describe("Basepath Mapping Is Empty And Fix Works", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds + this.timeout(FIFTEEN_MINUTES); const testName = "null-basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - before(async () => { + it("Creates a basepath mapping", async () => { // Perform sequence of commands to replicate basepath mapping issue - // Sleep for a min b/w commands in order to avoid rate limiting. + // Sleep for half a min between commands in order to avoid rate limiting. await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - }); - it("Creates a basepath mapping", async () => { const basePath = await utilities.getBasePath(testURL); expect(basePath).to.equal("(none)"); - }); - after(async () => { await utilities.destroyResources(testURL, RANDOM_STRING); }); }); describe("Create domain is idempotent", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds + this.timeout(FIFTEEN_MINUTES); const testName = "create-domain-idempotent"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; @@ -244,23 +211,21 @@ describe("Integration Tests", function () { // eslint-disable-line func-names let deploySuccess; await utilities.createTempDir(TEMP_DIR, testName); createDomainSuccess = createDomainSuccess && await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); createDomainSuccess = createDomainSuccess && await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); createDomainSuccess = createDomainSuccess && await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); deploySuccess = await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); expect(createDomainSuccess).to.equal(true); expect(deploySuccess).to.equal(true); - }); - after(async () => { await utilities.destroyResources(testURL, RANDOM_STRING); }); }); describe("Deploy is idempotent", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds + this.timeout(FIFTEEN_MINUTES); const testName = "deploy-idempotent"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; @@ -269,82 +234,16 @@ describe("Integration Tests", function () { // eslint-disable-line func-names let deploySuccess = true; await utilities.createTempDir(TEMP_DIR, testName); createDomainSuccess = await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); deploySuccess = deploySuccess && await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); deploySuccess = deploySuccess && await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(60); + await utilities.sleep(30); deploySuccess = deploySuccess && await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); expect(createDomainSuccess).to.equal(true); expect(deploySuccess).to.equal(true); - }); - after(async () => { await utilities.destroyResources(testURL, RANDOM_STRING); }); }); - - describe("Migrating from 2.x.x to 3.x.x works", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds - const testName = "two-three-migration-default"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - before(async () => { - await utilities.exec(`rm -rf ${TEMP_DIR}`); - await utilities.exec(`mkdir -p ${TEMP_DIR} && cp -R test/integration-tests/${testName}/. ${TEMP_DIR}`); - await utilities.exec(`cd ${TEMP_DIR}/ && npm install serverless-domain-manager@2.6.13`); - }); - - it("Creates a basepath mapping", async () => { - await utilities.exec(`cd ${TEMP_DIR} && sls create_domain --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`cd ${TEMP_DIR} && sls deploy --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`cp -R . ${TEMP_DIR}/node_modules/serverless-domain-manager`); - await utilities.exec(`cd ${TEMP_DIR} && sls deploy --RANDOM_STRING ${RANDOM_STRING}`); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - }); - - after(async () => { - await utilities.exec(`cd ${TEMP_DIR} && sls remove --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`cd ${TEMP_DIR} && sls delete_domain --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`rm -rf ${TEMP_DIR}`); - }); - }); - - describe("Migrating from 2.x.x to 3.x.x works given basepath", function () { // eslint-disable-line func-names - this.timeout(15 * 60 * 1000); // 15 minutes in milliseconds - const testName = "two-three-migration-basepath"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - before(async () => { - await utilities.exec(`rm -rf ${TEMP_DIR}`); - await utilities.exec(`mkdir -p ${TEMP_DIR} && cp -R test/integration-tests/${testName}/. ${TEMP_DIR}`); - await utilities.exec(`cd ${TEMP_DIR}/ && npm install serverless-domain-manager@2.6.13`); - }); - - it("Creates a basepath mapping", async () => { - await utilities.exec(`cd ${TEMP_DIR} && sls create_domain --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`cd ${TEMP_DIR} && sls deploy --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`cp -R . ${TEMP_DIR}/node_modules/serverless-domain-manager`); - await utilities.exec(`cd ${TEMP_DIR} && sls deploy --RANDOM_STRING ${RANDOM_STRING}`); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("api"); - }); - - after(async () => { - await utilities.exec(`cd ${TEMP_DIR} && sls remove --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`cd ${TEMP_DIR} && sls delete_domain --RANDOM_STRING ${RANDOM_STRING}`); - await utilities.sleep(60); - await utilities.exec(`rm -rf ${TEMP_DIR}`); - }); - }); }); diff --git a/test/integration-tests/null-basepath-mapping/serverless.yml b/test/integration-tests/null-basepath-mapping/serverless.yml index 38425351..1d1d5cc0 100644 --- a/test/integration-tests/null-basepath-mapping/serverless.yml +++ b/test/integration-tests/null-basepath-mapping/serverless.yml @@ -1,8 +1,8 @@ # Enabled and testing basepath mapping -service: null-basepath-mapping +service: null-basepath-mapping-${opt:RANDOM_STRING} provider: name: aws - runtime: nodejs6.10 + runtime: nodejs12.x region: us-west-2 stage: test functions: @@ -19,3 +19,7 @@ custom: customDomain: domainName: null-basepath-mapping-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} basePath: '' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/test-utilities.js b/test/integration-tests/test-utilities.js index 2a7234b5..7218ca8f 100644 --- a/test/integration-tests/test-utilities.js +++ b/test/integration-tests/test-utilities.js @@ -4,6 +4,7 @@ const request = require("request-promise-native"); const aws = require("aws-sdk"); const dns = require("dns"); const shell = require("shelljs"); +const spawn = require("child_process"); const AWS_PROFILE = process.env.AWS_PROFILE; const apiGateway = new aws.APIGateway({ @@ -32,7 +33,7 @@ function sleep(seconds) { */ async function exec(cmd) { return new Promise((resolve) => { - shell.exec(`${cmd}`, { silent: true }, (err, stdout, stderr) => { + shell.exec(`${cmd}`, { silent: false }, (err, stdout, stderr) => { if (err || stderr) { return resolve(false); } @@ -49,8 +50,8 @@ async function exec(cmd) { async function createTempDir(tempDir, folderName) { await exec(`rm -rf ${tempDir}`); await exec(`mkdir -p ${tempDir} && cp -R test/integration-tests/${folderName}/. ${tempDir}`); - await exec(`mkdir -p ${tempDir}/node_modules/serverless-domain-manager`); - await exec(`cp -R . ${tempDir}/node_modules/serverless-domain-manager`); + await exec(`mkdir -p ${tempDir}/node_modules`); + await exec(`ln -s $(pwd) ${tempDir}/node_modules/`); } /** @@ -59,7 +60,7 @@ async function createTempDir(tempDir, folderName) { */ async function linkPackages() { return new Promise((resolve) => { - shell.exec("npm link serverless-domain-manager", { silent: true }, (err, stdout, stderr) => { + shell.exec("npm link serverless-domain-manager", { silent: false }, (err, stdout, stderr) => { if (err || stderr) { return resolve(false); } @@ -211,7 +212,7 @@ async function deleteApiGatewayResources(restApiId) { */ function slsCreateDomain(tempDir, domainIdentifier) { return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && sls create_domain --RANDOM_STRING ${domainIdentifier}`, { silent: true }, (err, stdout, stderr) => { + shell.exec(`cd ${tempDir} && serverless create_domain --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { if (err || stderr) { return resolve(false); } @@ -228,7 +229,7 @@ function slsCreateDomain(tempDir, domainIdentifier) { */ function slsDeploy(tempDir, domainIdentifier) { return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && sls deploy --RANDOM_STRING ${domainIdentifier}`, { silent: true }, (err, stdout, stderr) => { + shell.exec(`cd ${tempDir} && serverless deploy --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { if (err || stderr) { return resolve(false); } @@ -245,7 +246,7 @@ function slsDeploy(tempDir, domainIdentifier) { */ function slsDeleteDomain(tempDir, domainIdentifier) { return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && sls delete_domain --RANDOM_STRING ${domainIdentifier}`, { silent: true }, (err, stdout, stderr) => { + shell.exec(`cd ${tempDir} && serverless delete_domain --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { if (err || stderr) { return resolve(false); } @@ -262,7 +263,7 @@ function slsDeleteDomain(tempDir, domainIdentifier) { */ function slsRemove(tempDir, domainIdentifier) { return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && sls remove --RANDOM_STRING ${domainIdentifier}`, { silent: true }, (err, stdout, stderr) => { + shell.exec(`cd ${tempDir} && serverless remove --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { if (err || stderr) { return resolve(false); } @@ -306,18 +307,15 @@ async function removeLambdas(tempDir, domainIdentifier) { async function createResources(folderName, url, domainIdentifier, enabled) { console.debug(`\tCreating Resources for ${url}`); // eslint-disable-line no-console const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; + console.debug(`\tUsing tmp directory ${tempDir}`); await createTempDir(tempDir, folderName); const created = await deployLambdas(tempDir, domainIdentifier); - let dnsVerified = false; if (created) { - dnsVerified = await verifyDnsPropogation(url, enabled); - } - if (created && dnsVerified) { console.debug("\tResources Created"); // eslint-disable-line no-console } else { console.debug("\tResources Failed to Create"); // eslint-disable-line no-console } - return created && dnsVerified; + return created; } /** diff --git a/test/integration-tests/two-three-migration-basepath/handler.js b/test/integration-tests/two-three-migration-basepath/handler.js deleted file mode 100644 index 1bd222d6..00000000 --- a/test/integration-tests/two-three-migration-basepath/handler.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -module.exports.helloWorld = (event, context, callback) => { - const response = { - statusCode: 200, - headers: { - "Access-Control-Allow-Origin": "*", // Required for CORS support to work - }, - body: JSON.stringify({ - message: "Go Serverless v1.0! Your function executed successfully!", - input: event, - }), - }; - - callback(null, response); -}; diff --git a/test/integration-tests/two-three-migration-basepath/serverless.yml b/test/integration-tests/two-three-migration-basepath/serverless.yml deleted file mode 100644 index 71b2efcf..00000000 --- a/test/integration-tests/two-three-migration-basepath/serverless.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Migrating from version 2 to version 3 -service: two-three-migration-basepath -provider: - name: aws - runtime: nodejs6.10 - region: us-west-2 -functions: - helloWorld: - handler: handler.helloWorld - events: - - http: - path: hello-world - method: get - cors: true -plugins: - - serverless-domain-manager -custom: - customDomain: - domainName: two-three-migration-basepath-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} - basePath: api diff --git a/test/integration-tests/two-three-migration-default/handler.js b/test/integration-tests/two-three-migration-default/handler.js deleted file mode 100644 index 1bd222d6..00000000 --- a/test/integration-tests/two-three-migration-default/handler.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -module.exports.helloWorld = (event, context, callback) => { - const response = { - statusCode: 200, - headers: { - "Access-Control-Allow-Origin": "*", // Required for CORS support to work - }, - body: JSON.stringify({ - message: "Go Serverless v1.0! Your function executed successfully!", - input: event, - }), - }; - - callback(null, response); -}; diff --git a/test/integration-tests/two-three-migration-default/serverless.yml b/test/integration-tests/two-three-migration-default/serverless.yml deleted file mode 100644 index a9093dee..00000000 --- a/test/integration-tests/two-three-migration-default/serverless.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Migrating from version 2 to version 3 -service: two-three-migration-default -provider: - name: aws - runtime: nodejs6.10 - region: us-west-2 -functions: - helloWorld: - handler: handler.helloWorld - events: - - http: - path: hello-world - method: get - cors: true -plugins: - - serverless-domain-manager -custom: - customDomain: - domainName: two-three-migration-default-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} From 628f0ea8b858075678e98f0322dcd8fb1b895544 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Mon, 11 May 2020 13:24:33 -0400 Subject: [PATCH 35/69] fix lint errors and remove unused functions --- test/integration-tests/integration.test.js | 2 +- test/integration-tests/test-utilities.js | 67 +--------------------- 2 files changed, 3 insertions(+), 66 deletions(-) diff --git a/test/integration-tests/integration.test.js b/test/integration-tests/integration.test.js index a8e5402a..a2186513 100644 --- a/test/integration-tests/integration.test.js +++ b/test/integration-tests/integration.test.js @@ -9,7 +9,7 @@ const expect = chai.expect; const TEST_DOMAIN = process.env.TEST_DOMAIN; if(!TEST_DOMAIN) { - throw new Error('TEST_DOMAIN environment variable not set') + throw new Error("TEST_DOMAIN environment variable not set") } const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds diff --git a/test/integration-tests/test-utilities.js b/test/integration-tests/test-utilities.js index 7218ca8f..3eb6edfd 100644 --- a/test/integration-tests/test-utilities.js +++ b/test/integration-tests/test-utilities.js @@ -4,7 +4,7 @@ const request = require("request-promise-native"); const aws = require("aws-sdk"); const dns = require("dns"); const shell = require("shelljs"); -const spawn = require("child_process"); +const util = require('util'); const AWS_PROFILE = process.env.AWS_PROFILE; const apiGateway = new aws.APIGateway({ @@ -69,26 +69,6 @@ async function linkPackages() { }); } -/** - * Curls the given URL to see if it exists - * @param url - * @returns {Promise} Resolves to status code if exists, else null. - */ -async function curlUrl(url) { - let response = null; - response = await request.get({ - url, - resolveWithFullResponse: true, - }) - .catch((err) => { // eslint-disable-line no-unused-vars - response = null; - }); - if (response === undefined || response === null) { - return null; - } - return response.statusCode; -} - /** * Gets endpoint type of given URL from AWS * @param url @@ -140,46 +120,6 @@ async function getBasePath(url) { } } -/** - * Looks up DNS records for the given url - * @param url - * @returns {Promise} Resolves true if DNS records exist, else false. - */ -function dnsLookup(url) { - return new Promise((resolve) => { - dns.resolveAny(url, (err) => { - if (err) { - return resolve(false); - } - return resolve(true); - }); - }); -} - -/** - * Periodically calls dnsLookup until records found or 40 minutes elapse. - * @param url - * @param enabled - * @returns {Promise} Resolves true if records found, else false. - */ -async function verifyDnsPropogation(url, enabled) { - console.debug("\tWaiting for DNS to Propogate..."); // eslint-disable-line no-console - if (!enabled) { - return true; - } - let numRetries = 0; - let dnsPropogated = false; - while (numRetries < 40 && !dnsPropogated && enabled) { - dnsPropogated = await dnsLookup(url); // eslint-disable-line no-await-in-loop - if (dnsPropogated) { - break; - } - numRetries += 1; - await sleep(60); // eslint-disable-line no-await-in-loop - } - return dnsPropogated; -} - /** * Make API Gateway calls to create an API Gateway * @param {string} randString @@ -308,7 +248,7 @@ async function createResources(folderName, url, domainIdentifier, enabled) { console.debug(`\tCreating Resources for ${url}`); // eslint-disable-line no-console const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; console.debug(`\tUsing tmp directory ${tempDir}`); - await createTempDir(tempDir, folderName); + await createTempDir(tempDir, folderName); // eslint-disable-line no-console const created = await deployLambdas(tempDir, domainIdentifier); if (created) { console.debug("\tResources Created"); // eslint-disable-line no-console @@ -338,13 +278,10 @@ async function destroyResources(url, domainIdentifier) { } module.exports = { - curlUrl, createResources, createTempDir, destroyResources, exec, - verifyDnsPropogation, - dnsLookup, slsCreateDomain, slsDeploy, slsDeleteDomain, From 2bed61e8b7854caf358edf2af7dc5abead061285 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Tue, 12 May 2020 01:48:20 -0400 Subject: [PATCH 36/69] release version 4.0.1 with blank base path fix --- CHANGELOG.md | 5 +++++ package-lock.json | 31 +++++++++++++++++++++++-------- package.json | 2 +- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba9341dc..643319e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [4.0.1] - 2020-05-12 + +### Changed +- Fix issue updating domains that use a blank base path. Thanks @fabiancook ([#337](https://github.com/amplify-education/serverless-domain-manager/pull/337)) + ## [4.0.0] - 2020-05-06 ### Added diff --git a/package-lock.json b/package-lock.json index 27e58dec..8db9a29e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.0.0", + "version": "4.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1525,18 +1525,18 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "mocha": { @@ -1572,6 +1572,21 @@ "path-is-absolute": "^1.0.0" } }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", diff --git a/package.json b/package.json index 25e6b9dd..6c2ae3a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.0.0", + "version": "4.0.1", "engines": { "node": ">=4.0" }, From e6486411d01b6a2a382c7bf9b59687c230d73fe1 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Tue, 12 May 2020 21:05:17 -0400 Subject: [PATCH 37/69] more test clean up --- package-lock.json | 7079 ++++++++++++++++++-- package.json | 1 + test/integration-tests/integration.test.js | 128 +- test/integration-tests/test-utilities.js | 121 +- 4 files changed, 6712 insertions(+), 617 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64319084..c6d49e44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,16 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "2-thenable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/2-thenable/-/2-thenable-1.0.0.tgz", + "integrity": "sha512-HqiDzaLDFCXkcCO/SwoyhRwqYtINFHF7t9BDRq4x90TOKNAJpiqUt9X5lQ08bwxYzc067HUywDjGySpebHcUpw==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.47" + } + }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -144,507 +154,2825 @@ "to-fast-properties": "^2.0.0" } }, - "@types/chai": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", - "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", - "dev": true - }, - "@types/chai-spies": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.0.tgz", - "integrity": "sha512-Bj/froHomMnlAPEYEeqhmSuNSjTWW/VuSvCVdhLdcb67+dy4ffjTR6fC0YYw9tHP6KR3U8fkF1mgzmzlChHc5Q==", + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", "dev": true, "requires": { - "@types/chai": "*" + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" } }, - "@types/mocha": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", - "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", - "dev": true - }, - "@types/node": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.0.tgz", - "integrity": "sha512-Jrb/x3HT4PTJp6a4avhmJCDEVrPdqLfl3e8GGMbpkGGdwAV5UGlIs4vVEfsHHfylZVOKZWpOqmqFH8CbfOZ6kg==", - "dev": true - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", "dev": true, - "optional": true - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "color-convert": "^1.9.0" + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" } }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "@serverless/component-metrics": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@serverless/component-metrics/-/component-metrics-1.0.8.tgz", + "integrity": "sha512-lOUyRopNTKJYVEU9T6stp2irwlTDsYMmUKBOUjnMcwGveuUfIJqrCOtFLtIPPj3XJlbZy5F68l4KP9rZ8Ipang==", "dev": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "node-fetch": "^2.6.0", + "shortid": "^2.2.14" } }, - "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "@serverless/components": { + "version": "2.30.10", + "resolved": "https://registry.npmjs.org/@serverless/components/-/components-2.30.10.tgz", + "integrity": "sha512-F6Y9FBh7lvAyKOkctcd6qIBtGZHUu1X5HTxvrQMPK3QlzSeyPonKw5/Xh57rlyurbki0GzKtXFK6qH75ZnNUAw==", "dev": true, "requires": { - "default-require-extensions": "^2.0.0" + "@serverless/inquirer": "^1.1.0", + "@serverless/platform-client": "^0.25.7", + "@serverless/platform-client-china": "^1.0.12", + "@serverless/platform-sdk": "^2.3.0", + "adm-zip": "^0.4.14", + "ansi-escapes": "^4.3.1", + "axios": "^0.19.2", + "chalk": "^2.4.2", + "chokidar": "^3.3.1", + "dotenv": "^8.2.0", + "figures": "^3.2.0", + "fs-extra": "^8.1.0", + "globby": "^10.0.2", + "graphlib": "^2.1.8", + "https-proxy-agent": "^5.0.0", + "ini": "^1.3.5", + "js-yaml": "^3.13.1", + "minimist": "^1.2.5", + "moment": "^2.24.0", + "open": "^7.0.3", + "prettyoutput": "^1.2.0", + "ramda": "^0.26.1", + "semver": "^7.3.2", + "strip-ansi": "^5.2.0", + "traverse": "^0.6.6", + "uuid": "^3.4.0", + "ws": "^7.2.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arg": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", - "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "@serverless/core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@serverless/core/-/core-1.1.2.tgz", + "integrity": "sha512-PY7gH+7aQ+MltcUD7SRDuQODJ9Sav9HhFJsgOiyf8IVo7XVD6FxZIsSnpMI6paSkptOB7n+0Jz03gNlEkKetQQ==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "fs-extra": "^7.0.1", + "js-yaml": "^3.13.1", + "package-json": "^6.3.0", + "ramda": "^0.26.1", + "semver": "^6.1.1" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "@serverless/enterprise-plugin": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@serverless/enterprise-plugin/-/enterprise-plugin-3.6.11.tgz", + "integrity": "sha512-cnn9A9ebpdW5Q1v9FHB7nbcFHkAttcownaw2AALXIld04hrIMpR3YILa47WxdXFyvyPg0dyKT5OhEly9Cc2BMQ==", + "dev": true, + "requires": { + "@serverless/event-mocks": "^1.1.1", + "@serverless/platform-client": "^0.25.7", + "@serverless/platform-sdk": "^2.3.0", + "chalk": "^2.4.2", + "child-process-ext": "^2.1.1", + "chokidar": "^3.4.0", + "cli-color": "^2.0.0", + "dependency-tree": "^7.2.1", + "find-process": "^1.4.3", + "flat": "^5.0.0", + "fs-extra": "^8.1.0", + "iso8601-duration": "^1.2.0", + "isomorphic-fetch": "^2.2.1", + "js-yaml": "^3.13.1", + "jsonata": "^1.8.3", + "jszip": "^3.4.0", + "lodash": "^4.17.15", + "memoizee": "^0.4.14", + "moment": "^2.25.3", + "node-dir": "^0.1.17", + "node-fetch": "^2.6.0", + "regenerator-runtime": "^0.13.5", + "semver": "^6.3.0", + "simple-git": "^1.132.0", + "source-map-support": "^0.5.19", + "update-notifier": "^2.5.0", + "uuid": "^3.4.0", + "yamljs": "^0.3.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "flat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.0.tgz", + "integrity": "sha512-6KSMM+cHHzXC/hpldXApL2S8Uz+QZv+tq5o/L0KQYleoG+GcwrnIJhTWC7tCOiKQp8D/fIvryINU1OZCCwevjA==", + "dev": true, + "requires": { + "is-buffer": "~2.0.4" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "@serverless/event-mocks": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@serverless/event-mocks/-/event-mocks-1.1.1.tgz", + "integrity": "sha512-YAV5V/y+XIOfd+HEVeXfPWZb8C6QLruFk9tBivoX2roQLWVq145s4uxf8D0QioCueuRzkukHUS4JIj+KVoS34A==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "@types/lodash": "^4.14.123", + "lodash": "^4.17.11" } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { + "@serverless/inquirer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "aws-sdk": { - "version": "2.490.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.490.0.tgz", - "integrity": "sha512-8dCf+F360XEwOorTk0wVV/haaxYvUZnfZI6PVXfR8xbcVd7Ioh9KWRe+MqHNStEttE4UQzknEPrUj/mDW++NDw==", - "requires": { - "buffer": "4.9.1", - "events": "1.1.1", - "ieee754": "1.1.8", - "jmespath": "0.15.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - } - }, - "aws-sdk-mock": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws-sdk-mock/-/aws-sdk-mock-1.7.0.tgz", - "integrity": "sha1-dpizuoL0k/cf8GCuISPNCAathnY=", + "resolved": "https://registry.npmjs.org/@serverless/inquirer/-/inquirer-1.1.0.tgz", + "integrity": "sha512-MpNMmV0uADfmGF8jVQ3Vmw+cdh7vAc8Ga/N9LHDhlbWh+EVHkqlpTi6bb3Xv6WsaPlWrx55Wo389IwpbhA0nPQ==", "dev": true, "requires": { - "aws-sdk": "^2.3.0", - "sinon": "^1.17.3", + "chalk": "^3.0.0", + "inquirer": "^7.1.0", + "ncjsm": "^4.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "inquirer": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@serverless/platform-client": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-0.25.7.tgz", + "integrity": "sha512-ZOKgT49qQPGjv0tDN46INO0gkc5syL2y5t0pau5ljQPtQpJzHrUL87xRlDj3BD+4Y9QFZV1UXXNsOQZsyCBsPw==", + "dev": true, + "requires": { + "adm-zip": "^0.4.13", + "axios": "^0.19.2", + "https-proxy-agent": "^5.0.0", + "isomorphic-ws": "^4.0.1", + "js-yaml": "^3.13.1", + "jwt-decode": "^2.2.0", + "minimatch": "^3.0.4", + "querystring": "^0.2.0", + "traverse": "^0.6.6", + "ws": "^7.2.1" + } + }, + "@serverless/platform-client-china": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@serverless/platform-client-china/-/platform-client-china-1.0.12.tgz", + "integrity": "sha512-bfEunU+6cXCygTtXTGylu6c01BeN8S7uU8hbG5ZT8zGpE9ik2hIL7iHg+xIXxIsSBlzZn8cASbo0x/FXkm7//w==", + "dev": true, + "requires": { + "@serverless/utils-china": "^0.1.7", + "adm-zip": "^0.4.13", + "dotenv": "^8.2.0", + "https-proxy-agent": "^5.0.0", + "isomorphic-ws": "^4.0.1", + "js-yaml": "^3.13.1", + "jwt-decode": "^2.2.0", + "minimatch": "^3.0.4", + "querystring": "^0.2.0", + "traverse": "^0.6.6", + "urlencode": "^1.1.0", + "ws": "^7.2.1" + } + }, + "@serverless/platform-sdk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-2.3.0.tgz", + "integrity": "sha512-+9TiMYDVKJOyDWg9p/k0kmGVZ3+rjB8DXpACDxxyUChDSsRS55CTJnt321Yx7APfHctNRSnv3ubYmx7oGSTETQ==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "https-proxy-agent": "^4.0.0", + "is-docker": "^1.1.0", + "isomorphic-fetch": "^2.2.1", + "jwt-decode": "^2.2.0", + "opn": "^5.5.0", + "querystring": "^0.2.0", + "ramda": "^0.25.0", + "rc": "^1.2.8", + "regenerator-runtime": "^0.13.1", + "source-map-support": "^0.5.12", + "uuid": "^3.3.2", + "write-file-atomic": "^2.4.2", + "ws": "<7.0.0" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + }, + "ramda": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", + "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "@serverless/template": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@serverless/template/-/template-1.1.3.tgz", + "integrity": "sha512-hcMiX523rkp6kHeKnM1x6/dXEY+d1UFSr901yVKeeCgpFy4u33UI9vlKaPweAZCF6Ahzqywf01IsFTuBVadCrQ==", + "dev": true, + "requires": { + "@serverless/component-metrics": "^1.0.8", + "@serverless/core": "^1.0.0", + "graphlib": "^2.1.7", "traverse": "^0.6.6" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "@serverless/utils-china": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@serverless/utils-china/-/utils-china-0.1.7.tgz", + "integrity": "sha512-xpsokLjRK7PQtoNuA+1LxZ4whLlmAuJvtv9m9ARYtMaZhJkmlHD8cEh9Y0/uTcvzcA+pWtxRSHQ92TonpXqVow==", + "dev": true, + "requires": { + "@tencent-sdk/capi": "^0.2.15-alpha.0", + "dijkstrajs": "^1.0.1", + "dot-qs": "0.2.0", + "duplexify": "^4.1.1", + "end-of-stream": "^1.4.4", + "https-proxy-agent": "^5.0.0", + "socket.io-client": "^2.3.0", + "socket.io-stream": "^0.9.1", + "winston": "^3.2.1" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + } + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@tencent-sdk/capi": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/@tencent-sdk/capi/-/capi-0.2.15.tgz", + "integrity": "sha512-5t94Mo/+Kdvr60tJR/+pylUCwIM+ipcBIkUi4M7dtV0yCpuykOXV4GYT1aWg/iWMXyIPnfOUk4Pr6OwDoAVehw==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "querystring": "^0.2.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.8" + }, + "dependencies": { + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + } + } + }, + "@types/chai": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", + "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "dev": true + }, + "@types/chai-spies": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.0.tgz", + "integrity": "sha512-Bj/froHomMnlAPEYEeqhmSuNSjTWW/VuSvCVdhLdcb67+dy4ffjTR6fC0YYw9tHP6KR3U8fkF1mgzmzlChHc5Q==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.150", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.150.tgz", + "integrity": "sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", + "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", + "dev": true + }, + "@types/node": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.0.tgz", + "integrity": "sha512-Jrb/x3HT4PTJp6a4avhmJCDEVrPdqLfl3e8GGMbpkGGdwAV5UGlIs4vVEfsHHfylZVOKZWpOqmqFH8CbfOZ6kg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.32.0.tgz", + "integrity": "sha512-hQpbWM/Y2iq6jB9FHYJBqa3h1R9IEGodOtajhb261cVHt9cz30AKjXM6WP7LxJdEPPlyJ9rPTZVgBUgZgiyPgw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "adm-zip": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz", + "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", + "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-module-path": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", + "dev": true + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "dev": true, + "requires": { + "file-type": "^4.2.0" + }, + "dependencies": { + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true + } + } + }, + "archiver": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", + "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^2.6.3", + "buffer-crc32": "^0.2.1", + "glob": "^7.1.4", + "readable-stream": "^3.4.0", + "tar-stream": "^2.1.0", + "zip-stream": "^2.1.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", + "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-module-types": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-2.6.0.tgz", + "integrity": "sha512-zXSoVaMrf2R+r+ISid5/9a8SXm1LLdkhHzh6pSRhj9jklzruOOl1hva1YmFT33wAstg/f9ZndJAlq1BSrFLSGA==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sdk": { + "version": "2.490.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.490.0.tgz", + "integrity": "sha512-8dCf+F360XEwOorTk0wVV/haaxYvUZnfZI6PVXfR8xbcVd7Ioh9KWRe+MqHNStEttE4UQzknEPrUj/mDW++NDw==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + } + }, + "aws-sdk-mock": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws-sdk-mock/-/aws-sdk-mock-1.7.0.tgz", + "integrity": "sha1-dpizuoL0k/cf8GCuISPNCAathnY=", + "dev": true, + "requires": { + "aws-sdk": "^2.3.0", + "sinon": "^1.17.3", + "traverse": "^0.6.6" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10" + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "bl": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz", + "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true + }, + "caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "requires": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "^1.0.1", + "deep-eql": "^0.1.3", + "type-detect": "^1.0.0" + } + }, + "chai-spies": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-1.0.0.tgz", + "integrity": "sha512-elF2ZUczBsFoP07qCfMO/zeggs8pqCf3fZGyK5+2X4AndS8jycZYID91ztD9oQ7d/0tnS963dPkd0frQEThDsg==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "child-process-ext": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/child-process-ext/-/child-process-ext-2.1.1.tgz", + "integrity": "sha512-0UQ55f51JBkOFa+fvR76ywRzxiPwQS3Xe8oe5bZRphpv+dIMeerW5Zn5e4cUy4COJwVtJyU0R79RMnw+aCqmGA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.5", + "es5-ext": "^0.10.53", + "log": "^6.0.0", + "split2": "^3.1.1", + "stream-promise": "^3.2.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.0.tgz", + "integrity": "sha512-a0VZ8LeraW0jTuCkuAGMNufareGHhyZU9z8OGsW0gXd1hZGi1SRuNRXdbGkraBBKnhyUhyebFWnRbp+dIn0f0A==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "^1.0.1", + "es5-ext": "^0.10.51", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.7" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=", + "dev": true + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "dev": true + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "dev": true, + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compress-commons": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", + "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^3.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", "dev": true }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true }, - "bcrypt-pbkdf": { + "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" } }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "requires": { + "buffer": "^5.1.0" + }, + "dependencies": { + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "crc32-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-3.0.1.tgz", + "integrity": "sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "crc": "^3.4.4", + "readable-stream": "^3.4.0" } }, - "braces": { + "create-error-class": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", "dev": true, "requires": { - "fill-range": "^7.0.1" + "capture-stack-trace": "^1.0.0" } }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "es5-ext": "^0.10.50", + "type": "^1.0.1" + }, + "dependencies": { + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + } } }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dayjs": { + "version": "1.8.26", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.26.tgz", + "integrity": "sha512-KqtAuIfdNfZR5sJY1Dixr2Is4ZvcCqhb0dZpCOt5dGEFiMzoIbjkTSzUb4QKTCsP+WNpGwUjAFIZrnZvUxxkhw==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decomment": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/decomment/-/decomment-0.9.2.tgz", + "integrity": "sha512-sblyUmOJZxiL7oJ2ogJS6jtl/67+CTOW87SrYE/96u3PhDYikYoLCdLzcnceToiQejOLlqNnLCkaxx/+nE/ehg==", + "dev": true, + "requires": { + "esprima": "4.0.1" + } + }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dev": true, + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "dependencies": { + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + } + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", "dev": true, "requires": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" + "strip-bom": "^3.0.0" } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, - "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "deferred": { + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/deferred/-/deferred-0.7.11.tgz", + "integrity": "sha512-8eluCl/Blx4YOGwMapBvXRKxHXhA8ejDXYzEaK8+/gtcm8hRMhSLmXSqDmNUKNc/C8HNSmuyyp/hflhqDAvK2A==", "dev": true, "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" + "d": "^1.0.1", + "es5-ext": "^0.10.50", + "event-emitter": "^0.3.5", + "next-tick": "^1.0.0", + "timers-ext": "^0.1.7" } }, - "chai-spies": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-1.0.0.tgz", - "integrity": "sha512-elF2ZUczBsFoP07qCfMO/zeggs8pqCf3fZGyK5+2X4AndS8jycZYID91ztD9oQ7d/0tnS963dPkd0frQEThDsg==", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "object-keys": "^1.0.12" } }, - "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "dependency-tree": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/dependency-tree/-/dependency-tree-7.2.1.tgz", + "integrity": "sha512-nBxnjkqDW4LqAzBazy60V4lE0mAtIQ+oers/GIIvVvGYVdCD9+RNNd4G9jjstyz7ZFVg/j/OiYCvK5MjoVqA2w==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "commander": "^2.19.0", + "debug": "^4.1.1", + "filing-cabinet": "^2.5.1", + "precinct": "^6.2.0", + "typescript": "^3.7.5" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ms": "^2.1.1" } + }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true } } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "detective-amd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-3.0.0.tgz", + "integrity": "sha512-kOpKHyabdSKF9kj7PqYHLeHPw+TJT8q2u48tZYMkIcas28el1CYeLEJ42Nm+563/Fq060T5WknfwDhdX9+kkBQ==", + "dev": true, "requires": { - "color-name": "1.1.3" + "ast-module-types": "^2.3.1", + "escodegen": "^1.8.0", + "get-amd-module-type": "^3.0.0", + "node-source-walk": "^4.0.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "detective-cjs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-3.1.1.tgz", + "integrity": "sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "ast-module-types": "^2.4.0", + "node-source-walk": "^4.0.0" } }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "detective-es6": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-2.1.0.tgz", + "integrity": "sha512-QSHqKGOp/YBIfmIqKXaXeq2rlL+bp3bcIQMfZ+0PvKzRlELSOSZxKRvpxVcxlLuocQv4QnOfuWGniGrmPbz8MQ==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "node-source-walk": "^4.0.0" } }, - "core-util-is": { + "detective-less": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "resolved": "https://registry.npmjs.org/detective-less/-/detective-less-1.0.2.tgz", + "integrity": "sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==", + "dev": true, + "requires": { + "debug": "^4.0.0", + "gonzales-pe": "^4.2.3", + "node-source-walk": "^4.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } }, - "cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "detective-postcss": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-3.0.1.tgz", + "integrity": "sha512-tfTS2GdpUal5NY0aCqI4dpEy8Xfr88AehYKB0iBIZvo8y2g3UsrcDnrp9PR2FbzoW7xD5Rip3NJW7eCSvtqdUw==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" + "debug": "^4.1.1", + "is-url": "^1.2.4", + "postcss": "^7.0.2", + "postcss-values-parser": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "detective-sass": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-3.0.1.tgz", + "integrity": "sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw==", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "debug": "^4.1.1", + "gonzales-pe": "^4.2.3", + "node-source-walk": "^4.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "detective-scss": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-2.0.1.tgz", + "integrity": "sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ==", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "debug": "^4.1.1", + "gonzales-pe": "^4.2.3", + "node-source-walk": "^4.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "detective-stylus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-1.0.0.tgz", + "integrity": "sha1-UK7n24uruZA4HwEMY/q7pbWOVM0=", + "dev": true + }, + "detective-typescript": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-5.8.0.tgz", + "integrity": "sha512-SrsUCfCaDTF64QVMHMidRal+kmkbIc5zP8cxxZPsomWx9vuEUjBlSJNhf7/ypE5cLdJJDI4qzKDmyzqQ+iz/xg==", "dev": true, "requires": { - "ms": "^2.1.1" + "@typescript-eslint/typescript-estree": "^2.29.0", + "ast-module-types": "^2.6.0", + "node-source-walk": "^4.2.0", + "typescript": "^3.8.3" + }, + "dependencies": { + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + } } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "dev": true, + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dijkstrajs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", + "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { - "type-detect": "0.1.1" + "is-obj": "^1.0.0" + } + }, + "dot-qs": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dot-qs/-/dot-qs-0.2.0.tgz", + "integrity": "sha1-02UX/iS3zaYfznpQJqACSvr1pDk=", + "dev": true + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true + }, + "download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "dev": true, + "requires": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" }, "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "dev": true + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + } + } + }, + "file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } } } }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "duplexify": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", + "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", "dev": true, "requires": { - "strip-bom": "^3.0.0" + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" } }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "duration": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", + "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "d": "1", + "es5-ext": "~0.10.46" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -661,6 +2989,24 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "dev": true, + "requires": { + "env-variable": "0.0.x" + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -670,6 +3016,84 @@ "once": "^1.4.0" } }, + "engine.io-client": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.1.tgz", + "integrity": "sha512-RJNmA+A9Js+8Aoq815xpGAsgWH1VoSYM//2VgIiu9lNOaHFfLpTjH4tOzktBpjIs5lvOfiNY1dwf+NuU6D38Mw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", + "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "env-variable": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", + "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -709,12 +3133,95 @@ "is-symbol": "^1.0.2" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + }, + "dependencies": { + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + } + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promisify": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.1.1.tgz", + "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", + "dev": true + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -747,18 +3254,50 @@ } } }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "esniff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-1.1.0.tgz", + "integrity": "sha1-xmhJIp+RRk3t4uDUAgHtar9l8qw=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.12" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "essentials": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/essentials/-/essentials-1.1.1.tgz", + "integrity": "sha512-SmaxoAdVu86XkZQM/u6TYSu96ZlFGwhvSk1l9zAkznFuQkMb9mRDS2iq/XWDow7R8OwBwdYH8nLyDKznMD+GWw==", + "dev": true + }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -794,36 +3333,214 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + } + }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "requires": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-glob": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", + "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, + "fastq": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz", + "integrity": "sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-exists-dazinatorfork": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/file-exists-dazinatorfork/-/file-exists-dazinatorfork-1.0.2.tgz", + "integrity": "sha512-r70c72ln2YHzQINNfxDp02hAhbGkt1HffZ+Du8oetWDLjDtFja/Lm10lUaSh9e+wD+7VDvPee0b0C9SAy8pWZg==", "dev": true }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", "dev": true }, - "fast-json-stable-stringify": { + "filename-reserved-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", "dev": true }, + "filing-cabinet": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-2.5.1.tgz", + "integrity": "sha512-GWOdObzou2L0HrJUk8MpJa01q0ZOwuTwTssM2+P+ABJWEGlVWd6ueEatANFdin94/3rdkVSdqpH14VqCNqp3RA==", + "dev": true, + "requires": { + "app-module-path": "^2.2.0", + "commander": "^2.13.0", + "debug": "^4.1.1", + "decomment": "^0.9.2", + "enhanced-resolve": "^4.1.0", + "is-relative-path": "^1.0.2", + "module-definition": "^3.0.0", + "module-lookup-amd": "^6.1.0", + "resolve": "^1.11.1", + "resolve-dependency-path": "^2.0.0", + "sass-lookup": "^3.0.0", + "stylus-lookup": "^3.0.1", + "typescript": "^3.0.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -833,6 +3550,15 @@ "to-regex-range": "^5.0.1" } }, + "find": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", + "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", + "dev": true, + "requires": { + "traverse-chain": "~0.1.0" + } + }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -844,6 +3570,44 @@ "pkg-dir": "^3.0.0" } }, + "find-process": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.3.tgz", + "integrity": "sha512-+IA+AUsQCf3uucawyTwMWcY+2M3FXq3BRvw3S+j5Jvydjk31f/+NPWpYZOJs+JUs2GvxH4Yfr6Wham0ZtRLlPA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "commander": "^2.11.0", + "debug": "^2.6.8" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-requires": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-requires/-/find-requires-1.0.0.tgz", + "integrity": "sha512-UME7hNwBfzeISSFQcBEDemEEskpOjI/shPrpJM5PI4DSdn6hX0dmz+2dL70blZER2z8tSnTRL+2rfzlYgtbBoQ==", + "dev": true, + "requires": { + "es5-ext": "^0.10.49", + "esniff": "^1.1.0" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -862,6 +3626,44 @@ "is-buffer": "~2.0.3" } }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -898,12 +3700,108 @@ "samsam": "~1.1" } }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fs2": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/fs2/-/fs2-0.3.8.tgz", + "integrity": "sha512-HxOTRiFS3PqwAOmlp1mTwLA+xhQBdaP82b5aBamc/rHKFVyn4qL8YpngaAleD52PNMzBm6TsGOoU/Hq+bAfBhA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "deferred": "^0.7.11", + "es5-ext": "^0.10.53", + "event-emitter": "^0.3.5", + "ignore": "^5.1.4", + "memoizee": "^0.4.14", + "type": "^2.0.0" + } + }, "fsevents": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", @@ -917,12 +3815,43 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "get-amd-module-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz", + "integrity": "sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw==", + "dev": true, + "requires": { + "ast-module-types": "^2.3.2", + "node-source-walk": "^4.0.0" + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "requires": { + "npm-conf": "^1.1.0" + } + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -932,6 +3861,12 @@ "pump": "^3.0.0" } }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -964,18 +3899,100 @@ "is-glob": "^4.0.1" } }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "gonzales-pe": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", + "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -1048,17 +4065,113 @@ "function-bind": "^1.1.1" } }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "hasha": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", @@ -1086,6 +4199,12 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1097,17 +4216,77 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ieee754": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1124,18 +4303,178 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + } + } + }, "interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "dev": true, + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + }, + "dependencies": { + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + } + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, "is-arguments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", @@ -1169,12 +4508,64 @@ "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", "dev": true }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + }, + "dependencies": { + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + } + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-docker": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz", + "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", + "dev": true + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1202,12 +4593,82 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, "is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", @@ -1217,6 +4678,24 @@ "has": "^1.0.3" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-relative-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-relative-path/-/is-relative-path-1.0.2.tgz", + "integrity": "sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -1238,6 +4717,35 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + }, + "dependencies": { + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true + } + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1249,6 +4757,46 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "iso8601-duration": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/iso8601-duration/-/iso8601-duration-1.2.0.tgz", + "integrity": "sha512-ErTBd++b17E8nmWII1K1uZtBgD1E8RjyvwmxlCjPHNqHMD7gmcMHOw0E8Ro/6+QT4PhHRSnnMo7bxa1vFPkwhg==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "dev": true, + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + }, + "dependencies": { + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + } + } + }, + "isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "dev": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -1424,6 +4972,16 @@ "html-escaper": "^2.0.0" } }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "jmespath": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", @@ -1451,12 +5009,62 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-cycle": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-cycle/-/json-cycle-1.3.0.tgz", + "integrity": "sha512-FD/SedD78LCdSvJaOUQAXseT8oQBb5z6IVYaQaCrVUlu9zOAr1BDdKyVYQaSD/GDsAMrXpKcOyBD4LIl8nfjHw==", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-refs": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-2.1.7.tgz", + "integrity": "sha1-uesB/in16j6Sh48VrqEK04taz4k=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "graphlib": "^2.1.1", + "js-yaml": "^3.8.3", + "native-promise-only": "^0.8.1", + "path-loader": "^1.0.2", + "slash": "^1.0.0", + "uri-js": "^3.0.2" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "uri-js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", + "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + } + } + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -1469,22 +5077,231 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonata": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-1.8.3.tgz", + "integrity": "sha512-r6ztI6ohbpRo77AxBm6vMs3aHZi2L2PaakW7TCPwSkeGcuAZ/SxXGLWH2Npwqq5+YBM/fg/g0EXg/pI9HvXQ8Q==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jszip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.4.0.tgz", + "integrity": "sha512-gZAOYuPl4EhPTXT0GjhI3o+ZAz3su6EhLrKUoAivcKqyqC7laS5JEv4XWZND9BgcDcF83vI85yGbDmDR6UhrIg==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "jwt-decode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "graceful-fs": "^4.1.9" + } + }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "dev": true, + "requires": { + "colornames": "^1.1.1" + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "^4.0.0" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + } + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "lcid": { @@ -1506,6 +5323,15 @@ "type-check": "~0.3.2" } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -1542,12 +5368,64 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, + "log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log/-/log-6.0.0.tgz", + "integrity": "sha512-sxChESNYJ/EcQv8C7xpmxhtTOngoXuMEqGDAkhXBEmt3MAzM3SM/TmIBOqnMEVdrOv1+VgZoYbo6U2GemQiU4g==", + "dev": true, + "requires": { + "d": "^1.0.0", + "duration": "^0.2.2", + "es5-ext": "^0.10.49", + "event-emitter": "^0.3.5", + "sprintf-kit": "^2.0.0", + "type": "^1.0.1" + }, + "dependencies": { + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + } + } + }, "log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -1570,12 +5448,31 @@ } } }, + "logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "dev": true, + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + } + }, "lolex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", "dev": true }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -1586,6 +5483,15 @@ "yallist": "^2.1.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -1611,6 +5517,21 @@ "p-defer": "^1.0.0" } }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, "mem": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", @@ -1622,6 +5543,58 @@ "p-is-promise": "^2.0.0" } }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -1639,6 +5612,34 @@ } } }, + "merge2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "mime-db": { "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", @@ -1660,6 +5661,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1675,6 +5682,16 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -1751,12 +5768,113 @@ "integrity": "sha512-fSdhAkOEEqGMO6MgyBwFD1/NzXaPSELZuz8I0sAKbd4CJRd2LKJpUQKlyX4VST4mT2zxn7Yh+Ek9GNVZTvdAXQ==", "dev": true }, + "module-definition": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-3.3.0.tgz", + "integrity": "sha512-HTplA9xwDzH67XJFC1YvZMUElWJD28DV0dUq7lhTs+JKJamUOWA/CcYWSlhW5amJO66uWtY7XdltT+LfX0wIVg==", + "dev": true, + "requires": { + "ast-module-types": "^2.6.0", + "node-source-walk": "^4.0.0" + } + }, + "module-lookup-amd": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/module-lookup-amd/-/module-lookup-amd-6.2.0.tgz", + "integrity": "sha512-uxHCj5Pw9psZiC1znjU2qPsubt6haCSsN9m7xmIdoTciEgfxUkE1vhtDvjHPuOXEZrVJhjKgkmkP+w73rRuelQ==", + "dev": true, + "requires": { + "commander": "^2.8.1", + "debug": "^4.1.0", + "file-exists-dazinatorfork": "^1.0.2", + "find": "^0.3.0", + "requirejs": "^2.3.5", + "requirejs-config-file": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "moment": { + "version": "2.25.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz", + "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==", + "dev": true + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "dev": true + }, + "ncjsm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.0.1.tgz", + "integrity": "sha512-gxh5Sgait8HyclaulfhgetHQGyhFm00ZQqISIfqtwFVnyWJ20rk+55SUamo9n3KhM6Vk63gemKPxIDYiSV/xZw==", + "dev": true, + "requires": { + "builtin-modules": "^3.1.0", + "deferred": "^0.7.11", + "es5-ext": "^0.10.51", + "es6-set": "^0.1.5", + "find-requires": "^1.0.0", + "fs2": "^0.3.6", + "type": "^2.0.0" + }, + "dependencies": { + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + } + } + }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", @@ -1769,12 +5887,27 @@ "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", "dev": true }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", + "dev": true, + "requires": { + "minimatch": "^3.0.2" + } + }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -1793,6 +5926,21 @@ } } }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true + }, + "node-source-walk": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-4.2.0.tgz", + "integrity": "sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA==", + "dev": true, + "requires": { + "@babel/parser": "^7.0.0" + } + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -1831,6 +5979,30 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -1881,10 +6053,102 @@ } } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-hash": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", + "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==", "dev": true }, "object-inspect": { @@ -1899,6 +6163,15 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", @@ -1933,6 +6206,15 @@ "es-abstract": "^1.17.0-next.1" } }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1942,6 +6224,56 @@ "wrappy": "1" } }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=", + "dev": true + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.3.tgz", + "integrity": "sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "dependencies": { + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true + } + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -1973,12 +6305,33 @@ "mem": "^4.0.0" } }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, + "p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "dev": true, + "requires": { + "p-timeout": "^2.0.1" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -2009,6 +6362,15 @@ "p-limit": "^2.0.0" } }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -2027,6 +6389,32 @@ "release-zalgo": "^1.0.0" } }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -2037,6 +6425,30 @@ "json-parse-better-errors": "^1.0.1" } }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2049,12 +6461,28 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "path-loader": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.10.tgz", + "integrity": "sha512-CMP0v6S6z8PHeJ6NFVyVJm6WyJjIwFvyz2b0n2/4bKdS/0uZa/9sKUlYZzubrn3zuDRU0zIuEDX9DZYQ2ZI8TA==", + "dev": true, + "requires": { + "native-promise-only": "^0.8.1", + "superagent": "^3.8.3" + } + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -2078,6 +6506,12 @@ } } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2096,6 +6530,21 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -2105,12 +6554,160 @@ "find-up": "^3.0.0" } }, + "postcss": { + "version": "7.0.30", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.30.tgz", + "integrity": "sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-values-parser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz", + "integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "precinct": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/precinct/-/precinct-6.2.0.tgz", + "integrity": "sha512-BCAmnOxZzobF3H1/h/gq70pEyvX/BVLWCrzi8beFD22dqu5Z14qOghNUsI24Wg8oaTsGFcIjOGtFX5L9ttmjVg==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "debug": "^4.1.1", + "detective-amd": "^3.0.0", + "detective-cjs": "^3.1.1", + "detective-es6": "^2.0.0", + "detective-less": "^1.0.2", + "detective-postcss": "^3.0.0", + "detective-sass": "^3.0.0", + "detective-scss": "^2.0.0", + "detective-stylus": "^1.0.0", + "detective-typescript": "^5.1.1", + "module-definition": "^3.3.0", + "node-source-walk": "^4.2.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "prettyoutput": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prettyoutput/-/prettyoutput-1.2.0.tgz", + "integrity": "sha512-G2gJwLzLcYS+2m6bTAe+CcDpwak9YpcvpScI0tE4WYb2O3lEZD/YywkMNpGqsSx5wttGvh2UXaKROTKKCyM2dw==", + "dev": true, + "requires": { + "colors": "1.3.x", + "commander": "2.19.x", + "lodash": "4.17.x" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promise-queue": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", + "integrity": "sha1-L29ffA9tCBCelnZZx5uIqe1ek7Q=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -2144,11 +6741,28 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, "randomstring": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.1.5.tgz", @@ -2166,6 +6780,18 @@ } } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -2187,6 +6813,17 @@ "read-pkg": "^3.0.0" } }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", @@ -2205,6 +6842,40 @@ "resolve": "^1.1.6" } }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", + "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -2214,6 +6885,12 @@ "es6-error": "^4.0.1" } }, + "replaceall": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/replaceall/-/replaceall-0.1.6.tgz", + "integrity": "sha1-gdgax663LX9cSUKt8ml6MiBojY4=", + "dev": true + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -2282,6 +6959,23 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", + "dev": true + }, + "requirejs-config-file": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/requirejs-config-file/-/requirejs-config-file-3.1.2.tgz", + "integrity": "sha512-sdLWywcDuNz7EIOhenSbRfT4YF84nItDv90coN2htbokjmU2QeyQuSBZILQUKNksepl8UPVU+hgYySFaDxbJPQ==", + "dev": true, + "requires": { + "esprima": "^4.0.0", + "make-dir": "^2.1.0", + "stringify-object": "^3.2.1" + } + }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -2291,10 +6985,53 @@ "path-parse": "^1.0.5" } }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "resolve-dependency-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz", + "integrity": "sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, "rimraf": { @@ -2306,12 +7043,42 @@ "glob": "^7.1.3" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -2324,65 +7091,616 @@ "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", "dev": true }, + "sass-lookup": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz", + "integrity": "sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg==", + "dev": true, + "requires": { + "commander": "^2.16.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, "sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "~2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + } + }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, + "serverless": { + "version": "1.70.1", + "resolved": "https://registry.npmjs.org/serverless/-/serverless-1.70.1.tgz", + "integrity": "sha512-2HU2wVKG3FKQQax8LuZDi35NutL8Gd7wq9YPuqs/S1cnM3HNsesptxAnUzz73dtUxu8d3tkVXvlqgpKd2RN1/A==", + "dev": true, + "requires": { + "@serverless/cli": "^1.4.0", + "@serverless/components": "^2.30.10", + "@serverless/enterprise-plugin": "^3.6.11", + "archiver": "^3.1.1", + "async": "^1.5.2", + "aws-sdk": "^2.673.0", + "bluebird": "^3.7.2", + "boxen": "^3.2.0", + "cachedir": "^2.3.0", + "chalk": "^2.4.2", + "child-process-ext": "^2.1.1", + "ci-info": "^2.0.0", + "d": "^1.0.1", + "dayjs": "^1.8.26", + "decompress": "^4.2.1", + "download": "^7.1.0", + "essentials": "^1.1.1", + "fast-levenshtein": "^2.0.6", + "filesize": "^3.6.1", + "fs-extra": "^0.30.0", + "get-stdin": "^6.0.0", + "globby": "^6.1.0", + "graceful-fs": "^4.2.4", + "https-proxy-agent": "^5.0.0", + "inquirer": "^6.5.2", + "is-docker": "^1.1.0", + "is-wsl": "^2.2.0", + "js-yaml": "^3.13.1", + "json-cycle": "^1.3.0", + "json-refs": "^2.1.7", + "jwt-decode": "^2.2.0", + "lodash": "^4.17.15", + "memoizee": "^0.4.14", + "mkdirp": "^0.5.4", + "nanomatch": "^1.2.13", + "ncjsm": "^4.0.1", + "node-fetch": "^2.6.0", + "object-hash": "^2.0.3", + "p-limit": "^2.3.0", + "promise-queue": "^2.2.5", + "rc": "^1.2.8", + "replaceall": "^0.1.6", + "semver": "^5.7.1", + "semver-regex": "^2.0.0", + "stream-promise": "^3.2.0", + "tabtab": "^3.0.2", + "untildify": "^3.0.3", + "update-notifier": "^2.5.0", + "uuid": "^8.0.0", + "write-file-atomic": "^2.4.3", + "yaml-ast-parser": "0.0.43", + "yargs-parser": "^18.1.3" + }, + "dependencies": { + "@serverless/cli": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@serverless/cli/-/cli-1.4.0.tgz", + "integrity": "sha512-YqlCiYmRFeGksw6XJaXbigIDlktc7OfRuVpyPB7IZgkCJ9mUlBmvyWdwqJEQdkUz0xPTGsd4Jd/XSrwyiw1Brg==", + "dev": true, + "requires": { + "@serverless/core": "^1.0.0", + "@serverless/template": "^1.1.0", + "ansi-escapes": "^4.2.0", + "chalk": "^2.4.2", + "chokidar": "^3.0.2", + "dotenv": "^8.0.0", + "figures": "^3.0.0", + "minimist": "^1.2.0", + "prettyoutput": "^1.2.0", + "strip-ansi": "^5.2.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "aws-sdk": { + "version": "2.674.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.674.0.tgz", + "integrity": "sha512-C0hBwsA779y3xbS1AClDcsg8ZBJE+BJC4vt1eHpI2mEbr0/qIwOcR2hl1DjXyp3RwHKoa/LPOTHRSSHDq01PxA==", + "dev": true, + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + } + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shortid": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.15.tgz", + "integrity": "sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw==", + "dev": true, + "requires": { + "nanoid": "^2.1.0" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-git": { + "version": "1.132.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.132.0.tgz", + "integrity": "sha512-xauHm1YqCTom1sC9eOjfq3/9RKiUA9iPnxBbrY2DdL8l4ADMu0jjM5l5lphQP5YWNqAL2aXC/OeuQ76vHtW5fg==", + "dev": true, + "requires": { + "debug": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": ">=0.10.3 <1" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "socket.io-client": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "socket.io-stream": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/socket.io-stream/-/socket.io-stream-0.9.1.tgz", + "integrity": "sha1-QhJYMWKIuDrGk7DUPv0J1tQ6upc=", "dev": true, "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "component-bind": "~1.0.0", + "debug": "~2.2.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } } }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } }, - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", "dev": true, "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" + "sort-keys": "^1.0.0" } }, "source-map": { @@ -2395,6 +7713,19 @@ "amdefine": ">=0.0.4" } }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, "source-map-support": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", @@ -2413,6 +7744,12 @@ } } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "spawn-wrap": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", @@ -2459,12 +7796,39 @@ "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "split2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.1.1.tgz", + "integrity": "sha512-emNzr1s7ruq4N+1993yht631/JH+jaj0NYBosuKmLcq+JkGQ9MmTw1RB1fGaTCzUuseRIClrlSLHRNYGwWQ58Q==", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sprintf-kit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.0.tgz", + "integrity": "sha512-/0d2YTn8ZFVpIPAU230S9ZLF8WDkSSRWvh/UOLM7zzvkCchum1TtouRgyV8OfgOaYilSGU4lSSqzwBXJVlAwUw==", + "dev": true, + "requires": { + "es5-ext": "^0.10.46" + } + }, "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", @@ -2482,12 +7846,125 @@ "tweetnacl": "~0.14.0" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-promise": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-promise/-/stream-promise-3.2.0.tgz", + "integrity": "sha512-P+7muTGs2C8yRcgJw/PPt61q7O517tDHiwYEzMWo1GSBCcZedUMT/clz7vUNsSxFphIlJ6QUL4GexQKlfJoVtA==", + "dev": true, + "requires": { + "2-thenable": "^1.0.0", + "es5-ext": "^0.10.49", + "is-stream": "^1.1.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -2536,59 +8013,350 @@ "function-bind": "^1.1.1" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "requires": { + "is-natural-number": "^4.0.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "stylus-lookup": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-3.0.2.tgz", + "integrity": "sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg==", + "dev": true, + "requires": { + "commander": "^2.8.1", + "debug": "^4.1.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "dev": true, + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tabtab": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tabtab/-/tabtab-3.0.2.tgz", + "integrity": "sha512-jANKmUe0sIQc/zTALTBy186PoM/k6aPrh3A7p6AaAfF6WPSbTx1JYeGIGH162btpH+mmVEXln+UxwViZHO2Jhg==", + "dev": true, + "requires": { + "debug": "^4.0.1", + "es6-promisify": "^6.0.0", + "inquirer": "^6.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "untildify": "^3.0.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar-stream": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz", + "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==", + "dev": true, + "requires": { + "bl": "^4.0.1", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "dev": true }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", "dev": true }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, "requires": { - "has-flag": "^3.0.0" + "es5-ext": "~0.10.46", + "next-tick": "1" } }, - "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "os-tmpdir": "~1.0.2" } }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2622,12 +8390,33 @@ "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", "dev": true }, + "traverse-chain": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", + "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", + "dev": true + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", + "dev": true + }, "ts-node": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.1.tgz", @@ -2721,6 +8510,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -2736,6 +8531,12 @@ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + }, "typescript": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", @@ -2769,6 +8570,172 @@ } } }, + "unbzip2-stream": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz", + "integrity": "sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + }, + "dependencies": { + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", + "dev": true + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -2786,6 +8753,12 @@ } } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", @@ -2795,6 +8768,36 @@ "querystring": "0.2.0" } }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, + "urlencode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/urlencode/-/urlencode-1.1.0.tgz", + "integrity": "sha1-HyuibwE8hfATP3o61v8nMK33y7c=", + "dev": true, + "requires": { + "iconv-lite": "~0.4.11" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, "util": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/util/-/util-0.12.1.tgz", @@ -2808,6 +8811,12 @@ "safe-buffer": "^5.1.2" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -2834,6 +8843,12 @@ "extsprintf": "^1.2.0" } }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -2870,6 +8885,91 @@ } } }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, + "winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "dev": true, + "requires": { + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "dev": true, + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -2921,6 +9021,18 @@ "signal-exit": "^3.0.2" } }, + "ws": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", + "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", + "dev": true + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -2935,6 +9047,18 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -2947,6 +9071,22 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, + "yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true + }, + "yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + } + }, "yargs": { "version": "13.2.4", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", @@ -3007,11 +9147,38 @@ } } }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, "yn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", "dev": true + }, + "zip-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", + "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^2.1.1", + "readable-stream": "^3.4.0" + } } } } diff --git a/package.json b/package.json index 6f3ae5f3..fc639989 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "randomstring": "^1.1.5", "request": "^2.88.0", "request-promise-native": "^1.0.5", + "serverless": "^1.70.1", "shelljs": "^0.8.3", "ts-node": "^8.0.1", "tslint": "^5.20.1", diff --git a/test/integration-tests/integration.test.js b/test/integration-tests/integration.test.js index a2186513..63349f79 100644 --- a/test/integration-tests/integration.test.js +++ b/test/integration-tests/integration.test.js @@ -87,47 +87,38 @@ const testCases = [ }, ]; - describe("Integration Tests", function () { // eslint-disable-line func-names this.timeout(FIFTEEN_MINUTES); - describe("Domain Manager Is Enabled", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); - - itParam("${value.testDescription}", testCases, async (value) => { // eslint-disable-line no-template-curly-in-string - let restApiInfo; - if (value.createApiGateway) { - restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); - } - const created = await utilities.createResources(value.testFolder, - value.testDomain, RANDOM_STRING, true); - if (!created) { - throw new utilities.CreationError("Resources failed to create."); - } else { - const stage = await utilities.getStage(value.testDomain); - expect(stage).to.equal(value.testStage); - - const basePath = await utilities.getBasePath(value.testDomain); - expect(basePath).to.equal(value.testBasePath); - - const endpoint = await utilities.getEndpointType(value.testDomain); - expect(endpoint).to.equal(value.testEndpoint); - } + itParam("${value.testDescription}", testCases, async (value) => { // eslint-disable-line no-template-curly-in-string + let restApiInfo; + if (value.createApiGateway) { + restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); + } + try { + await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING, true); + const stage = await utilities.getStage(value.testDomain); + expect(stage).to.equal(value.testStage); + + const basePath = await utilities.getBasePath(value.testDomain); + expect(basePath).to.equal(value.testBasePath); + + const endpoint = await utilities.getEndpointType(value.testDomain); + expect(endpoint).to.equal(value.testEndpoint); + } finally { await utilities.destroyResources(value.testDomain, RANDOM_STRING); if (value.createApiGateway) { await utilities.deleteApiGatewayResources(restApiInfo.restApiId); } - }); + } }); - describe("Basepath Mapping Is Empty", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); + it("Creates a empty basepath mapping", async () => { const testName = "null-basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - it("Creates a basepath mapping", async () => { - // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. + // Perform sequence of commands to replicate basepath mapping issue + // Sleep for half a min between commands in order to avoid rate limiting. + try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); @@ -141,19 +132,17 @@ describe("Integration Tests", function () { // eslint-disable-line func-names const basePath = await utilities.getBasePath(testURL); expect(basePath).to.equal("(none)"); - + } finally { await utilities.destroyResources(testURL, RANDOM_STRING); - }); + } }); - describe("Basepath Mapping Is Set", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); + it("Creates a basepath mapping", async () => { const testName = "basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - it("Creates a basepath mapping", async () => { - // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. + // Perform sequence of commands to replicate basepath mapping issue + // Sleep for half a min between commands in order to avoid rate limiting. + try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); @@ -167,20 +156,17 @@ describe("Integration Tests", function () { // eslint-disable-line func-names const basePath = await utilities.getBasePath(testURL); expect(basePath).to.equal("api"); - + } finally { await utilities.destroyResources(testURL, RANDOM_STRING); - }); + } }); - - describe("Basepath Mapping Is Empty And Fix Works", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); + it("Creates a basepath mapping", async () => { const testName = "null-basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - it("Creates a basepath mapping", async () => { - // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. + // Perform sequence of commands to replicate basepath mapping issue + // Sleep for half a min between commands in order to avoid rate limiting. + try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); @@ -196,54 +182,42 @@ describe("Integration Tests", function () { // eslint-disable-line func-names const basePath = await utilities.getBasePath(testURL); expect(basePath).to.equal("(none)"); - + } finally { await utilities.destroyResources(testURL, RANDOM_STRING); - }); + } }); - describe("Create domain is idempotent", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); + it("Creates a domain multiple times without failure", async () => { const testName = "create-domain-idempotent"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - it("Creates a domain multiple times without failure", async () => { - let createDomainSuccess = true; - let deploySuccess; + try { await utilities.createTempDir(TEMP_DIR, testName); - createDomainSuccess = createDomainSuccess && await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); - createDomainSuccess = createDomainSuccess && await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); - createDomainSuccess = createDomainSuccess && await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); - deploySuccess = await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - expect(createDomainSuccess).to.equal(true); - expect(deploySuccess).to.equal(true); - + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { await utilities.destroyResources(testURL, RANDOM_STRING); - }); + } }); - describe("Deploy is idempotent", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); + it("Deploys multiple times without failure", async () => { const testName = "deploy-idempotent"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - - it("Deploys multiple times without failure", async () => { - let createDomainSuccess; - let deploySuccess = true; + try { await utilities.createTempDir(TEMP_DIR, testName); - createDomainSuccess = await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); - deploySuccess = deploySuccess && await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); - deploySuccess = deploySuccess && await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); await utilities.sleep(30); - deploySuccess = deploySuccess && await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - expect(createDomainSuccess).to.equal(true); - expect(deploySuccess).to.equal(true); - + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { await utilities.destroyResources(testURL, RANDOM_STRING); - }); + } }); }); diff --git a/test/integration-tests/test-utilities.js b/test/integration-tests/test-utilities.js index 3eb6edfd..865861c9 100644 --- a/test/integration-tests/test-utilities.js +++ b/test/integration-tests/test-utilities.js @@ -1,10 +1,7 @@ "use strict"; -const request = require("request-promise-native"); const aws = require("aws-sdk"); -const dns = require("dns"); const shell = require("shelljs"); -const util = require('util'); const AWS_PROFILE = process.env.AWS_PROFILE; const apiGateway = new aws.APIGateway({ @@ -29,15 +26,16 @@ function sleep(seconds) { /** * Executes given shell command. * @param cmd shell command to execute - * @returns {Promise} Resolves true if successfully executed, else false + * @returns {Promise} Resolves if successfully executed, else rejects */ async function exec(cmd) { - return new Promise((resolve) => { - shell.exec(`${cmd}`, { silent: false }, (err, stdout, stderr) => { + console.debug(`\tRunning command: ${cmd}`); + return new Promise((resolve, reject) => { + shell.exec(cmd, {silent: false}, (err, stdout, stderr) => { if (err || stderr) { - return resolve(false); + return reject(); } - return resolve(true); + return resolve(); }); }); } @@ -50,23 +48,12 @@ async function exec(cmd) { async function createTempDir(tempDir, folderName) { await exec(`rm -rf ${tempDir}`); await exec(`mkdir -p ${tempDir} && cp -R test/integration-tests/${folderName}/. ${tempDir}`); - await exec(`mkdir -p ${tempDir}/node_modules`); + await exec(`mkdir -p ${tempDir}/node_modules/.bin`); await exec(`ln -s $(pwd) ${tempDir}/node_modules/`); -} -/** - * Links current serverless-domain-manager to global node_modules in order to run tests. - * @returns {Promise} Resolves true if successfully linked, else false. - */ -async function linkPackages() { - return new Promise((resolve) => { - shell.exec("npm link serverless-domain-manager", { silent: false }, (err, stdout, stderr) => { - if (err || stderr) { - return resolve(false); - } - return resolve(true); - }); - }); + await exec(`ln -s $(pwd)/node_modules/serverless ${tempDir}/node_modules/`); + // link serverless to the bin directory so we can use $(npm bin) to get the path to serverless + await exec(`ln -s $(pwd)/node_modules/serverless/bin/serverless.js ${tempDir}/node_modules/.bin/serverless`); } /** @@ -148,92 +135,62 @@ async function deleteApiGatewayResources(restApiId) { * Runs `sls create_domain` for the given folder * @param tempDir * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise} + * @returns {Promise} */ function slsCreateDomain(tempDir, domainIdentifier) { - return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && serverless create_domain --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { - if (err || stderr) { - return resolve(false); - } - return resolve(true); - }); - }); + return exec(`cd ${tempDir} && $(npm bin)/serverless create_domain --RANDOM_STRING ${domainIdentifier}`); } /** * Runs `sls deploy` for the given folder * @param tempDir * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise} + * @returns {Promise} */ function slsDeploy(tempDir, domainIdentifier) { - return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && serverless deploy --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { - if (err || stderr) { - return resolve(false); - } - return resolve(true); - }); - }); + return exec(`cd ${tempDir} && $(npm bin)/serverless deploy --RANDOM_STRING ${domainIdentifier}`); } /** * Runs `sls delete_domain` for the given folder * @param tempDir * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise} + * @returns {Promise} */ function slsDeleteDomain(tempDir, domainIdentifier) { - return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && serverless delete_domain --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { - if (err || stderr) { - return resolve(false); - } - return resolve(true); - }); - }); + return exec(`cd ${tempDir} && $(npm bin)/serverless delete_domain --RANDOM_STRING ${domainIdentifier}`); } /** * Runs `sls remove` for the given folder * @param tempDir * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise} + * @returns {Promise} */ function slsRemove(tempDir, domainIdentifier) { - return new Promise((resolve) => { - shell.exec(`cd ${tempDir} && serverless remove --RANDOM_STRING ${domainIdentifier}`, { silent: false }, (err, stdout, stderr) => { - if (err || stderr) { - return resolve(false); - } - return resolve(true); - }); - }); + return exec(`cd ${tempDir} && $(npm bin)/serverless remove --RANDOM_STRING ${domainIdentifier}`); } /** * Runs both `sls create_domain` and `sls deploy` * @param tempDir * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise<*>} + * @returns {Promise} */ async function deployLambdas(tempDir, domainIdentifier) { - const created = await slsCreateDomain(tempDir, domainIdentifier); - const deployed = await slsDeploy(tempDir, domainIdentifier); - return created && deployed; + await slsCreateDomain(tempDir, domainIdentifier); + await slsDeploy(tempDir, domainIdentifier); } /** * Runs both `sls delete_domain` and `sls remove` * @param tempDir temp directory where code is being run from * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise<*>} + * @returns {Promise} */ async function removeLambdas(tempDir, domainIdentifier) { - const removed = await slsRemove(tempDir, domainIdentifier); - const deleted = await slsDeleteDomain(tempDir, domainIdentifier); - return deleted && removed; + await slsRemove(tempDir, domainIdentifier); + await slsDeleteDomain(tempDir, domainIdentifier); } /** @@ -242,39 +199,38 @@ async function removeLambdas(tempDir, domainIdentifier) { * @param url * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. * @param enabled - * @returns {Promise} Resolves true if resources created, else false. + * @returns {Promise} Resolves if successfully executed, else rejects */ async function createResources(folderName, url, domainIdentifier, enabled) { console.debug(`\tCreating Resources for ${url}`); // eslint-disable-line no-console const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; console.debug(`\tUsing tmp directory ${tempDir}`); - await createTempDir(tempDir, folderName); // eslint-disable-line no-console - const created = await deployLambdas(tempDir, domainIdentifier); - if (created) { + try { + await createTempDir(tempDir, folderName); // eslint-disable-line no-console + await deployLambdas(tempDir, domainIdentifier); console.debug("\tResources Created"); // eslint-disable-line no-console - } else { + } catch(e) { console.debug("\tResources Failed to Create"); // eslint-disable-line no-console } - return created; } /** * Wraps deletion of testing resources. * @param url * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @returns {Promise} Resolves true if resources destroyed, else false. + * @returns {Promise} Resolves if successfully executed, else rejects */ async function destroyResources(url, domainIdentifier) { - console.debug(`\tCleaning Up Resources for ${url}`); // eslint-disable-line no-console - const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; - const removed = await removeLambdas(tempDir, domainIdentifier); - await exec(`rm -rf ${tempDir}`); - if (removed) { + try { + console.debug(`\tCleaning Up Resources for ${url}`); // eslint-disable-line no-console + const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; + await removeLambdas(tempDir, domainIdentifier); + await exec(`rm -rf ${tempDir}`); + console.debug("\tResources Cleaned Up"); // eslint-disable-line no-console - } else { + } catch (e) { console.debug("\tFailed to Clean Up Resources"); // eslint-disable-line no-console } - return removed; } module.exports = { @@ -286,12 +242,9 @@ module.exports = { slsDeploy, slsDeleteDomain, slsRemove, - deployLambdas, - removeLambdas, getEndpointType, getBasePath, getStage, - linkPackages, sleep, CreationError, setupApiGatewayResources, From 99f2b48b43725fb7d544400bc0e2071ca336abd7 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Thu, 14 May 2020 01:22:23 -0400 Subject: [PATCH 38/69] switch integration tests to typescript --- README.md | 2 +- package.json | 6 +- test/integration-tests/integration.test.js | 223 ----------------- test/integration-tests/integration.test.ts | 229 ++++++++++++++++++ .../{test-utilities.js => test-utilities.ts} | 25 +- test/unit-tests/index.test.ts | 3 +- tsconfig.json | 5 +- tsconfig.tests.json | 17 ++ tslint.json | 5 +- 9 files changed, 270 insertions(+), 245 deletions(-) delete mode 100644 test/integration-tests/integration.test.js create mode 100644 test/integration-tests/integration.test.ts rename test/integration-tests/{test-utilities.js => test-utilities.ts} (91%) create mode 100644 tsconfig.tests.json diff --git a/README.md b/README.md index 702d32e9..b70408ad 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ npm install ``` ## Writing Integration Tests -Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `integration.test.js`. +Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `integration.test.ts`. ## Changing API Types AWS API Gateway has three different API types: REST, HTTP, and WebSocket. Special steps need to be taken when migrating from one api type to another. A common migration will be from a REST API to an HTTP API given the potential cost savings. Below are the steps required to change from REST to HTTP. A similar process can be applied for other API type migrations. diff --git a/package.json b/package.json index fc639989..56a16402 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,9 @@ "main": "dist/index.js", "bin": {}, "scripts": { - "test": "tsc --project . && nyc mocha -r ts-node/register test/unit-tests/index.test.ts && nyc report --reporter=text-summary", - "integration-test": "node ./node_modules/istanbul/lib/cli.js test _mocha test/integration-tests -- -R spec", - "lint": "tslint --project .", + "test": "nyc mocha -r ts-node/register --project tsconfig.tests.json test/unit-tests/index.test.ts && nyc report --reporter=text-summary", + "integration-test": "nyc mocha -r ts-node/register --project tsconfig.tests.json test/integration-tests/integration.test.ts && nyc report --reporter=text-summary", + "lint": "tslint --project . && tslint --project tsconfig.tests.json", "build": "tsc --project ." }, "files": [ diff --git a/test/integration-tests/integration.test.js b/test/integration-tests/integration.test.js deleted file mode 100644 index 63349f79..00000000 --- a/test/integration-tests/integration.test.js +++ /dev/null @@ -1,223 +0,0 @@ -"use strict"; - -const chai = require("chai"); -const itParam = require("mocha-param"); -const utilities = require("./test-utilities"); -const randomstring = require("randomstring"); - -const expect = chai.expect; - -const TEST_DOMAIN = process.env.TEST_DOMAIN; -if(!TEST_DOMAIN) { - throw new Error("TEST_DOMAIN environment variable not set") -} - -const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds -const RANDOM_STRING = randomstring.generate({ - length: 5, - charset: "alphanumeric", - capitalization: "lowercase", -}); -const TEMP_DIR = `~/tmp/domain-manager-test-${RANDOM_STRING}`; - -const testCases = [ - { - testDescription: "Enabled with default values", - testFolder: "enabled-default", - testDomain: `enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "dev", - testBasePath: "(none)", - testEndpoint: "EDGE", - testURL: `https://enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, - }, - { - testDescription: "Enabled with custom api gateway", - testFolder: "enabled-custom-apigateway", - testDomain: `enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "dev", - testBasePath: "(none)", - testEndpoint: "EDGE", - testURL: `https://enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, - createApiGateway: true, - }, - { - testDescription: "Enabled with custom basepath", - testFolder: "enabled-basepath", - testDomain: `enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "dev", - testBasePath: "api", - testEndpoint: "EDGE", - testURL: `https://enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/api/hello-world`, - }, - { - testDescription: "Enabled with custom stage and empty basepath", - testFolder: "enabled-stage-basepath", - testDomain: `enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "test", - testBasePath: "(none)", - testEndpoint: "EDGE", - testURL: `https://enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, - }, - { - testDescription: "Enabled with regional endpoint, custom basePath", - testFolder: "enabled-regional-basepath", - testDomain: `enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "dev", - testBasePath: "api", - testEndpoint: "REGIONAL", - testURL: `https://enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/api/hello-world`, - }, - { - testDescription: "Enabled with regional endpoint, custom stage, empty basepath", - testFolder: "enabled-regional-stage-basepath", - testDomain: `enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "test", - testBasePath: "(none)", - testEndpoint: "REGIONAL", - testURL: `https://enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, - }, - { - testDescription: "Enabled with regional endpoint and empty basepath", - testFolder: "enabled-regional-empty-basepath", - testDomain: `enabled-regional-empty-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testStage: "dev", - testBasePath: "(none)", - testEndpoint: "REGIONAL", - testURL: `https://enabled-regional-empty-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, - }, -]; - -describe("Integration Tests", function () { // eslint-disable-line func-names - this.timeout(FIFTEEN_MINUTES); - - itParam("${value.testDescription}", testCases, async (value) => { // eslint-disable-line no-template-curly-in-string - let restApiInfo; - if (value.createApiGateway) { - restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); - } - try { - await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING, true); - const stage = await utilities.getStage(value.testDomain); - expect(stage).to.equal(value.testStage); - - const basePath = await utilities.getBasePath(value.testDomain); - expect(basePath).to.equal(value.testBasePath); - - const endpoint = await utilities.getEndpointType(value.testDomain); - expect(endpoint).to.equal(value.testEndpoint); - } finally { - await utilities.destroyResources(value.testDomain, RANDOM_STRING); - if (value.createApiGateway) { - await utilities.deleteApiGatewayResources(restApiInfo.restApiId); - } - } - }); - - it("Creates a empty basepath mapping", async () => { - const testName = "null-basepath-mapping"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Creates a basepath mapping", async () => { - const testName = "basepath-mapping"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("api"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Creates a basepath mapping", async () => { - const testName = "null-basepath-mapping"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Creates a domain multiple times without failure", async () => { - const testName = "create-domain-idempotent"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Deploys multiple times without failure", async () => { - const testName = "deploy-idempotent"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); -}); diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts new file mode 100644 index 00000000..8d0fe803 --- /dev/null +++ b/test/integration-tests/integration.test.ts @@ -0,0 +1,229 @@ +import chai = require("chai"); +import "mocha"; +import itParam = require("mocha-param"); +import randomstring = require("randomstring"); +import utilities = require("./test-utilities"); + +const expect = chai.expect; + +const TEST_DOMAIN = process.env.TEST_DOMAIN; + +if (!TEST_DOMAIN) { + throw new Error("TEST_DOMAIN environment variable not set"); +} + +const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds +const RANDOM_STRING = randomstring.generate({ + capitalization: "lowercase", + charset: "alphanumeric", + length: 5, +}); +const TEMP_DIR = `~/tmp/domain-manager-test-${RANDOM_STRING}`; + +const testCases = [ + { + testBasePath: "(none)", + testDescription: "Enabled with default values", + testDomain: `enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: "enabled-default", + testStage: "dev", + testURL: `https://enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, + }, + { + createApiGateway: true, + testBasePath: "(none)", + testDescription: "Enabled with custom api gateway", + testDomain: `enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: "enabled-custom-apigateway", + testStage: "dev", + testURL: `https://enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, + }, + { + testBasePath: "api", + testDescription: "Enabled with custom basepath", + testDomain: `enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: "enabled-basepath", + testStage: "dev", + testURL: `https://enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/api/hello-world`, + }, + { + testBasePath: "(none)", + testDescription: "Enabled with custom stage and empty basepath", + testDomain: `enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: "enabled-stage-basepath", + testStage: "test", + testURL: `https://enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, + }, + { + testBasePath: "api", + testDescription: "Enabled with regional endpoint, custom basePath", + testDomain: `enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: "enabled-regional-basepath", + testStage: "dev", + testURL: `https://enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/api/hello-world`, + }, + { + testBasePath: "(none)", + testDescription: "Enabled with regional endpoint, custom stage, empty basepath", + testDomain: `enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: "enabled-regional-stage-basepath", + testStage: "test", + testURL: `https://enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, + }, + { + testBasePath: "(none)", + testDescription: "Enabled with regional endpoint and empty basepath", + testDomain: `enabled-regional-empty-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: "enabled-regional-empty-basepath", + testStage: "dev", + testURL: `https://enabled-regional-empty-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, + }, +]; + +describe("Integration Tests", function() { + this.timeout(FIFTEEN_MINUTES); + + describe("Configuration Tests", () => { + itParam("${value.testDescription}", testCases, async (value) => { + let restApiInfo; + if (value.createApiGateway) { + restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); + } + try { + await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING, true); + const stage = await utilities.getStage(value.testDomain); + expect(stage).to.equal(value.testStage); + + const basePath = await utilities.getBasePath(value.testDomain); + expect(basePath).to.equal(value.testBasePath); + + const endpoint = await utilities.getEndpointType(value.testDomain); + expect(endpoint).to.equal(value.testEndpoint); + } finally { + await utilities.destroyResources(value.testDomain, RANDOM_STRING); + if (value.createApiGateway) { + await utilities.deleteApiGatewayResources(restApiInfo.restApiId); + } + } + }); + }); + + describe("Basepath mapping issue tests", () => { + it("Creates a empty basepath mapping", async () => { + const testName = "null-basepath-mapping"; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + // Sleep for half a min between commands in order to avoid rate limiting. + try { + await utilities.createTempDir(TEMP_DIR, testName); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("(none)"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Delete domain then recreate", async () => { + const testName = "basepath-mapping"; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + // Sleep for half a min between commands in order to avoid rate limiting. + try { + await utilities.createTempDir(TEMP_DIR, testName); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("api"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Delete domain then remove", async () => { + const testName = "null-basepath-mapping"; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + // Sleep for half a min between commands in order to avoid rate limiting. + try { + await utilities.createTempDir(TEMP_DIR, testName); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("(none)"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + }); + + describe("Idempotency tests", () => { + it("Creates a domain multiple times without failure", async () => { + const testName = "create-domain-idempotent"; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + try { + await utilities.createTempDir(TEMP_DIR, testName); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Deploys multiple times without failure", async () => { + const testName = "deploy-idempotent"; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + try { + await utilities.createTempDir(TEMP_DIR, testName); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.sleep(30); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + }); +}); diff --git a/test/integration-tests/test-utilities.js b/test/integration-tests/test-utilities.ts similarity index 91% rename from test/integration-tests/test-utilities.js rename to test/integration-tests/test-utilities.ts index 865861c9..ed7155a6 100644 --- a/test/integration-tests/test-utilities.js +++ b/test/integration-tests/test-utilities.ts @@ -1,19 +1,18 @@ "use strict"; -const aws = require("aws-sdk"); -const shell = require("shelljs"); +import aws = require("aws-sdk"); +import shell = require("shelljs"); const AWS_PROFILE = process.env.AWS_PROFILE; const apiGateway = new aws.APIGateway({ - region: "us-west-2", credentials: new aws.SharedIniFileCredentials( { profile: AWS_PROFILE }, ), + region: "us-west-2", }); class CreationError extends Error {} - /** * Stops event thread execution for given number of seconds. * @param seconds @@ -202,15 +201,15 @@ async function removeLambdas(tempDir, domainIdentifier) { * @returns {Promise} Resolves if successfully executed, else rejects */ async function createResources(folderName, url, domainIdentifier, enabled) { - console.debug(`\tCreating Resources for ${url}`); // eslint-disable-line no-console + console.debug(`\tCreating Resources for ${url}`); const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; console.debug(`\tUsing tmp directory ${tempDir}`); try { - await createTempDir(tempDir, folderName); // eslint-disable-line no-console + await createTempDir(tempDir, folderName); await deployLambdas(tempDir, domainIdentifier); - console.debug("\tResources Created"); // eslint-disable-line no-console - } catch(e) { - console.debug("\tResources Failed to Create"); // eslint-disable-line no-console + console.debug("\tResources Created"); + } catch (e) { + console.debug("\tResources Failed to Create"); } } @@ -222,18 +221,18 @@ async function createResources(folderName, url, domainIdentifier, enabled) { */ async function destroyResources(url, domainIdentifier) { try { - console.debug(`\tCleaning Up Resources for ${url}`); // eslint-disable-line no-console + console.debug(`\tCleaning Up Resources for ${url}`); const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; await removeLambdas(tempDir, domainIdentifier); await exec(`rm -rf ${tempDir}`); - console.debug("\tResources Cleaned Up"); // eslint-disable-line no-console + console.debug("\tResources Cleaned Up"); } catch (e) { - console.debug("\tFailed to Clean Up Resources"); // eslint-disable-line no-console + console.debug("\tFailed to Clean Up Resources"); } } -module.exports = { +export { createResources, createTempDir, destroyResources, diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 803a2e61..72c372d7 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -3,11 +3,10 @@ import * as AWS from "aws-sdk-mock"; import chai = require("chai"); import spies = require("chai-spies"); import "mocha"; -import DomainInfo = require("../../DomainInfo"); import DomainConfig = require("../../DomainConfig"); +import DomainInfo = require("../../DomainInfo"); import Globals from "../../Globals"; import ServerlessCustomDomain = require("../../index"); -import { ServerlessInstance, ServerlessOptions } from "../../types"; const expect = chai.expect; chai.use(spies); diff --git a/tsconfig.json b/tsconfig.json index babfb254..c07f20b8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,9 +9,10 @@ "types": ["node"] }, "include": [ - "*.ts" + "**/*.ts" ], "exclude": [ - "node_modules" + "node_modules", + "test" ] } diff --git a/tsconfig.tests.json b/tsconfig.tests.json new file mode 100644 index 00000000..962b5022 --- /dev/null +++ b/tsconfig.tests.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "rootDir": ".", + "target": "es6", + "sourceMap": false, + "outDir": "dist", + "types": ["mocha", "node"] + }, + "include": [ + "test/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tslint.json b/tslint.json index 78af2344..534cb941 100644 --- a/tslint.json +++ b/tslint.json @@ -1,3 +1,6 @@ { - "extends": "tslint:recommended" + "extends": "tslint:recommended", + "rules": { + "no-console": false + } } From 83f44417af8a7e6b809d85b6d811401b88d9abd3 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Thu, 14 May 2020 02:07:40 -0400 Subject: [PATCH 39/69] add websocket and http api tests --- test/integration-tests/http-api/handler.js | 16 ++++++++++++ .../integration-tests/http-api/serverless.yml | 25 +++++++++++++++++++ test/integration-tests/integration.test.ts | 21 ++++++++-------- test/integration-tests/test-utilities.ts | 7 ++---- test/integration-tests/web-socket/handler.js | 9 +++++++ .../web-socket/serverless.yml | 24 ++++++++++++++++++ 6 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 test/integration-tests/http-api/handler.js create mode 100644 test/integration-tests/http-api/serverless.yml create mode 100644 test/integration-tests/web-socket/handler.js create mode 100644 test/integration-tests/web-socket/serverless.yml diff --git a/test/integration-tests/http-api/handler.js b/test/integration-tests/http-api/handler.js new file mode 100644 index 00000000..1bd222d6 --- /dev/null +++ b/test/integration-tests/http-api/handler.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports.helloWorld = (event, context, callback) => { + const response = { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin": "*", // Required for CORS support to work + }, + body: JSON.stringify({ + message: "Go Serverless v1.0! Your function executed successfully!", + input: event, + }), + }; + + callback(null, response); +}; diff --git a/test/integration-tests/http-api/serverless.yml b/test/integration-tests/http-api/serverless.yml new file mode 100644 index 00000000..74903b96 --- /dev/null +++ b/test/integration-tests/http-api/serverless.yml @@ -0,0 +1,25 @@ +service: http-api-${opt:RANDOM_STRING} +provider: + name: aws + runtime: nodejs12.x + region: us-west-2 + stage: dev +functions: + helloWorld: + handler: handler.connect + events: + - httpApi: + method: GET + path: /hello-world +plugins: + - serverless-domain-manager +custom: + customDomain: + http: + domainName: http-api-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + basePath: '' + endpointType: 'regional' + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index 8d0fe803..fe7c2e2a 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -28,7 +28,6 @@ const testCases = [ testEndpoint: "EDGE", testFolder: "enabled-default", testStage: "dev", - testURL: `https://enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, }, { createApiGateway: true, @@ -38,7 +37,6 @@ const testCases = [ testEndpoint: "EDGE", testFolder: "enabled-custom-apigateway", testStage: "dev", - testURL: `https://enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, }, { testBasePath: "api", @@ -47,7 +45,6 @@ const testCases = [ testEndpoint: "EDGE", testFolder: "enabled-basepath", testStage: "dev", - testURL: `https://enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/api/hello-world`, }, { testBasePath: "(none)", @@ -56,7 +53,6 @@ const testCases = [ testEndpoint: "EDGE", testFolder: "enabled-stage-basepath", testStage: "test", - testURL: `https://enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, }, { testBasePath: "api", @@ -65,7 +61,6 @@ const testCases = [ testEndpoint: "REGIONAL", testFolder: "enabled-regional-basepath", testStage: "dev", - testURL: `https://enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/api/hello-world`, }, { testBasePath: "(none)", @@ -74,17 +69,23 @@ const testCases = [ testEndpoint: "REGIONAL", testFolder: "enabled-regional-stage-basepath", testStage: "test", - testURL: `https://enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, }, { testBasePath: "(none)", - testDescription: "Enabled with regional endpoint and empty basepath", - testDomain: `enabled-regional-empty-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testDescription: "Create Web socket API and domain name", + testDomain: `web-socket-${RANDOM_STRING}.${TEST_DOMAIN}`, testEndpoint: "REGIONAL", - testFolder: "enabled-regional-empty-basepath", + testFolder: "web-socket", testStage: "dev", - testURL: `https://enabled-regional-empty-basepath-${RANDOM_STRING}.${TEST_DOMAIN}/hello-world`, }, + { + testBasePath: "(none)", + testDescription: "Create HTTP API and domain name", + testDomain: `http-api-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: "http-api", + testStage: "$default", + } ]; describe("Integration Tests", function() { diff --git a/test/integration-tests/test-utilities.ts b/test/integration-tests/test-utilities.ts index ed7155a6..8e4ec1e5 100644 --- a/test/integration-tests/test-utilities.ts +++ b/test/integration-tests/test-utilities.ts @@ -11,14 +11,12 @@ const apiGateway = new aws.APIGateway({ region: "us-west-2", }); -class CreationError extends Error {} - /** * Stops event thread execution for given number of seconds. * @param seconds - * @returns {Promise} Resolves after given number of seconds. + * @returns {Promise} Resolves after given number of seconds. */ -function sleep(seconds) { +async function sleep(seconds) { return new Promise((resolve) => setTimeout(resolve, 1000 * seconds)); } @@ -245,7 +243,6 @@ export { getBasePath, getStage, sleep, - CreationError, setupApiGatewayResources, deleteApiGatewayResources, }; diff --git a/test/integration-tests/web-socket/handler.js b/test/integration-tests/web-socket/handler.js new file mode 100644 index 00000000..9d807dd4 --- /dev/null +++ b/test/integration-tests/web-socket/handler.js @@ -0,0 +1,9 @@ +"use strict"; + +module.exports.connect = (event, context, callback) => { + const response = { + statusCode: 200, + }; + + callback(null, response); +}; diff --git a/test/integration-tests/web-socket/serverless.yml b/test/integration-tests/web-socket/serverless.yml new file mode 100644 index 00000000..d004cb5a --- /dev/null +++ b/test/integration-tests/web-socket/serverless.yml @@ -0,0 +1,24 @@ +service: web-socket-${opt:RANDOM_STRING} +provider: + name: aws + runtime: nodejs12.x + region: us-west-2 + stage: dev +functions: + connect: + handler: handler.connect + events: + - websocket: + route: $connect +plugins: + - serverless-domain-manager +custom: + customDomain: + websocket: + domainName: web-socket-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + basePath: '' + endpointType: 'regional' + +package: + exclude: + - node_modules/** From 9c5ac1cea955e2d74509a1530db74c2ab79a456a Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Thu, 14 May 2020 23:13:42 -0400 Subject: [PATCH 40/69] fix lint error --- test/integration-tests/integration.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index fe7c2e2a..65e5f33d 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -85,7 +85,7 @@ const testCases = [ testEndpoint: "REGIONAL", testFolder: "http-api", testStage: "$default", - } + }, ]; describe("Integration Tests", function() { From 9264bc62b3d73fe339d734a2b19bd8aa49c21673 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Fri, 15 May 2020 01:06:16 -0400 Subject: [PATCH 41/69] move code to the src directory I think this makes it easier to maintain and is more consistent with other typescript projects --- DomainConfig.ts => src/DomainConfig.ts | 0 DomainInfo.ts => src/DomainInfo.ts | 0 Globals.ts => src/Globals.ts | 0 index.ts => src/index.ts | 0 types.ts => src/types.ts | 0 test/unit-tests/index.test.ts | 8 ++++---- tsconfig.json | 8 ++------ tsconfig.tests.json | 4 +--- 8 files changed, 7 insertions(+), 13 deletions(-) rename DomainConfig.ts => src/DomainConfig.ts (100%) rename DomainInfo.ts => src/DomainInfo.ts (100%) rename Globals.ts => src/Globals.ts (100%) rename index.ts => src/index.ts (100%) rename types.ts => src/types.ts (100%) diff --git a/DomainConfig.ts b/src/DomainConfig.ts similarity index 100% rename from DomainConfig.ts rename to src/DomainConfig.ts diff --git a/DomainInfo.ts b/src/DomainInfo.ts similarity index 100% rename from DomainInfo.ts rename to src/DomainInfo.ts diff --git a/Globals.ts b/src/Globals.ts similarity index 100% rename from Globals.ts rename to src/Globals.ts diff --git a/index.ts b/src/index.ts similarity index 100% rename from index.ts rename to src/index.ts diff --git a/types.ts b/src/types.ts similarity index 100% rename from types.ts rename to src/types.ts diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 72c372d7..75dc2bca 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -3,10 +3,10 @@ import * as AWS from "aws-sdk-mock"; import chai = require("chai"); import spies = require("chai-spies"); import "mocha"; -import DomainConfig = require("../../DomainConfig"); -import DomainInfo = require("../../DomainInfo"); -import Globals from "../../Globals"; -import ServerlessCustomDomain = require("../../index"); +import DomainConfig = require("../../src/DomainConfig"); +import DomainInfo = require("../../src/DomainInfo"); +import Globals from "../../src/Globals"; +import ServerlessCustomDomain = require("../../src/index"); const expect = chai.expect; chai.use(spies); diff --git a/tsconfig.json b/tsconfig.json index c07f20b8..10e94eea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,17 +2,13 @@ "compilerOptions": { "module": "commonjs", "moduleResolution": "node", - "rootDir": ".", + "rootDir": "src", "target": "es6", "sourceMap": false, "outDir": "dist", "types": ["node"] }, "include": [ - "**/*.ts" - ], - "exclude": [ - "node_modules", - "test" + "src/**/*.ts" ] } diff --git a/tsconfig.tests.json b/tsconfig.tests.json index 962b5022..f80adfec 100644 --- a/tsconfig.tests.json +++ b/tsconfig.tests.json @@ -9,9 +9,7 @@ "types": ["mocha", "node"] }, "include": [ + "src/**/*.ts", "test/**/*.ts" - ], - "exclude": [ - "node_modules" ] } From 7274e99f72be297d38f0ab88cacc1c66afdbde10 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Fri, 15 May 2020 02:11:02 -0400 Subject: [PATCH 42/69] add utility function for doing paging and use it for ACM certs and API mappings --- package.json | 2 +- src/index.ts | 71 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 56a16402..e0b49ae3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.0.1", + "version": "4.1.0", "engines": { "node": ">=4.0" }, diff --git a/src/index.ts b/src/index.ts index c1004eb5..aab27f6d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ "use strict"; +import {Service} from "aws-sdk"; import chalk from "chalk"; import DomainConfig = require("./DomainConfig"); import DomainInfo = require("./DomainInfo"); @@ -315,14 +316,14 @@ class ServerlessCustomDomain { let certificateName = domain.certificateName; // The certificate name try { - let certificates = []; - let nextToken; - do { - const certData = await this.acm.listCertificates( - { CertificateStatuses: certStatuses, NextToken: nextToken }).promise(); - certificates = certificates.concat(certData.CertificateSummaryList); - nextToken = certData.NextToken; - } while (nextToken); + const certificates = await this.getAWSPagedResults( + this.acm, + "listCertificates", + "CertificateSummaryList", + "NextToken", + "NextToken", + { CertificateStatuses: certStatuses }, + ); // The more specific name will be the longest let nameLength = 0; @@ -555,20 +556,19 @@ class ServerlessCustomDomain { } public async getBasePathMapping(domain: DomainConfig): Promise { - const params = { - DomainName: domain.givenDomainName, - }; try { - const mappings = await this.apigatewayV2.getApiMappings(params).promise(); - - if (mappings.Items.length === 0) { - return; - } else { - for (const mapping of mappings.Items) { - if (mapping.ApiId === domain.apiId - || (mapping.ApiMappingKey === domain.basePath && domain.allowPathMatching) ) { - return mapping; - } + const mappings = await this.getAWSPagedResults( + this.apigatewayV2, + "getApiMappings", + "Items", + "NextToken", + "NextToken", + { DomainName: domain.givenDomainName }, + ); + for (const mapping of mappings) { + if (mapping.ApiId === domain.apiId + || (mapping.ApiMappingKey === domain.basePath && domain.allowPathMatching) ) { + return mapping; } } } catch (err) { @@ -786,6 +786,35 @@ class ServerlessCustomDomain { this.serverless.cli.consoleLog(` Target Domain: ${domain.domainInfo.domainName}`); this.serverless.cli.consoleLog(` Hosted Zone Id: ${domain.domainInfo.hostedZoneId}`); } + + /** + * Iterate through the pages of a AWS SDK response and collect them into a single array + * + * @param service - The AWS service instance to use to make the calls + * @param funcName - The function name in the service to call + * @param resultsKey - The key name in the response that contains the items to return + * @param nextTokenKey - The request key name to append to the request that has the paging token value + * @param nextRequestTokenKey - The response key name that has the next paging token value + * @param params - Parameters to send in the request + */ + private async getAWSPagedResults( + service: Service, + funcName: string, + resultsKey: string, + nextTokenKey: string, + nextRequestTokenKey: string, + params: object, + ): Promise { + let results = []; + let response = await service[funcName](params).promise(); + results = results.concat(response[resultsKey]); + while (response.hasOwnProperty(nextRequestTokenKey) && response[nextRequestTokenKey]) { + params[nextTokenKey] = response[nextRequestTokenKey]; + response = await service[funcName](params).promise(); + results = results.concat(response[resultsKey]); + } + return results; + } } export = ServerlessCustomDomain; From f4caf0859461a2d9b0702b481db828eaa4451b2c Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Fri, 15 May 2020 13:01:24 -0400 Subject: [PATCH 43/69] remove unused file --- test/unit-tests/tslint.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 test/unit-tests/tslint.json diff --git a/test/unit-tests/tslint.json b/test/unit-tests/tslint.json deleted file mode 100644 index f7bb7a71..00000000 --- a/test/unit-tests/tslint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "tslint:recommended" -} From 73cd8c9ecb112c76c364c5eaa9f9115558486f57 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Fri, 15 May 2020 15:15:55 -0400 Subject: [PATCH 44/69] update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 643319e2..5b056aae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [4.1.0] - 2020-05-15 + +### Changed +- Fixed issue when there are multiple pages of base path mappings. Also refactored how paging is handled throughout the code. Thanks @kzhou57 for discovering this ([#345](https://github.com/amplify-education/serverless-domain-manager/pull/345)) + ## [4.0.1] - 2020-05-12 ### Changed From 08a565876c10db70930b08925b1f371d9587edb1 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Fri, 15 May 2020 16:32:19 -0400 Subject: [PATCH 45/69] simplify test utils --- test/integration-tests/test-utilities.ts | 42 +++++++++--------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/test/integration-tests/test-utilities.ts b/test/integration-tests/test-utilities.ts index 8e4ec1e5..6012a355 100644 --- a/test/integration-tests/test-utilities.ts +++ b/test/integration-tests/test-utilities.ts @@ -56,52 +56,40 @@ async function createTempDir(tempDir, folderName) { /** * Gets endpoint type of given URL from AWS * @param url - * @returns {Promise} Resolves to String if endpoint exists, else null. + * @returns {Promise} */ async function getEndpointType(url) { - const params = { + const result = await apiGateway.getDomainName({ domainName: url, - }; - try { - const result = await apiGateway.getDomainName(params).promise(); - return result.endpointConfiguration.types[0]; - } catch (err) { - return null; - } + }).promise(); + + return result.endpointConfiguration.types[0]; } /** * Gets stage of given URL from AWS * @param url - * @returns {Promise} Resolves to String if stage exists, else null. + * @returns {Promise} */ async function getStage(url) { - const params = { + const result = await apiGateway.getBasePathMappings({ domainName: url, - }; - try { - const result = await apiGateway.getBasePathMappings(params).promise(); - return result.items[0].stage; - } catch (err) { - return null; - } + }).promise(); + + return result.items[0].stage; } /** * Gets basePath of given URL from AWS * @param url - * @returns {Promise} Resolves to String if basePath exists, else null. + * @returns {Promise} */ async function getBasePath(url) { - const params = { + const result = await apiGateway.getBasePathMappings({ domainName: url, - }; - try { - const result = await apiGateway.getBasePathMappings(params).promise(); - return result.items[0].basePath; - } catch (err) { - return null; - } + }).promise(); + + return result.items[0].basePath; } /** From e2d3004ba6aa0ac71d19bb2443319c4516a65951 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Mon, 18 May 2020 01:48:19 -0400 Subject: [PATCH 46/69] add unit test --- src/index.ts | 28 ++++++++++++++-------------- test/unit-tests/index.test.ts | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/index.ts b/src/index.ts index aab27f6d..d4e5802e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -774,19 +774,6 @@ class ServerlessCustomDomain { } } - /** - * Prints out a summary of all domain manager related info - */ - - private printDomainSummary(domain: DomainConfig): void { - this.serverless.cli.consoleLog(chalk.yellow.underline("\nServerless Domain Manager Summary")); - - this.serverless.cli.consoleLog(chalk.yellow("Distribution Domain Name")); - this.serverless.cli.consoleLog(` Domain Name: ${domain.givenDomainName}`); - this.serverless.cli.consoleLog(` Target Domain: ${domain.domainInfo.domainName}`); - this.serverless.cli.consoleLog(` Hosted Zone Id: ${domain.domainInfo.hostedZoneId}`); - } - /** * Iterate through the pages of a AWS SDK response and collect them into a single array * @@ -797,7 +784,7 @@ class ServerlessCustomDomain { * @param nextRequestTokenKey - The response key name that has the next paging token value * @param params - Parameters to send in the request */ - private async getAWSPagedResults( + public async getAWSPagedResults( service: Service, funcName: string, resultsKey: string, @@ -815,6 +802,19 @@ class ServerlessCustomDomain { } return results; } + + /** + * Prints out a summary of all domain manager related info + */ + + private printDomainSummary(domain: DomainConfig): void { + this.serverless.cli.consoleLog(chalk.yellow.underline("\nServerless Domain Manager Summary")); + + this.serverless.cli.consoleLog(chalk.yellow("Distribution Domain Name")); + this.serverless.cli.consoleLog(` Domain Name: ${domain.givenDomainName}`); + this.serverless.cli.consoleLog(` Target Domain: ${domain.domainInfo.domainName}`); + this.serverless.cli.consoleLog(` Hosted Zone Id: ${domain.domainInfo.hostedZoneId}`); + } } export = ServerlessCustomDomain; diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 75dc2bca..6c34e4a1 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -1478,4 +1478,39 @@ describe("Custom Domain Plugin", () => { consoleOutput = []; }); }); + + describe("AWS paged results", () => { + it("Should combine paged results into a list", async () => { + let callCount = 0; + const responses = [{ + Items: ["a", "b"], + NextToken: "1", + }, + { + Items: ["c", "d"], + NextToken: "2", + }, + { + Items: ["e"], + }, + { + Items: ["f"], // this call should never happen since its after the last request that included a token + }]; + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { + callback(null, responses[callCount++]); + }); + + const plugin = constructPlugin({}); + const results = await plugin.getAWSPagedResults( + new aws.ApiGatewayV2(), + "getApiMappings", + "Items", + "NextToken", + "NextToken", + { DomainName: "example.com"}, + ); + expect(results).to.deep.equal([ "a", "b", "c", "d", "e" ]); + AWS.restore(); + }); + }); }); From 0dc1ede15f71faecceb5596276a5c60dc71af315 Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Mon, 18 May 2020 01:48:42 -0400 Subject: [PATCH 47/69] update date in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b056aae..daac6ae1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [4.1.0] - 2020-05-15 +## [4.1.0] - 2020-05-18 ### Changed - Fixed issue when there are multiple pages of base path mappings. Also refactored how paging is handled throughout the code. Thanks @kzhou57 for discovering this ([#345](https://github.com/amplify-education/serverless-domain-manager/pull/345)) From 3293c3d9d032ca29da0dd0acefef374014912216 Mon Sep 17 00:00:00 2001 From: Hunter Date: Wed, 20 May 2020 14:41:12 -0500 Subject: [PATCH 48/69] better naming --- src/index.ts | 4 ++-- test/unit-tests/index.test.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8106295c..9d7a4fc1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -54,7 +54,7 @@ class ServerlessCustomDomain { this.hooks = { "after:deploy:deploy": this.hookWrapper.bind(this, this.setupBasePathMappings), "after:info:info": this.hookWrapper.bind(this, this.domainSummaries), - "before:deploy:deploy": this.hookWrapper.bind(this, this.updateCloudFormationOutputs), + "before:deploy:deploy": this.hookWrapper.bind(this, this.createOrGetDomainForCfOutputs), "before:remove:remove": this.hookWrapper.bind(this, this.removeBasePathMappings), "create_domain:create": this.hookWrapper.bind(this, this.createDomains), "delete_domain:delete": this.hookWrapper.bind(this, this.deleteDomains), @@ -131,7 +131,7 @@ class ServerlessCustomDomain { /** * Lifecycle function to createDomain before deploy and add domain info to the CloudFormation stack's Outputs */ - public async updateCloudFormationOutputs(): Promise { + public async createOrGetDomainForCfOutputs(): Promise { const autoDomain = this.serverless.service.custom.customDomain.autoDomain; if (autoDomain === true) { this.serverless.cli.log("Creating domain name before deploy."); diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index e8767a05..2c3cdd8a 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -1522,7 +1522,7 @@ describe("Custom Domain Plugin", () => { expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(undefined); }); - it("updateCloudFormationOutputs should call createDomain when autoDomain is true", async () => { + it("createOrGetDomainForCfOutputs should call createDomain when autoDomain is true", async () => { AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { callback(null, params); }); @@ -1543,13 +1543,13 @@ describe("Custom Domain Plugin", () => { const spy = chai.spy.on(plugin.apigatewayV2, "getDomainName"); - await plugin.updateCloudFormationOutputs(); + await plugin.createOrGetDomainForCfOutputs(); expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); expect(spy).to.have.been.called(); }); - it("updateCloudFormationOutputs should not call createDomain when autoDomain is not true", async () => { + it("createOrGetDomainForCfOutputs should not call createDomain when autoDomain is not true", async () => { AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { callback(null, params); }); @@ -1572,7 +1572,7 @@ describe("Custom Domain Plugin", () => { const spy1 = chai.spy.on(plugin.apigateway, "createDomainName"); const spy2 = chai.spy.on(plugin.apigatewayV2, "createDomainName"); - await plugin.updateCloudFormationOutputs(); + await plugin.createOrGetDomainForCfOutputs(); expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); expect(spy1).to.have.not.been.called(); From 88a558e30ea9905480bc664f2fde565045d04cff Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Mon, 25 May 2020 15:23:51 -0400 Subject: [PATCH 49/69] Fix support for regional domains using TLS 1.0 (#348) * Fix support for regional domains using TLS 1.0 * fix lint * add unit test * update changelog * check if existing domain is tls 1.0 instead of config * fix lint errors * update release date : --- CHANGELOG.md | 8 +++ package-lock.json | 2 +- package.json | 2 +- src/index.ts | 28 +++++--- test/integration-tests/integration.test.ts | 8 +++ .../regional-tls-1-0/handler.js | 16 +++++ .../regional-tls-1-0/serverless.yml | 28 ++++++++ test/unit-tests/index.test.ts | 64 ++++++++++++++++++- 8 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 test/integration-tests/regional-tls-1-0/handler.js create mode 100644 test/integration-tests/regional-tls-1-0/serverless.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index daac6ae1..708a1448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [4.1.1] - 2020-05-25 + +### Changed +- Fix support for TLS 1.0 regional domains which were broken in the 4.0.0 release. Discovered by @jufemaiz ([#348](https://github.com/amplify-education/serverless-domain-manager/pull/348)) + ## [4.1.0] - 2020-05-18 ### Changed @@ -16,6 +21,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [4.0.0] - 2020-05-06 +### Breaking Changes +- Regional domains with TLS 1.0 no longer work. Fixed in 4.1.1 + ### Added - Add support for WebSocket and HTTP APIs. A domain name can be created for each API type (Rest, WebSocket, HTTP) for up to 3 domain names in a single Serverless config. Thanks @TehNrd ([#319](https://github.com/amplify-education/serverless-domain-manager/pull/319)) diff --git a/package-lock.json b/package-lock.json index c6d49e44..c2947526 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.0.1", + "version": "4.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e0b49ae3..76e1aaf3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.1.0", + "version": "4.1.1", "engines": { "node": ">=4.0" }, diff --git a/src/index.ts b/src/index.ts index d4e5802e..5e3d2854 100644 --- a/src/index.ts +++ b/src/index.ts @@ -152,14 +152,14 @@ class ServerlessCustomDomain { domain.apiMapping = await this.getBasePathMapping(domain); + await this.getDomainInfo(); + if (!domain.apiMapping) { await this.createBasePathMapping(domain); } else { await this.updateBasePathMapping(domain); } - await this.getDomainInfo(); - } catch (err) { this.logIfDebug(err, domain.givenDomainName); throw new Error(`Error: Unable to setup base domain mappings for ${domain.givenDomainName}`); @@ -390,11 +390,10 @@ class ServerlessCustomDomain { let createdDomain = {}; - // For EDGE domain name, create with APIGateway (v1) - if (domain.endpointType === Globals.endpointTypes.edge) { + // For EDGE domain name or TLS 1.0, create with APIGateway (v1) + if (domain.endpointType === Globals.endpointTypes.edge || domain.securityPolicy === "TLS_1_0") { // Set up parameters const params = { - certificateArn: domain.certificateArn, domainName: domain.givenDomainName, endpointConfiguration: { types: [domain.endpointType], @@ -402,6 +401,14 @@ class ServerlessCustomDomain { securityPolicy: domain.securityPolicy, }; + /* tslint:disable:no-string-literal */ + if (domain.endpointType === Globals.endpointTypes.edge) { + params["certificateArn"] = domain.certificateArn; + } else { + params["regionalCertificateArn"] = domain.certificateArn; + } + /* tslint:enable:no-string-literal */ + // Make API call to create domain try { // Creating EDGE domain so use APIGateway (v1) service @@ -581,8 +588,8 @@ class ServerlessCustomDomain { * Creates basepath mapping */ public async createBasePathMapping(domain: DomainConfig): Promise { - // Use APIGateway (v1) for EDGE domains - if (domain.endpointType === Globals.endpointTypes.edge) { + // Use APIGateway (v1) for EDGE or TLS 1.0 domains + if (domain.endpointType === Globals.endpointTypes.edge || domain.securityPolicy === "TLS_1_0") { const params = { basePath: domain.basePath, domainName: domain.givenDomainName, @@ -620,8 +627,11 @@ class ServerlessCustomDomain { * Updates basepath mapping */ public async updateBasePathMapping(domain: DomainConfig): Promise { - // Use APIGateway (v1) for EDGE domains - if (domain.endpointType === Globals.endpointTypes.edge) { + // Use APIGateway (v1) for EDGE or TLS 1.0 domains + // check here if the EXISTING domain is using TLS 1.0 regardless of what is configured + // We don't support updating custom domains so switching from TLS 1.0 to 1.2 will require recreating + // the domain + if (domain.endpointType === Globals.endpointTypes.edge || domain.domainInfo.securityPolicy === "TLS_1_0") { const params = { basePath: domain.apiMapping.ApiMappingKey || "(none)", domainName: domain.givenDomainName, diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index 65e5f33d..0ee9b7e7 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -86,6 +86,14 @@ const testCases = [ testFolder: "http-api", testStage: "$default", }, + { + testBasePath: "(none)", + testDescription: "Deploy regional domain with TLS 1.0", + testDomain: `regional-tls-1-0-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: "regional-tls-1-0", + testStage: "dev", + }, ]; describe("Integration Tests", function() { diff --git a/test/integration-tests/regional-tls-1-0/handler.js b/test/integration-tests/regional-tls-1-0/handler.js new file mode 100644 index 00000000..1bd222d6 --- /dev/null +++ b/test/integration-tests/regional-tls-1-0/handler.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports.helloWorld = (event, context, callback) => { + const response = { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin": "*", // Required for CORS support to work + }, + body: JSON.stringify({ + message: "Go Serverless v1.0! Your function executed successfully!", + input: event, + }), + }; + + callback(null, response); +}; diff --git a/test/integration-tests/regional-tls-1-0/serverless.yml b/test/integration-tests/regional-tls-1-0/serverless.yml new file mode 100644 index 00000000..fc1219d3 --- /dev/null +++ b/test/integration-tests/regional-tls-1-0/serverless.yml @@ -0,0 +1,28 @@ +# Test regional domains with TLS 1.0 +service: regional-tls-1-0-${opt:RANDOM_STRING} +provider: + name: aws + runtime: nodejs12.x + region: us-west-2 + stage: dev + endpointType: regional + +functions: + helloWorld: + handler: handler.helloWorld + events: + - http: + path: hello-world + method: get + cors: true +plugins: + - serverless-domain-manager +custom: + customDomain: + domainName: regional-tls-1-0-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + securityPolicy: tls_1_0 + endpointType: regional + +package: + exclude: + - node_modules/** diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 6c34e4a1..34133b21 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -189,6 +189,61 @@ describe("Custom Domain Plugin", () => { }); }); + it("Creates basepath mapping for regional tls 1.0 REST api", async () => { + AWS.mock("APIGateway", "createBasePathMapping", (params, callback) => { + callback(null, params); + }); + const plugin = constructPlugin({ + basePath: "test_basepath", + domainName: "test_domain", + endpointType: "regional", + securityPolicy: "tls_1_0", + }); + plugin.initializeVariables(); + plugin.apigateway = new aws.APIGateway(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + dc.apiId = "test_rest_api_id"; + + const spy = chai.spy.on(plugin.apigateway, "createBasePathMapping"); + + await plugin.createBasePathMapping(dc); + + expect(spy).to.have.been.called.with({ + basePath: "test_basepath", + domainName: "test_domain", + restApiId: "test_rest_api_id", + stage: "test", + }); + }); + + it("Creates basepath mapping for regional tls 1.2 REST api", async () => { + AWS.mock("ApiGatewayV2", "createApiMapping", (params, callback) => { + callback(null, params); + }); + const plugin = constructPlugin({ + basePath: "test_basepath", + domainName: "test_domain", + endpointType: "regional", + }); + plugin.initializeVariables(); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + + const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); + dc.apiId = "test_rest_api_id"; + + const spy = chai.spy.on(plugin.apigatewayV2, "createApiMapping"); + + await plugin.createBasePathMapping(dc); + + expect(spy).to.have.been.called.with({ + ApiId: "test_rest_api_id", + ApiMappingKey: "test_basepath", + DomainName: "test_domain", + Stage: "test", + }); + }); + it("Creates basepath mapping for regional HTTP/Websocket api", async () => { AWS.mock("ApiGatewayV2", "createApiMapping", (params, callback) => { callback(null, params); @@ -264,8 +319,15 @@ describe("Custom Domain Plugin", () => { plugin.apigatewayV2 = new aws.ApiGatewayV2(); const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); - dc.apiId = "test_api_id", + dc.apiId = "test_api_id"; dc.apiMapping = {ApiMappingId: "test_mapping_id"}; + dc.domainInfo = new DomainInfo({ + DomainNameConfigurations: [{ + ApiGatewayDomainName: "fake_dist_name", + HostedZoneId: "fake_zone_id", + SecurityPolicy: "TLS_1_2", + }], + }); const spy = chai.spy.on(plugin.apigatewayV2, "updateApiMapping"); From 33271fcb3b1a68c92cb70eb126564c5e4301857b Mon Sep 17 00:00:00 2001 From: Alex Oskotsky Date: Tue, 26 May 2020 22:03:11 -0400 Subject: [PATCH 50/69] Add throttledCall function (#350) Switch to using a custom backoff function instead of depending on the built in backoff in the AWS client. This allows us to retry for only certain types of exceptions and increase the number of times it retries to avoid getting throttle errors --- src/index.ts | 64 +++++------------ src/utils.ts | 81 ++++++++++++++++++++++ test/integration-tests/integration.test.ts | 22 ------ test/integration-tests/test-utilities.ts | 10 --- test/unit-tests/index.test.ts | 3 +- 5 files changed, 101 insertions(+), 79 deletions(-) create mode 100644 src/utils.ts diff --git a/src/index.ts b/src/index.ts index 5e3d2854..9cb2a5c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,11 @@ "use strict"; -import {Service} from "aws-sdk"; import chalk from "chalk"; import DomainConfig = require("./DomainConfig"); import DomainInfo = require("./DomainInfo"); import Globals from "./Globals"; import { ServerlessInstance, ServerlessOptions } from "./types"; +import {getAWSPagedResults, throttledCall} from "./utils"; const certStatuses = ["PENDING_VALIDATION", "ISSUED", "INACTIVE"]; @@ -234,7 +234,6 @@ class ServerlessCustomDomain { const credentials = this.serverless.providers.aws.getCredentials(); credentials.region = this.serverless.providers.aws.getRegion(); - this.serverless.providers.aws.sdk.config.update({ maxRetries: 20 }); this.apigateway = new this.serverless.providers.aws.sdk.APIGateway(credentials); this.apigatewayV2 = new this.serverless.providers.aws.sdk.ApiGatewayV2(credentials); this.route53 = new this.serverless.providers.aws.sdk.Route53(credentials); @@ -316,7 +315,7 @@ class ServerlessCustomDomain { let certificateName = domain.certificateName; // The certificate name try { - const certificates = await this.getAWSPagedResults( + const certificates = await getAWSPagedResults( this.acm, "listCertificates", "CertificateSummaryList", @@ -368,9 +367,9 @@ class ServerlessCustomDomain { public async getDomainInfo(): Promise { await Promise.all(this.domains.map(async (domain) => { try { - const domainInfo = await this.apigatewayV2.getDomainName({ + const domainInfo = await throttledCall(this.apigatewayV2, "getDomainName", { DomainName: domain.givenDomainName, - }).promise(); + }); domain.domainInfo = new DomainInfo(domainInfo); } catch (err) { @@ -412,7 +411,7 @@ class ServerlessCustomDomain { // Make API call to create domain try { // Creating EDGE domain so use APIGateway (v1) service - createdDomain = await this.apigateway.createDomainName(params).promise(); + createdDomain = await throttledCall(this.apigateway, "createDomainName", params); domain.domainInfo = new DomainInfo(createdDomain); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -432,7 +431,7 @@ class ServerlessCustomDomain { // Make API call to create domain try { // Creating Regional domain so use ApiGatewayV2 - createdDomain = await this.apigatewayV2.createDomainName(params).promise(); + createdDomain = await throttledCall(this.apigatewayV2, "createDomainName", params); domain.domainInfo = new DomainInfo(createdDomain); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -447,7 +446,9 @@ class ServerlessCustomDomain { public async deleteCustomDomain(domain: DomainConfig): Promise { // Make API call try { - await this.apigatewayV2.deleteDomainName({DomainName: domain.givenDomainName}).promise(); + await throttledCall(this.apigatewayV2, "deleteDomainName", { + DomainName: domain.givenDomainName, + }); } catch (err) { this.logIfDebug(err, domain.givenDomainName); throw new Error(`Error: Failed to delete custom domain ${domain.givenDomainName}\n`); @@ -493,7 +494,7 @@ class ServerlessCustomDomain { }; // Make API call try { - await this.route53.changeResourceRecordSets(params).promise(); + await throttledCall(this.route53, "changeResourceRecordSets", params); } catch (err) { this.logIfDebug(err, domain.givenDomainName); throw new Error(`Error: Failed to ${action} A Alias for ${domain.givenDomainName}\n`); @@ -521,7 +522,7 @@ class ServerlessCustomDomain { const givenDomainNameReverse = domain.givenDomainName.split(".").reverse(); try { - hostedZoneData = await this.route53.listHostedZones({}).promise(); + hostedZoneData = await throttledCall(this.route53, "listHostedZones", {}); const targetHostedZone = hostedZoneData.HostedZones .filter((hostedZone) => { let hostedZoneName; @@ -564,7 +565,7 @@ class ServerlessCustomDomain { public async getBasePathMapping(domain: DomainConfig): Promise { try { - const mappings = await this.getAWSPagedResults( + const mappings = await getAWSPagedResults( this.apigatewayV2, "getApiMappings", "Items", @@ -598,7 +599,7 @@ class ServerlessCustomDomain { }; // Make API call try { - await this.apigateway.createBasePathMapping(params).promise(); + await throttledCall(this.apigateway, "createBasePathMapping", params); this.serverless.cli.log(`Created API mapping '${domain.basePath}' for ${domain.givenDomainName}`); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -614,7 +615,7 @@ class ServerlessCustomDomain { }; // Make API call try { - await this.apigatewayV2.createApiMapping(params).promise(); + await throttledCall(this.apigatewayV2, "createApiMapping", params); this.serverless.cli.log(`Created API mapping '${domain.basePath}' for ${domain.givenDomainName}`); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -646,7 +647,7 @@ class ServerlessCustomDomain { // Make API call try { - await this.apigateway.updateBasePathMapping(params).promise(); + await throttledCall(this.apigateway, "updateBasePathMapping", params); this.serverless.cli.log(`Updated API mapping from '${domain.apiMapping.ApiMappingKey}' to '${domain.basePath}' for ${domain.givenDomainName}`); } catch (err) { @@ -666,7 +667,7 @@ class ServerlessCustomDomain { // Make API call try { - await this.apigatewayV2.updateApiMapping(params).promise(); + await throttledCall(this.apigatewayV2, "updateApiMapping", params); this.serverless.cli.log(`Updated API mapping to '${domain.basePath}' for ${domain.givenDomainName}`); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -702,7 +703,7 @@ class ServerlessCustomDomain { let response; try { - response = await this.cloudformation.describeStackResource(params).promise(); + response = await throttledCall(this.cloudformation, "describeStackResource", params); } catch (err) { this.logIfDebug(err, domain.givenDomainName); throw new Error(`Error: Failed to find CloudFormation resources for ${domain.givenDomainName}\n`); @@ -726,7 +727,7 @@ class ServerlessCustomDomain { // Make API call try { - await this.apigatewayV2.deleteApiMapping(params).promise(); + await throttledCall(this.apigatewayV2, "deleteApiMapping", params); this.serverless.cli.log("Removed basepath mapping."); } catch (err) { this.logIfDebug(err, domain.givenDomainName); @@ -784,35 +785,6 @@ class ServerlessCustomDomain { } } - /** - * Iterate through the pages of a AWS SDK response and collect them into a single array - * - * @param service - The AWS service instance to use to make the calls - * @param funcName - The function name in the service to call - * @param resultsKey - The key name in the response that contains the items to return - * @param nextTokenKey - The request key name to append to the request that has the paging token value - * @param nextRequestTokenKey - The response key name that has the next paging token value - * @param params - Parameters to send in the request - */ - public async getAWSPagedResults( - service: Service, - funcName: string, - resultsKey: string, - nextTokenKey: string, - nextRequestTokenKey: string, - params: object, - ): Promise { - let results = []; - let response = await service[funcName](params).promise(); - results = results.concat(response[resultsKey]); - while (response.hasOwnProperty(nextRequestTokenKey) && response[nextRequestTokenKey]) { - params[nextTokenKey] = response[nextRequestTokenKey]; - response = await service[funcName](params).promise(); - results = results.concat(response[resultsKey]); - } - return results; - } - /** * Prints out a summary of all domain manager related info */ diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..ce960381 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,81 @@ +import {Service} from "aws-sdk"; + +const RETRYABLE_ERRORS = ["Throttling", "RequestLimitExceeded", "TooManyRequestsException"]; + +/** + * Iterate through the pages of a AWS SDK response and collect them into a single array + * + * @param service - The AWS service instance to use to make the calls + * @param funcName - The function name in the service to call + * @param resultsKey - The key name in the response that contains the items to return + * @param nextTokenKey - The request key name to append to the request that has the paging token value + * @param nextRequestTokenKey - The response key name that has the next paging token value + * @param params - Parameters to send in the request + */ +async function getAWSPagedResults( + service: Service, + funcName: string, + resultsKey: string, + nextTokenKey: string, + nextRequestTokenKey: string, + params: object, +): Promise { + let results = []; + let response = await throttledCall(service, funcName, params); + results = results.concat(response[resultsKey]); + while (response.hasOwnProperty(nextRequestTokenKey) && response[nextRequestTokenKey]) { + params[nextTokenKey] = response[nextRequestTokenKey]; + response = await service[funcName](params).promise(); + results = results.concat(response[resultsKey]); + } + return results; +} + +async function throttledCall(service: Service, funcName: string, params: object): Promise { + const maxTimePassed = 5 * 60; + + let timePassed = 0; + let previousInterval = 0; + + const minWait = 3; + const maxWait = 60; + + while (true) { + try { + return await service[funcName](params).promise(); + } catch (ex) { + // rethrow the exception if it is not a type of retryable exception + if (RETRYABLE_ERRORS.indexOf(ex.code) === -1) { + throw ex; + } + + // rethrow the exception if we have waited too long + if (timePassed >= maxTimePassed) { + throw ex; + } + + // Sleep using the Decorrelated Jitter algorithm recommended by AWS + // https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ + let newInterval = Math.random() * Math.min(maxWait, previousInterval * 3); + newInterval = Math.max(minWait, newInterval); + + await sleep(newInterval); + previousInterval = newInterval; + timePassed += previousInterval; + } + } +} + +/** + * Stops event thread execution for given number of seconds. + * @param seconds + * @returns {Promise} Resolves after given number of seconds. + */ +async function sleep(seconds) { + return new Promise((resolve) => setTimeout(resolve, 1000 * seconds)); +} + +export { + getAWSPagedResults, + throttledCall, +}; diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index 0ee9b7e7..6b52c88a 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -129,17 +129,12 @@ describe("Integration Tests", function() { const testName = "null-basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); const basePath = await utilities.getBasePath(testURL); @@ -153,17 +148,12 @@ describe("Integration Tests", function() { const testName = "basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); const basePath = await utilities.getBasePath(testURL); @@ -177,19 +167,13 @@ describe("Integration Tests", function() { const testName = "null-basepath-mapping"; const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; // Perform sequence of commands to replicate basepath mapping issue - // Sleep for half a min between commands in order to avoid rate limiting. try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); const basePath = await utilities.getBasePath(testURL); @@ -207,11 +191,8 @@ describe("Integration Tests", function() { try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); } finally { await utilities.destroyResources(testURL, RANDOM_STRING); @@ -224,11 +205,8 @@ describe("Integration Tests", function() { try { await utilities.createTempDir(TEMP_DIR, testName); await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.sleep(30); await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); } finally { await utilities.destroyResources(testURL, RANDOM_STRING); diff --git a/test/integration-tests/test-utilities.ts b/test/integration-tests/test-utilities.ts index 6012a355..6ab0fa43 100644 --- a/test/integration-tests/test-utilities.ts +++ b/test/integration-tests/test-utilities.ts @@ -11,15 +11,6 @@ const apiGateway = new aws.APIGateway({ region: "us-west-2", }); -/** - * Stops event thread execution for given number of seconds. - * @param seconds - * @returns {Promise} Resolves after given number of seconds. - */ -async function sleep(seconds) { - return new Promise((resolve) => setTimeout(resolve, 1000 * seconds)); -} - /** * Executes given shell command. * @param cmd shell command to execute @@ -230,7 +221,6 @@ export { getEndpointType, getBasePath, getStage, - sleep, setupApiGatewayResources, deleteApiGatewayResources, }; diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 34133b21..e8412b31 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -7,6 +7,7 @@ import DomainConfig = require("../../src/DomainConfig"); import DomainInfo = require("../../src/DomainInfo"); import Globals from "../../src/Globals"; import ServerlessCustomDomain = require("../../src/index"); +import {getAWSPagedResults} from "../../src/utils"; const expect = chai.expect; chai.use(spies); @@ -1563,7 +1564,7 @@ describe("Custom Domain Plugin", () => { }); const plugin = constructPlugin({}); - const results = await plugin.getAWSPagedResults( + const results = await getAWSPagedResults( new aws.ApiGatewayV2(), "getApiMappings", "Items", From f3c84470624850acf70df2c6469b76704250ac1a Mon Sep 17 00:00:00 2001 From: Max Countryman Date: Thu, 28 May 2020 09:11:40 -0700 Subject: [PATCH 51/69] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b70408ad..60082ff2 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ custom: apiType: rest ``` -Multiple API types mapped to different domains can also be supported with the follow structure. The key is the API Gateway API type. +Multiple API types mapped to different domains can also be supported with the following structure. The key is the API Gateway API type. ```yaml custom: From 3fbe9fef5ad366b507e94c7172cf012a2c54d674 Mon Sep 17 00:00:00 2001 From: Isaac Levy Date: Mon, 1 Jun 2020 08:17:28 -0400 Subject: [PATCH 52/69] fix typo (bath -> path) --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 9cb2a5c7..40bd6787 100644 --- a/src/index.ts +++ b/src/index.ts @@ -195,7 +195,7 @@ class ServerlessCustomDomain { API Mappings may need to be manually removed.`, "Serverless Domain Manager"); } else { this.logIfDebug(err, domain.givenDomainName); - this.serverless.cli.log(`Error: Unable to remove base bath mappings + this.serverless.cli.log(`Error: Unable to remove base path mappings for domain ${domain.givenDomainName}`); } } From a8179c3d97b09fc1d504f99983cf0f5e33724349 Mon Sep 17 00:00:00 2001 From: Johnathan Constance Date: Tue, 2 Jun 2020 15:55:03 -0400 Subject: [PATCH 53/69] Revert "add autoDomain option to config" --- README.md | 2 - src/index.ts | 17 +--- src/types.ts | 1 - test/unit-tests/index.test.ts | 168 ---------------------------------- 4 files changed, 4 insertions(+), 184 deletions(-) diff --git a/README.md b/README.md index bc522c8a..60082ff2 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,6 @@ custom: endpointType: 'regional' securityPolicy: tls_1_2 apiType: rest - autoDomain: false ``` Multiple API types mapped to different domains can also be supported with the following structure. The key is the API Gateway API type. @@ -120,7 +119,6 @@ custom: | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| allowPathMatching | false | When updating an existing api mapping this will match on the basePath instead of the API ID to find existing mappings for an upsate. This should only be used when changing API types. For example, migrating a REST API to an HTTP API. See Changing API Types for more information. | -| autoDomain | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | ## Running diff --git a/src/index.ts b/src/index.ts index 0c69972c..40bd6787 100644 --- a/src/index.ts +++ b/src/index.ts @@ -54,7 +54,7 @@ class ServerlessCustomDomain { this.hooks = { "after:deploy:deploy": this.hookWrapper.bind(this, this.setupBasePathMappings), "after:info:info": this.hookWrapper.bind(this, this.domainSummaries), - "before:deploy:deploy": this.hookWrapper.bind(this, this.createOrGetDomainForCfOutputs), + "before:deploy:deploy": this.hookWrapper.bind(this, this.updateCloudFormationOutputs), "before:remove:remove": this.hookWrapper.bind(this, this.removeBasePathMappings), "create_domain:create": this.hookWrapper.bind(this, this.createDomains), "delete_domain:delete": this.hookWrapper.bind(this, this.deleteDomains), @@ -83,6 +83,7 @@ class ServerlessCustomDomain { await Promise.all(this.domains.map(async (domain) => { try { if (!domain.domainInfo) { + domain.certificateArn = await this.getCertArn(domain); await this.createCustomDomain(domain); @@ -129,14 +130,9 @@ class ServerlessCustomDomain { } /** - * Lifecycle function to createDomain before deploy and add domain info to the CloudFormation stack's Outputs + * Lifecycle function to add domain info to the CloudFormation stack's Outputs */ - public async createOrGetDomainForCfOutputs(): Promise { - const autoDomain = this.serverless.service.custom.customDomain.autoDomain; - if (autoDomain === true) { - this.serverless.cli.log("Creating domain name before deploy."); - await this.createDomains(); - } + public async updateCloudFormationOutputs(): Promise { await this.getDomainInfo(); @@ -204,11 +200,6 @@ class ServerlessCustomDomain { } } })); - const autoDomain = this.serverless.service.custom.customDomain.autoDomain; - if (autoDomain === true) { - this.serverless.cli.log("Deleting domain name after removing base path mapping."); - await this.deleteDomains(); - } } /** diff --git a/src/types.ts b/src/types.ts index 371858fa..0e8c089c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,7 +25,6 @@ export interface ServerlessInstance { // tslint:disable-line hostedZonePrivate: boolean | undefined, enabled: boolean | string | undefined, securityPolicy: string | undefined, - autoDomain: boolean | undefined, }, }, }; diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 4d30b5aa..e8412b31 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -64,7 +64,6 @@ const constructPlugin = (customDomainOptions) => { custom: { customDomain: { apiType: customDomainOptions.apiType, - autoDomain: customDomainOptions.autoDomain, basePath: customDomainOptions.basePath, certificateArn: customDomainOptions.certificateArn, certificateName: customDomainOptions.certificateName, @@ -1577,171 +1576,4 @@ describe("Custom Domain Plugin", () => { AWS.restore(); }); }); - - describe("autoDomain deploy", () => { - it("Should be disabled by default", () => { - const plugin = constructPlugin({ domainName: "test_domain" }); - plugin.initializeVariables(); - expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(undefined); - }); - - it("createOrGetDomainForCfOutputs should call createDomain when autoDomain is true", async () => { - AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { - callback(null, params); - }); - const plugin = constructPlugin({ - autoDomain: true, - basePath: "test_basepath", - createRoute53Record: false, - domainName: "test_domain", - restApiId: "test_rest_api_id", - }); - plugin.initializeVariables(); - - plugin.apigateway = new aws.APIGateway(); - plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); - - plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; - - const spy = chai.spy.on(plugin.apigatewayV2, "getDomainName"); - - await plugin.createOrGetDomainForCfOutputs(); - - expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); - expect(spy).to.have.been.called(); - }); - - it("createOrGetDomainForCfOutputs should not call createDomain when autoDomain is not true", async () => { - AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { - callback(null, params); - }); - - const plugin = constructPlugin({ - autoDomain: false, - basePath: "test_basepath", - createRoute53Record: false, - domainName: "test_domain", - restApiId: "test_rest_api_id", - }); - plugin.initializeVariables(); - - plugin.apigateway = new aws.APIGateway(); - plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); - - plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; - - const spy1 = chai.spy.on(plugin.apigateway, "createDomainName"); - const spy2 = chai.spy.on(plugin.apigatewayV2, "createDomainName"); - - await plugin.createOrGetDomainForCfOutputs(); - - expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); - expect(spy1).to.have.not.been.called(); - expect(spy2).to.have.not.been.called(); - }); - - it("removeBasePathMapping should call deleteDomain when autoDomain is true", async () => { - AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { - callback(null, { - StackResourceDetail: - { - LogicalResourceId: "ApiGatewayRestApi", - PhysicalResourceId: "test_rest_api_id", - }, - }); - }); - AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { - callback(null, { - Items: [ - { ApiId: "test_rest_api_id", MappingKey: "test", ApiMappingId: "test_mapping_id", Stage: "test" }, - ], - }); - }); - AWS.mock("ApiGatewayV2", "deleteApiMapping", (params, callback) => { - callback(null, params); - }); - AWS.mock("ApiGatewayV2", "deleteDomainName", (params, callback) => { - callback(null, params); - }); - AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { - callback(null, params); - }); - - const plugin = constructPlugin({ - autoDomain: true, - basePath: "test_basepath", - createRoute53Record: false, - domainName: "test_domain", - restApiId: "test_rest_api_id", - }); - plugin.initializeVariables(); - - plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); - - plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; - - const spy = chai.spy.on(plugin.apigatewayV2, "deleteDomainName"); - - await plugin.removeBasePathMappings(); - - expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); - expect(spy).to.have.been.called.with({DomainName: "test_domain"}); - }); - - it("removeBasePathMapping should not call deleteDomain when autoDomain is not true", async () => { - AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { - callback(null, { - StackResourceDetail: - { - LogicalResourceId: "ApiGatewayRestApi", - PhysicalResourceId: "test_rest_api_id", - }, - }); - }); - AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { - callback(null, { - Items: [ - { ApiId: "test_rest_api_id", MappingKey: "test", ApiMappingId: "test_mapping_id", Stage: "test" }, - ], - }); - }); - AWS.mock("ApiGatewayV2", "deleteApiMapping", (params, callback) => { - callback(null, params); - }); - AWS.mock("ApiGatewayV2", "deleteDomainName", (params, callback) => { - callback(null, params); - }); - AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { - callback(null, params); - }); - - const plugin = constructPlugin({ - autoDomain: false, - basePath: "test_basepath", - createRoute53Record: false, - domainName: "test_domain", - restApiId: "test_rest_api_id", - }); - plugin.initializeVariables(); - - plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); - - plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; - - const spy = chai.spy.on(plugin.apigatewayV2, "deleteDomainName"); - - await plugin.removeBasePathMappings(); - - expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); - expect(spy).to.have.not.been.called(); - }); - - afterEach(() => { - consoleOutput = []; - }); - }); }); From 65a697bbf8cc283fd7e34a2ac390c41a9ede9ccf Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 8 Jun 2020 21:48:27 -0500 Subject: [PATCH 54/69] add autoDomain and autoDomainWaitFor option --- README.md | 6 + src/index.ts | 33 +++- src/types.ts | 2 + src/utils.ts | 1 + test/integration-tests/auto-domain/handler.js | 16 ++ .../auto-domain/serverless.yml | 27 +++ test/unit-tests/index.test.ts | 169 ++++++++++++++++++ 7 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 test/integration-tests/auto-domain/handler.js create mode 100644 test/integration-tests/auto-domain/serverless.yml diff --git a/README.md b/README.md index 60082ff2..3a8aa920 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ custom: endpointType: 'regional' securityPolicy: tls_1_2 apiType: rest + autoDomain: false ``` Multiple API types mapped to different domains can also be supported with the following structure. The key is the API Gateway API type. @@ -86,6 +87,7 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 + autoDomain: false http: domainName: http.serverless.foo.com stage: ci @@ -94,6 +96,7 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 + autoDomain: false websocket: domainName: ws.serverless.foo.com stage: ci @@ -102,6 +105,7 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 + autoDomain: false ``` | Parameter Name | Default Value | Description | @@ -119,6 +123,8 @@ custom: | enabled | true | Sometimes there are stages for which is not desired to have custom domain names. This flag allows the developer to disable the plugin for such cases. Accepts either `boolean` or `string` values and defaults to `true` for backwards compatibility. | securityPolicy | tls_1_2 | The security policy to apply to the custom domain name. Accepts `tls_1_0` or `tls_1_2`| allowPathMatching | false | When updating an existing api mapping this will match on the basePath instead of the API ID to find existing mappings for an upsate. This should only be used when changing API types. For example, migrating a REST API to an HTTP API. See Changing API Types for more information. | +| autoDomain | `false` | Toggles whether or not the plugin will run `create_domain/delete_domain` as part of `sls deploy/remove` so that multiple commands are not required. | +| autoDomainWaitFor | `120` | How long to wait for create_domain to finish before starting deployment if domain does not exist immediately. | ## Running diff --git a/src/index.ts b/src/index.ts index 40bd6787..ddf65eb2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import DomainConfig = require("./DomainConfig"); import DomainInfo = require("./DomainInfo"); import Globals from "./Globals"; import { ServerlessInstance, ServerlessOptions } from "./types"; -import {getAWSPagedResults, throttledCall} from "./utils"; +import {getAWSPagedResults, sleep, throttledCall} from "./utils"; const certStatuses = ["PENDING_VALIDATION", "ISSUED", "INACTIVE"]; @@ -54,7 +54,7 @@ class ServerlessCustomDomain { this.hooks = { "after:deploy:deploy": this.hookWrapper.bind(this, this.setupBasePathMappings), "after:info:info": this.hookWrapper.bind(this, this.domainSummaries), - "before:deploy:deploy": this.hookWrapper.bind(this, this.updateCloudFormationOutputs), + "before:deploy:deploy": this.hookWrapper.bind(this, this.createOrGetDomainForCfOutputs), "before:remove:remove": this.hookWrapper.bind(this, this.removeBasePathMappings), "create_domain:create": this.hookWrapper.bind(this, this.createDomains), "delete_domain:delete": this.hookWrapper.bind(this, this.deleteDomains), @@ -130,12 +130,31 @@ class ServerlessCustomDomain { } /** - * Lifecycle function to add domain info to the CloudFormation stack's Outputs + * Lifecycle function to createDomain before deploy and add domain info to the CloudFormation stack's Outputs */ - public async updateCloudFormationOutputs(): Promise { + public async createOrGetDomainForCfOutputs(): Promise { + const autoDomain = this.serverless.service.custom.customDomain.autoDomain; + if (autoDomain === true) { + this.serverless.cli.log("Creating domain name before deploy."); + await this.createDomains(); + } await this.getDomainInfo(); + if (autoDomain === true) { + const atLeastOneDoesNotExist = this.domains.some((domain) => !domain.domainInfo); + if (atLeastOneDoesNotExist === true) { + const waitFor = + parseInt(this.serverless.service.custom.customDomain.autoDomainWaitFor, 10) + || 120; + this.serverless.cli.log(`Waiting ${waitFor} seconds before starting deployment + because first time creating domain`); + + await sleep(waitFor); + await this.getDomainInfo(); + } + } + await Promise.all(this.domains.map(async (domain) => { this.addOutputs(domain); })); @@ -200,6 +219,12 @@ class ServerlessCustomDomain { } } })); + + const autoDomain = this.serverless.service.custom.customDomain.autoDomain; + if (autoDomain === true) { + this.serverless.cli.log("Deleting domain name after removing base path mapping."); + await this.deleteDomains(); + } } /** diff --git a/src/types.ts b/src/types.ts index 0e8c089c..34059e66 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,6 +25,8 @@ export interface ServerlessInstance { // tslint:disable-line hostedZonePrivate: boolean | undefined, enabled: boolean | string | undefined, securityPolicy: string | undefined, + autoDomain: boolean | undefined, + autoDomainWaitFor: string | undefined, }, }, }; diff --git a/src/utils.ts b/src/utils.ts index ce960381..f9fef870 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -76,6 +76,7 @@ async function sleep(seconds) { } export { + sleep, getAWSPagedResults, throttledCall, }; diff --git a/test/integration-tests/auto-domain/handler.js b/test/integration-tests/auto-domain/handler.js new file mode 100644 index 00000000..1bd222d6 --- /dev/null +++ b/test/integration-tests/auto-domain/handler.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports.helloWorld = (event, context, callback) => { + const response = { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin": "*", // Required for CORS support to work + }, + body: JSON.stringify({ + message: "Go Serverless v1.0! Your function executed successfully!", + input: event, + }), + }; + + callback(null, response); +}; diff --git a/test/integration-tests/auto-domain/serverless.yml b/test/integration-tests/auto-domain/serverless.yml new file mode 100644 index 00000000..1f7c323f --- /dev/null +++ b/test/integration-tests/auto-domain/serverless.yml @@ -0,0 +1,27 @@ +# Deploying should be idempotent +service: auto-domain-${opt:RANDOM_STRING} +provider: + name: aws + runtime: nodejs12.x + region: us-west-2 + stage: test +functions: + helloWorld: + handler: handler.helloWorld + events: + - http: + path: hello-world + method: get + cors: true +plugins: + - serverless-domain-manager +custom: + customDomain: + domainName: auto-domain-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + basePath: '' + autoDomain: true + autoDomainWaitFor: 120 + +package: + exclude: + - node_modules/** diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index e8412b31..d338253c 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -64,6 +64,8 @@ const constructPlugin = (customDomainOptions) => { custom: { customDomain: { apiType: customDomainOptions.apiType, + autoDomain: customDomainOptions.autoDomain, + autoDomainWaitFor: customDomainOptions.autoDomainWaitFor, basePath: customDomainOptions.basePath, certificateArn: customDomainOptions.certificateArn, certificateName: customDomainOptions.certificateName, @@ -1576,4 +1578,171 @@ describe("Custom Domain Plugin", () => { AWS.restore(); }); }); + + describe("autoDomain deploy", () => { + it("Should be disabled by default", () => { + const plugin = constructPlugin({ domainName: "test_domain" }); + plugin.initializeVariables(); + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(undefined); + }); + + it("createOrGetDomainForCfOutputs should call createDomain when autoDomain is true", async () => { + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, params); + }); + const plugin = constructPlugin({ + autoDomain: true, + basePath: "test_basepath", + createRoute53Record: false, + domainName: "test_domain", + restApiId: "test_rest_api_id", + }); + plugin.initializeVariables(); + + plugin.apigateway = new aws.APIGateway(); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + plugin.cloudformation = new aws.CloudFormation(); + + plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; + + const spy = chai.spy.on(plugin.apigatewayV2, "getDomainName"); + + await plugin.createOrGetDomainForCfOutputs(); + + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); + expect(spy).to.have.been.called(); + }); + + it("createOrGetDomainForCfOutputs should not call createDomain when autoDomain is not true", async () => { + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, params); + }); + + const plugin = constructPlugin({ + autoDomain: false, + basePath: "test_basepath", + createRoute53Record: false, + domainName: "test_domain", + restApiId: "test_rest_api_id", + }); + plugin.initializeVariables(); + + plugin.apigateway = new aws.APIGateway(); + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + plugin.cloudformation = new aws.CloudFormation(); + + plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; + + const spy1 = chai.spy.on(plugin.apigateway, "createDomainName"); + const spy2 = chai.spy.on(plugin.apigatewayV2, "createDomainName"); + + await plugin.createOrGetDomainForCfOutputs(); + + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); + expect(spy1).to.have.not.been.called(); + expect(spy2).to.have.not.been.called(); + }); + + it("removeBasePathMapping should call deleteDomain when autoDomain is true", async () => { + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "ApiGatewayRestApi", + PhysicalResourceId: "test_rest_api_id", + }, + }); + }); + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { + callback(null, { + Items: [ + { ApiId: "test_rest_api_id", MappingKey: "test", ApiMappingId: "test_mapping_id", Stage: "test" }, + ], + }); + }); + AWS.mock("ApiGatewayV2", "deleteApiMapping", (params, callback) => { + callback(null, params); + }); + AWS.mock("ApiGatewayV2", "deleteDomainName", (params, callback) => { + callback(null, params); + }); + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, params); + }); + + const plugin = constructPlugin({ + autoDomain: true, + basePath: "test_basepath", + createRoute53Record: false, + domainName: "test_domain", + restApiId: "test_rest_api_id", + }); + plugin.initializeVariables(); + + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + plugin.cloudformation = new aws.CloudFormation(); + + plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; + + const spy = chai.spy.on(plugin.apigatewayV2, "deleteDomainName"); + + await plugin.removeBasePathMappings(); + + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(true); + expect(spy).to.have.been.called.with({DomainName: "test_domain"}); + }); + + it("removeBasePathMapping should not call deleteDomain when autoDomain is not true", async () => { + AWS.mock("CloudFormation", "describeStackResource", (params, callback) => { + callback(null, { + StackResourceDetail: + { + LogicalResourceId: "ApiGatewayRestApi", + PhysicalResourceId: "test_rest_api_id", + }, + }); + }); + AWS.mock("ApiGatewayV2", "getApiMappings", (params, callback) => { + callback(null, { + Items: [ + { ApiId: "test_rest_api_id", MappingKey: "test", ApiMappingId: "test_mapping_id", Stage: "test" }, + ], + }); + }); + AWS.mock("ApiGatewayV2", "deleteApiMapping", (params, callback) => { + callback(null, params); + }); + AWS.mock("ApiGatewayV2", "deleteDomainName", (params, callback) => { + callback(null, params); + }); + AWS.mock("ApiGatewayV2", "getDomainName", (params, callback) => { + callback(null, params); + }); + + const plugin = constructPlugin({ + autoDomain: false, + basePath: "test_basepath", + createRoute53Record: false, + domainName: "test_domain", + restApiId: "test_rest_api_id", + }); + plugin.initializeVariables(); + + plugin.apigatewayV2 = new aws.ApiGatewayV2(); + plugin.cloudformation = new aws.CloudFormation(); + + plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; + + const spy = chai.spy.on(plugin.apigatewayV2, "deleteDomainName"); + + await plugin.removeBasePathMappings(); + + expect(plugin.serverless.service.custom.customDomain.autoDomain).to.equal(false); + expect(spy).to.have.not.been.called(); + }); + + afterEach(() => { + consoleOutput = []; + }); + }); }); From fb0f464fa33ce072e8dbeb9e624a9a1a8adcaea9 Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 8 Jun 2020 21:56:32 -0500 Subject: [PATCH 55/69] updates --- README.md | 3 --- test/integration-tests/auto-domain/serverless.yml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a8aa920..6eb0f6b2 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,6 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 - autoDomain: false http: domainName: http.serverless.foo.com stage: ci @@ -96,7 +95,6 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 - autoDomain: false websocket: domainName: ws.serverless.foo.com stage: ci @@ -105,7 +103,6 @@ custom: createRoute53Record: true endpointType: 'regional' securityPolicy: tls_1_2 - autoDomain: false ``` | Parameter Name | Default Value | Description | diff --git a/test/integration-tests/auto-domain/serverless.yml b/test/integration-tests/auto-domain/serverless.yml index 1f7c323f..594aa5a6 100644 --- a/test/integration-tests/auto-domain/serverless.yml +++ b/test/integration-tests/auto-domain/serverless.yml @@ -1,4 +1,4 @@ -# Deploying should be idempotent +# create_domain should be run as part of deployment service: auto-domain-${opt:RANDOM_STRING} provider: name: aws From 805d6209bf4fcab837a4f86d021579e4d50a5b91 Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 15 Jun 2020 10:40:50 -0500 Subject: [PATCH 56/69] add to test cases --- test/integration-tests/integration.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index 6b52c88a..fd6a3204 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -21,6 +21,14 @@ const RANDOM_STRING = randomstring.generate({ const TEMP_DIR = `~/tmp/domain-manager-test-${RANDOM_STRING}`; const testCases = [ + { + testBasePath: "(none)", + testDescription: "Creates domain as part of deploy", + testDomain: `auto-domain-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: "auto-domain", + testStage: "dev", + }, { testBasePath: "(none)", testDescription: "Enabled with default values", From 2cee458ee52468f63c1a82f78c9b829a7acab808 Mon Sep 17 00:00:00 2001 From: Hunter Date: Fri, 19 Jun 2020 11:48:21 -0500 Subject: [PATCH 57/69] add polling interval --- src/index.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index ddf65eb2..c4abf0fc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -142,15 +142,17 @@ class ServerlessCustomDomain { await this.getDomainInfo(); if (autoDomain === true) { - const atLeastOneDoesNotExist = this.domains.some((domain) => !domain.domainInfo); - if (atLeastOneDoesNotExist === true) { - const waitFor = - parseInt(this.serverless.service.custom.customDomain.autoDomainWaitFor, 10) - || 120; - this.serverless.cli.log(`Waiting ${waitFor} seconds before starting deployment - because first time creating domain`); - - await sleep(waitFor); + const atLeastOneDoesNotExist = () => this.domains.some((domain) => !domain.domainInfo); + const maxWaitFor = parseInt(this.serverless.service.custom.customDomain.autoDomainWaitFor, 10) || 120; + const pollInterval = 3; + for (let i = 0; i * pollInterval < maxWaitFor && atLeastOneDoesNotExist() === true; i++) { + this.serverless.cli.log(` + Poll #${i + 1}: polling every ${pollInterval} seconds + for domain to exist or until ${maxWaitFor} seconds + have elapsed before starting deployment + `); + + await sleep(pollInterval); await this.getDomainInfo(); } } From 1c058290b56ce718003ad9f7e50e998073e1fb7c Mon Sep 17 00:00:00 2001 From: Johnathan Constance Date: Tue, 14 Jul 2020 11:11:52 -0400 Subject: [PATCH 58/69] Releasing 4.2.0 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 708a1448..68fbe10f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [4.2.0] - 2020-07-14 + +### Changed +- Added support for automatically creating/destroying custom domains on deploy/remove via the autoDomain option. Thank you @bryan-hunter ([#356](https://github.com/amplify-education/serverless-domain-manager/pull/356)) + ## [4.1.1] - 2020-05-25 ### Changed diff --git a/package.json b/package.json index 76e1aaf3..e8a0c545 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.1.1", + "version": "4.2.0", "engines": { "node": ">=4.0" }, From b8ffcc5477ccfae4b9d7915687a878f1560decba Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Mon, 14 Sep 2020 19:45:18 +0300 Subject: [PATCH 59/69] add integration test --- package-lock.json | 802 ++---------------- .../apigateway-with-export/handler.js | 16 + .../apigateway-with-export/serverless.yml | 51 ++ .../apigateway-with-import/handler.js | 16 + .../apigateway-with-import/serverless.yml | 25 + test/integration-tests/integration.test.ts | 22 +- test/integration-tests/test-utilities.ts | 3 +- 7 files changed, 211 insertions(+), 724 deletions(-) create mode 100644 test/integration-tests/apigateway-with-export/handler.js create mode 100644 test/integration-tests/apigateway-with-export/serverless.yml create mode 100644 test/integration-tests/apigateway-with-import/handler.js create mode 100644 test/integration-tests/apigateway-with-import/serverless.yml diff --git a/package-lock.json b/package-lock.json index f630ec83..d493fbda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -287,41 +287,45 @@ } }, "@serverless/enterprise-plugin": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/@serverless/enterprise-plugin/-/enterprise-plugin-3.6.11.tgz", - "integrity": "sha512-cnn9A9ebpdW5Q1v9FHB7nbcFHkAttcownaw2AALXIld04hrIMpR3YILa47WxdXFyvyPg0dyKT5OhEly9Cc2BMQ==", + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@serverless/enterprise-plugin/-/enterprise-plugin-3.8.4.tgz", + "integrity": "sha512-pUrREqLXdO4AhO0lSS8nXDe2E56WR8aNVz2N6F+0QnAKEsfvyUxMYybwK0diLd4UAD/sMzMHpoohDgeqpHrdwQ==", "dev": true, "requires": { "@serverless/event-mocks": "^1.1.1", - "@serverless/platform-client": "^0.25.7", - "@serverless/platform-sdk": "^2.3.0", + "@serverless/platform-client": "^1.1.10", + "@serverless/platform-sdk": "^2.3.1", "chalk": "^2.4.2", "child-process-ext": "^2.1.1", - "chokidar": "^3.4.0", + "chokidar": "^3.4.2", "cli-color": "^2.0.0", - "dependency-tree": "^7.2.1", "find-process": "^1.4.3", - "flat": "^5.0.0", + "flat": "^5.0.2", "fs-extra": "^8.1.0", "iso8601-duration": "^1.2.0", - "isomorphic-fetch": "^2.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^3.14.0", "jsonata": "^1.8.3", - "jszip": "^3.4.0", - "lodash": "^4.17.15", + "jszip": "^3.5.0", + "lodash": "^4.17.20", "memoizee": "^0.4.14", - "moment": "^2.25.3", + "moment": "^2.27.0", + "ncjsm": "^4.1.0", "node-dir": "^0.1.17", - "node-fetch": "^2.6.0", - "regenerator-runtime": "^0.13.5", + "node-fetch": "^2.6.1", + "regenerator-runtime": "^0.13.7", "semver": "^6.3.0", "simple-git": "^1.132.0", "source-map-support": "^0.5.19", - "update-notifier": "^2.5.0", "uuid": "^3.4.0", "yamljs": "^0.3.0" }, "dependencies": { + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -334,9 +338,9 @@ } }, "chokidar": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", - "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -350,13 +354,10 @@ } }, "flat": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.0.tgz", - "integrity": "sha512-6KSMM+cHHzXC/hpldXApL2S8Uz+QZv+tq5o/L0KQYleoG+GcwrnIJhTWC7tCOiKQp8D/fIvryINU1OZCCwevjA==", - "dev": true, - "requires": { - "is-buffer": "~2.0.4" - } + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true }, "fs-extra": { "version": "8.1.0", @@ -375,6 +376,31 @@ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "ncjsm": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.1.0.tgz", + "integrity": "sha512-YElRGtbz5iIartetOI3we+XAkcGE29F0SdNC0qRy500/u4WceQd2z9Nhlx24OHmIDIKz9MHdJwf/fkSG0hdWcQ==", + "dev": true, + "requires": { + "builtin-modules": "^3.1.0", + "deferred": "^0.7.11", + "es5-ext": "^0.10.53", + "es6-set": "^0.1.5", + "find-requires": "^1.0.0", + "fs2": "^0.3.8", + "type": "^2.0.0" + } + }, "readdirp": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", @@ -384,6 +410,12 @@ "picomatch": "^2.2.1" } }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -436,9 +468,9 @@ } }, "@serverless/platform-client": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-0.25.7.tgz", - "integrity": "sha512-ZOKgT49qQPGjv0tDN46INO0gkc5syL2y5t0pau5ljQPtQpJzHrUL87xRlDj3BD+4Y9QFZV1UXXNsOQZsyCBsPw==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-1.1.10.tgz", + "integrity": "sha512-vMCYRdDaqQjPDlny3+mVNy0lr1P6RJ7hVkR2w9Bk783ZB894hobtMrTm8V8OQPwOvlAypmLnQsLPXwRNM+AMsw==", "dev": true, "requires": { "adm-zip": "^0.4.13", @@ -594,9 +626,9 @@ } }, "@serverless/platform-sdk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-2.3.0.tgz", - "integrity": "sha512-+9TiMYDVKJOyDWg9p/k0kmGVZ3+rjB8DXpACDxxyUChDSsRS55CTJnt321Yx7APfHctNRSnv3ubYmx7oGSTETQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-2.3.1.tgz", + "integrity": "sha512-EiSizya9bK0+5uae3GH9uXuWAchZplkLO0tWOAXtnU5QWSg5zicANL9jKCw0dyhjUOvbcO0ddhFlG8EGYvJFSA==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -836,9 +868,9 @@ } }, "@types/lodash": { - "version": "4.14.150", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.150.tgz", - "integrity": "sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w==", + "version": "4.14.161", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.161.tgz", + "integrity": "sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA==", "dev": true }, "@types/long": { @@ -911,61 +943,6 @@ "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==", "dev": true }, - "@typescript-eslint/typescript-estree": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.32.0.tgz", - "integrity": "sha512-hQpbWM/Y2iq6jB9FHYJBqa3h1R9IEGodOtajhb261cVHt9cz30AKjXM6WP7LxJdEPPlyJ9rPTZVgBUgZgiyPgw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "eslint-visitor-keys": "^1.1.0", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -973,9 +950,9 @@ "dev": true }, "adm-zip": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz", - "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==", + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", "dev": true }, "after": { @@ -1071,12 +1048,6 @@ "picomatch": "^2.0.4" } }, - "app-module-path": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", - "dev": true - }, "append-transform": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", @@ -1297,12 +1268,6 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-module-types": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-2.6.0.tgz", - "integrity": "sha512-zXSoVaMrf2R+r+ISid5/9a8SXm1LLdkhHzh6pSRhj9jklzruOOl1hva1YmFT33wAstg/f9ZndJAlq1BSrFLSGA==", - "dev": true - }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -2305,15 +2270,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "decomment": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/decomment/-/decomment-0.9.2.tgz", - "integrity": "sha512-sblyUmOJZxiL7oJ2ogJS6jtl/67+CTOW87SrYE/96u3PhDYikYoLCdLzcnceToiQejOLlqNnLCkaxx/+nE/ehg==", - "dev": true, - "requires": { - "esprima": "4.0.1" - } - }, "decompress": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", @@ -2376,9 +2332,9 @@ }, "dependencies": { "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", "dev": true, "requires": { "readable-stream": "^2.3.5", @@ -2576,188 +2532,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "dependency-tree": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/dependency-tree/-/dependency-tree-7.2.1.tgz", - "integrity": "sha512-nBxnjkqDW4LqAzBazy60V4lE0mAtIQ+oers/GIIvVvGYVdCD9+RNNd4G9jjstyz7ZFVg/j/OiYCvK5MjoVqA2w==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "debug": "^4.1.1", - "filing-cabinet": "^2.5.1", - "precinct": "^6.2.0", - "typescript": "^3.7.5" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true - } - } - }, - "detective-amd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-3.0.0.tgz", - "integrity": "sha512-kOpKHyabdSKF9kj7PqYHLeHPw+TJT8q2u48tZYMkIcas28el1CYeLEJ42Nm+563/Fq060T5WknfwDhdX9+kkBQ==", - "dev": true, - "requires": { - "ast-module-types": "^2.3.1", - "escodegen": "^1.8.0", - "get-amd-module-type": "^3.0.0", - "node-source-walk": "^4.0.0" - } - }, - "detective-cjs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-3.1.1.tgz", - "integrity": "sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg==", - "dev": true, - "requires": { - "ast-module-types": "^2.4.0", - "node-source-walk": "^4.0.0" - } - }, - "detective-es6": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-2.1.0.tgz", - "integrity": "sha512-QSHqKGOp/YBIfmIqKXaXeq2rlL+bp3bcIQMfZ+0PvKzRlELSOSZxKRvpxVcxlLuocQv4QnOfuWGniGrmPbz8MQ==", - "dev": true, - "requires": { - "node-source-walk": "^4.0.0" - } - }, - "detective-less": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/detective-less/-/detective-less-1.0.2.tgz", - "integrity": "sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==", - "dev": true, - "requires": { - "debug": "^4.0.0", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "detective-postcss": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-3.0.1.tgz", - "integrity": "sha512-tfTS2GdpUal5NY0aCqI4dpEy8Xfr88AehYKB0iBIZvo8y2g3UsrcDnrp9PR2FbzoW7xD5Rip3NJW7eCSvtqdUw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "is-url": "^1.2.4", - "postcss": "^7.0.2", - "postcss-values-parser": "^1.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "detective-sass": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-3.0.1.tgz", - "integrity": "sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "detective-scss": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-2.0.1.tgz", - "integrity": "sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "detective-stylus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-1.0.0.tgz", - "integrity": "sha1-UK7n24uruZA4HwEMY/q7pbWOVM0=", - "dev": true - }, - "detective-typescript": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-5.8.0.tgz", - "integrity": "sha512-SrsUCfCaDTF64QVMHMidRal+kmkbIc5zP8cxxZPsomWx9vuEUjBlSJNhf7/ypE5cLdJJDI4qzKDmyzqQ+iz/xg==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "^2.29.0", - "ast-module-types": "^2.6.0", - "node-source-walk": "^4.2.0", - "typescript": "^3.8.3" - }, - "dependencies": { - "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true - } - } - }, "diagnostics": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", @@ -3092,32 +2866,12 @@ "has-binary2": "~1.0.2" } }, - "enhanced-resolve": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", - "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, "env-variable": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==", "dev": true }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3278,12 +3032,6 @@ } } }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - }, "esniff": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/esniff/-/esniff-1.1.0.tgz", @@ -3489,12 +3237,6 @@ "escape-string-regexp": "^1.0.5" } }, - "file-exists-dazinatorfork": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/file-exists-dazinatorfork/-/file-exists-dazinatorfork-1.0.2.tgz", - "integrity": "sha512-r70c72ln2YHzQINNfxDp02hAhbGkt1HffZ+Du8oetWDLjDtFja/Lm10lUaSh9e+wD+7VDvPee0b0C9SAy8pWZg==", - "dev": true - }, "file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", @@ -3524,47 +3266,6 @@ "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", "dev": true }, - "filing-cabinet": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-2.5.1.tgz", - "integrity": "sha512-GWOdObzou2L0HrJUk8MpJa01q0ZOwuTwTssM2+P+ABJWEGlVWd6ueEatANFdin94/3rdkVSdqpH14VqCNqp3RA==", - "dev": true, - "requires": { - "app-module-path": "^2.2.0", - "commander": "^2.13.0", - "debug": "^4.1.1", - "decomment": "^0.9.2", - "enhanced-resolve": "^4.1.0", - "is-relative-path": "^1.0.2", - "module-definition": "^3.0.0", - "module-lookup-amd": "^6.1.0", - "resolve": "^1.11.1", - "resolve-dependency-path": "^2.0.0", - "sass-lookup": "^3.0.0", - "stylus-lookup": "^3.0.1", - "typescript": "^3.0.3" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3574,15 +3275,6 @@ "to-regex-range": "^5.0.1" } }, - "find": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", - "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", - "dev": true, - "requires": { - "traverse-chain": "~0.1.0" - } - }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -3650,12 +3342,6 @@ "is-buffer": "~2.0.3" } }, - "flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", - "dev": true - }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -3839,28 +3525,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "get-amd-module-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz", - "integrity": "sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw==", - "dev": true, - "requires": { - "ast-module-types": "^2.3.2", - "node-source-walk": "^4.0.0" - } - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, "get-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", @@ -3968,15 +3638,6 @@ } } }, - "gonzales-pe": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", - "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -4299,12 +3960,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -4776,18 +4431,6 @@ "has": "^1.0.3" } }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-relative-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-relative-path/-/is-relative-path-1.0.2.tgz", - "integrity": "sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY=", - "dev": true - }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -4815,12 +4458,6 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -5209,9 +4846,9 @@ } }, "jszip": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.4.0.tgz", - "integrity": "sha512-gZAOYuPl4EhPTXT0GjhI3o+ZAz3su6EhLrKUoAivcKqyqC7laS5JEv4XWZND9BgcDcF83vI85yGbDmDR6UhrIg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", + "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", "dev": true, "requires": { "lie": "~3.3.0", @@ -5663,42 +5300,6 @@ "timers-ext": "^0.1.5" } }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -5872,45 +5473,10 @@ "integrity": "sha512-fSdhAkOEEqGMO6MgyBwFD1/NzXaPSELZuz8I0sAKbd4CJRd2LKJpUQKlyX4VST4mT2zxn7Yh+Ek9GNVZTvdAXQ==", "dev": true }, - "module-definition": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-3.3.0.tgz", - "integrity": "sha512-HTplA9xwDzH67XJFC1YvZMUElWJD28DV0dUq7lhTs+JKJamUOWA/CcYWSlhW5amJO66uWtY7XdltT+LfX0wIVg==", - "dev": true, - "requires": { - "ast-module-types": "^2.6.0", - "node-source-walk": "^4.0.0" - } - }, - "module-lookup-amd": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/module-lookup-amd/-/module-lookup-amd-6.2.0.tgz", - "integrity": "sha512-uxHCj5Pw9psZiC1znjU2qPsubt6haCSsN9m7xmIdoTciEgfxUkE1vhtDvjHPuOXEZrVJhjKgkmkP+w73rRuelQ==", - "dev": true, - "requires": { - "commander": "^2.8.1", - "debug": "^4.1.0", - "file-exists-dazinatorfork": "^1.0.2", - "find": "^0.3.0", - "requirejs": "^2.3.5", - "requirejs-config-file": "^3.1.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, "moment": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz", - "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==", + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", "dev": true }, "ms": { @@ -6025,20 +5591,11 @@ } }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", "dev": true }, - "node-source-walk": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-4.2.0.tgz", - "integrity": "sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA==", - "dev": true, - "requires": { - "@babel/parser": "^7.0.0" - } - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -6643,105 +6200,6 @@ "find-up": "^3.0.0" } }, - "postcss": { - "version": "7.0.30", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.30.tgz", - "integrity": "sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-values-parser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz", - "integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "precinct": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-6.2.0.tgz", - "integrity": "sha512-BCAmnOxZzobF3H1/h/gq70pEyvX/BVLWCrzi8beFD22dqu5Z14qOghNUsI24Wg8oaTsGFcIjOGtFX5L9ttmjVg==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "debug": "^4.1.1", - "detective-amd": "^3.0.0", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.0.0", - "detective-less": "^1.0.2", - "detective-postcss": "^3.0.0", - "detective-sass": "^3.0.0", - "detective-scss": "^2.0.0", - "detective-stylus": "^1.0.0", - "detective-typescript": "^5.1.1", - "module-definition": "^3.3.0", - "node-source-walk": "^4.2.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6820,12 +6278,6 @@ } } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -7077,23 +6529,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "requirejs": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", - "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", - "dev": true - }, - "requirejs-config-file": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/requirejs-config-file/-/requirejs-config-file-3.1.2.tgz", - "integrity": "sha512-sdLWywcDuNz7EIOhenSbRfT4YF84nItDv90coN2htbokjmU2QeyQuSBZILQUKNksepl8UPVU+hgYySFaDxbJPQ==", - "dev": true, - "requires": { - "esprima": "^4.0.0", - "make-dir": "^2.1.0", - "stringify-object": "^3.2.1" - } - }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -7103,12 +6538,6 @@ "path-parse": "^1.0.5" } }, - "resolve-dependency-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz", - "integrity": "sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w==", - "dev": true - }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -7199,23 +6628,6 @@ "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", "dev": true }, - "sass-lookup": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz", - "integrity": "sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg==", - "dev": true, - "requires": { - "commander": "^2.16.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, "sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", @@ -8369,17 +7781,6 @@ } } }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -8425,27 +7826,6 @@ "escape-string-regexp": "^1.0.2" } }, - "stylus-lookup": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-3.0.2.tgz", - "integrity": "sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg==", - "dev": true, - "requires": { - "commander": "^2.8.1", - "debug": "^4.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, "superagent": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", @@ -8523,12 +7903,6 @@ } } }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, "tar-stream": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz", @@ -8729,12 +8103,6 @@ "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", "dev": true }, - "traverse-chain": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", - "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", - "dev": true - }, "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -8951,12 +8319,6 @@ } } }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", diff --git a/test/integration-tests/apigateway-with-export/handler.js b/test/integration-tests/apigateway-with-export/handler.js new file mode 100644 index 00000000..1bd222d6 --- /dev/null +++ b/test/integration-tests/apigateway-with-export/handler.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports.helloWorld = (event, context, callback) => { + const response = { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin": "*", // Required for CORS support to work + }, + body: JSON.stringify({ + message: "Go Serverless v1.0! Your function executed successfully!", + input: event, + }), + }; + + callback(null, response); +}; diff --git a/test/integration-tests/apigateway-with-export/serverless.yml b/test/integration-tests/apigateway-with-export/serverless.yml new file mode 100644 index 00000000..5b222260 --- /dev/null +++ b/test/integration-tests/apigateway-with-export/serverless.yml @@ -0,0 +1,51 @@ +# APIGateway with export outputs +service: apigateway-with-export-${opt:RANDOM_STRING} + +provider: + name: aws + runtime: nodejs12.x + region: us-west-2 + endpointType: regional + +functions: + helloWorld: + handler: handler.helloWorld + events: + - http: + path: hello-world + method: get + cors: true + +resources: + Outputs: + RestApi: + Description: Main service's API Gateway REST API ID + Value: + Ref: ApiGatewayRestApi # Logical ID + Export: + Name: api-${opt:stage, self:provider.stage}-restApiId + RootResource: + Description: Main service's API Gateway Root Resource ID + Value: + Fn::GetAtt: + - ApiGatewayRestApi # Logical ID + - RootResourceId # Logical ID + Export: + Name: api-${opt:stage, self:provider.stage}-RootResourceId + +plugins: + - serverless-domain-manager + +custom: + customDomain: + stage: ${opt:stage} + domainName: apigateway-with-export-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} + autoDomain: true + basePath: hello-world + endpointType: regional + createRoute53Record: false + + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/apigateway-with-import/handler.js b/test/integration-tests/apigateway-with-import/handler.js new file mode 100644 index 00000000..1bd222d6 --- /dev/null +++ b/test/integration-tests/apigateway-with-import/handler.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports.helloWorld = (event, context, callback) => { + const response = { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin": "*", // Required for CORS support to work + }, + body: JSON.stringify({ + message: "Go Serverless v1.0! Your function executed successfully!", + input: event, + }), + }; + + callback(null, response); +}; diff --git a/test/integration-tests/apigateway-with-import/serverless.yml b/test/integration-tests/apigateway-with-import/serverless.yml new file mode 100644 index 00000000..e658743c --- /dev/null +++ b/test/integration-tests/apigateway-with-import/serverless.yml @@ -0,0 +1,25 @@ +# APIGateway with import other CloudFormation stack outputs +service: apigateway-with-import-${opt:RANDOM_STRING} + +provider: + name: aws + runtime: nodejs12.x + region: us-west-2 + apiGateway: + restApiId: + Fn::ImportValue: api-${opt:stage, self:provider.stage}-restApiId + restApiRootResourceId: + Fn::ImportValue: api-${opt:stage, self:provider.stage}-RootResourceId + +functions: + helloWorld: + handler: handler.helloWorld + events: + - http: + path: hello-world2 + method: get + cors: true + +package: + exclude: + - node_modules/** diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index fd6a3204..9bca7f4a 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -27,7 +27,7 @@ const testCases = [ testDomain: `auto-domain-${RANDOM_STRING}.${TEST_DOMAIN}`, testEndpoint: "EDGE", testFolder: "auto-domain", - testStage: "dev", + testStage: "test", }, { testBasePath: "(none)", @@ -114,7 +114,7 @@ describe("Integration Tests", function() { restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); } try { - await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING, true); + await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING); const stage = await utilities.getStage(value.testDomain); expect(stage).to.equal(value.testStage); @@ -130,6 +130,24 @@ describe("Integration Tests", function() { } } }); + + it("APIGateway with export and import resources", async () => { + const testExportFolder = "apigateway-with-export"; + const testImportFolder = "apigateway-with-import"; + const testURL = `apigateway-with-export-${RANDOM_STRING}.${TEST_DOMAIN}`; + + try { + await utilities.createTempDir(TEMP_DIR, testExportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + await utilities.createTempDir(TEMP_DIR, testImportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + } finally { + await utilities.destroyResources(testURL, testImportFolder); + await utilities.destroyResources(testURL, testExportFolder); + } + }); }); describe("Basepath mapping issue tests", () => { diff --git a/test/integration-tests/test-utilities.ts b/test/integration-tests/test-utilities.ts index 6ab0fa43..95e8a4a7 100644 --- a/test/integration-tests/test-utilities.ts +++ b/test/integration-tests/test-utilities.ts @@ -174,10 +174,9 @@ async function removeLambdas(tempDir, domainIdentifier) { * @param folderName * @param url * @param domainIdentifier Random alphanumeric string to identify specific run of integration tests. - * @param enabled * @returns {Promise} Resolves if successfully executed, else rejects */ -async function createResources(folderName, url, domainIdentifier, enabled) { +async function createResources(folderName, url, domainIdentifier) { console.debug(`\tCreating Resources for ${url}`); const tempDir = `~/tmp/domain-manager-test-${domainIdentifier}`; console.debug(`\tUsing tmp directory ${tempDir}`); From f202ad46fdf0c9b539b58f46a67869a24af12081 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Mon, 14 Sep 2020 19:53:17 +0300 Subject: [PATCH 60/69] update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68fbe10f..8c1b37e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [4.2.1] - 2020-09-14 + +### Changed +- Added support for using CloudFormation Fn::ImportValue. Thank you @sampsasaarela ([#220](https://github.com/amplify-education/serverless-domain-manager/pull/220)), @rddimon ([#380](https://github.com/amplify-education/serverless-domain-manager/pull/380)) + ## [4.2.0] - 2020-07-14 ### Changed From 41d6bd6ed4b58a708f49d0f32f6d521f993dc9e5 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Tue, 15 Sep 2020 17:58:15 +0300 Subject: [PATCH 61/69] refactoring, update packages and tests --- package-lock.json | 2499 +++++++---------- package.json | 30 +- src/aws/cloud-formation-wrapper.ts | 66 + src/index.ts | 123 +- .../apigateway-with-export/serverless.yml | 7 +- .../apigateway-with-import/serverless.yml | 5 +- test/integration-tests/integration.test.ts | 39 +- test/unit-tests/index.test.ts | 20 +- 8 files changed, 1246 insertions(+), 1543 deletions(-) create mode 100644 src/aws/cloud-formation-wrapper.ts diff --git a/package-lock.json b/package-lock.json index d493fbda..372f64a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -154,6 +154,16 @@ "to-fast-properties": "^2.0.0" } }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", @@ -254,6 +264,125 @@ "shortid": "^2.2.14" } }, + "@serverless/components": { + "version": "2.34.9", + "resolved": "https://registry.npmjs.org/@serverless/components/-/components-2.34.9.tgz", + "integrity": "sha512-qFjIeGgR4SjS32Tbl4BvoxOtLpv3Vx4s/81HdmmpdIrMPe7ePGUfkBVBu3axxAXHf4ajlb4WC1HmhTmZAHHSLQ==", + "dev": true, + "requires": { + "@serverless/inquirer": "^1.1.2", + "@serverless/platform-client": "^1.1.3", + "@serverless/platform-client-china": "^1.0.37", + "@serverless/platform-sdk": "^2.3.1", + "@serverless/utils": "^1.2.0", + "adm-zip": "^0.4.16", + "ansi-escapes": "^4.3.1", + "chalk": "^2.4.2", + "child-process-ext": "^2.1.1", + "chokidar": "^3.4.1", + "dotenv": "^8.2.0", + "figures": "^3.2.0", + "fs-extra": "^8.1.0", + "globby": "^10.0.2", + "got": "^9.6.0", + "graphlib": "^2.1.8", + "https-proxy-agent": "^5.0.0", + "ini": "^1.3.5", + "inquirer-autocomplete-prompt": "^1.0.2", + "js-yaml": "^3.14.0", + "minimist": "^1.2.5", + "moment": "^2.27.0", + "open": "^7.1.0", + "prettyoutput": "^1.2.0", + "ramda": "^0.26.1", + "semver": "^7.3.2", + "stream.pipeline-shim": "^1.1.0", + "strip-ansi": "^5.2.0", + "traverse": "^0.6.6", + "uuid": "^3.4.0", + "ws": "^7.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, "@serverless/core": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@serverless/core/-/core-1.1.2.tgz", @@ -320,23 +449,6 @@ "yamljs": "^0.3.0" }, "dependencies": { - "builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "chokidar": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", @@ -359,23 +471,6 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", @@ -386,21 +481,6 @@ "esprima": "^4.0.0" } }, - "ncjsm": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.1.0.tgz", - "integrity": "sha512-YElRGtbz5iIartetOI3we+XAkcGE29F0SdNC0qRy500/u4WceQd2z9Nhlx24OHmIDIKz9MHdJwf/fkSG0hdWcQ==", - "dev": true, - "requires": { - "builtin-modules": "^3.1.0", - "deferred": "^0.7.11", - "es5-ext": "^0.10.53", - "es6-set": "^0.1.5", - "find-requires": "^1.0.0", - "fs2": "^0.3.8", - "type": "^2.0.0" - } - }, "readdirp": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", @@ -410,34 +490,12 @@ "picomatch": "^2.2.1" } }, - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -527,46 +585,6 @@ "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", "dev": true }, - "compress-commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-3.0.0.tgz", - "integrity": "sha512-FyDqr8TKX5/X0qo+aVfaZ+PVmNJHJeckFBlq8jZGSJOgnynhfifoyl24qaqdUdDIBe0EVTHByN6NAkqYvE/2Xg==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^3.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^2.3.7" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -581,12 +599,6 @@ "path-is-absolute": "^1.0.0" } }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", @@ -602,48 +614,28 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "zip-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-3.0.1.tgz", - "integrity": "sha512-r+JdDipt93ttDjsOVPU5zaq5bAyY+3H19bDrThkvuVxC0xMQzU1PJcS6D+KrP3u96gH9XLomcHPb+2skoDjulQ==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^3.0.0", - "readable-stream": "^3.6.0" - } } } }, "@serverless/platform-sdk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-2.3.1.tgz", - "integrity": "sha512-EiSizya9bK0+5uae3GH9uXuWAchZplkLO0tWOAXtnU5QWSg5zicANL9jKCw0dyhjUOvbcO0ddhFlG8EGYvJFSA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-2.3.2.tgz", + "integrity": "sha512-JSX0/EphGVvnb4RAgZYewtBXPuVsU2TFCuXh6EEZ4jxK3WgUwNYeYdwB8EuVLrm1/dYqu/UWUC0rPKb+ZDycJg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "https-proxy-agent": "^4.0.0", "is-docker": "^1.1.0", - "isomorphic-fetch": "^2.2.1", "jwt-decode": "^2.2.0", + "node-fetch": "^2.6.1", "opn": "^5.5.0", "querystring": "^0.2.0", "ramda": "^0.25.0", "rc": "^1.2.8", - "regenerator-runtime": "^0.13.1", - "source-map-support": "^0.5.12", - "uuid": "^3.3.2", - "write-file-atomic": "^2.4.2", + "regenerator-runtime": "^0.13.7", + "source-map-support": "^0.5.19", + "uuid": "^3.4.0", + "write-file-atomic": "^2.4.3", "ws": "<7.0.0" }, "dependencies": { @@ -678,22 +670,12 @@ "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", @@ -828,15 +810,15 @@ "dev": true }, "@types/chai": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", - "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.12.tgz", + "integrity": "sha512-aN5IAC8QNtSUdQzxu7lGBgYAOuU1tmRU4c9dIq5OKGf/SBVjXo+ffM2wEjudAWbgpOhy60nLoAGH1xm8fpCKFQ==", "dev": true }, "@types/chai-spies": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.0.tgz", - "integrity": "sha512-Bj/froHomMnlAPEYEeqhmSuNSjTWW/VuSvCVdhLdcb67+dy4ffjTR6fC0YYw9tHP6KR3U8fkF1mgzmzlChHc5Q==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.2.tgz", + "integrity": "sha512-Z04E43GW/dnYdQyj/N868wT5HhMDw2DbfxfPV7DNOX70PqODv9BKXGriFWY508vk1rPAtYcgENaRh/YCikuFtQ==", "dev": true, "requires": { "@types/chai": "*" @@ -886,15 +868,15 @@ "dev": true }, "@types/mocha": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", - "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", "dev": true }, "@types/node": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.0.tgz", - "integrity": "sha512-Jrb/x3HT4PTJp6a4avhmJCDEVrPdqLfl3e8GGMbpkGGdwAV5UGlIs4vVEfsHHfylZVOKZWpOqmqFH8CbfOZ6kg==", + "version": "12.12.58", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.58.tgz", + "integrity": "sha512-Be46CNIHWAagEfINOjmriSxuv7IVcqbGe+sDSg2SYCEz/0CRBy7LRASGfRbD8KZkqoePU73Wsx3UvOSFcq/9hA==", "dev": true }, "@types/object-assign": { @@ -962,9 +944,9 @@ "dev": true }, "agent-base": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", - "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", "dev": true, "requires": { "debug": "4" @@ -981,6 +963,32 @@ } } }, + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -989,24 +997,12 @@ "optional": true }, "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", "dev": true, "requires": { - "string-width": "^2.0.0" - }, - "dependencies": { - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - } + "string-width": "^3.0.0" } }, "ansi-colors": { @@ -1098,6 +1094,35 @@ "lodash": "^4.17.14" } }, + "compress-commons": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", + "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^3.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -1111,6 +1136,26 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "zip-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", + "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^2.1.1", + "readable-stream": "^3.4.0" + } } } }, @@ -1185,9 +1230,9 @@ "dev": true }, "arg": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", - "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, "argparse": { @@ -1205,6 +1250,12 @@ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", @@ -1235,12 +1286,6 @@ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -1293,19 +1338,26 @@ "dev": true }, "aws-sdk": { - "version": "2.490.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.490.0.tgz", - "integrity": "sha512-8dCf+F360XEwOorTk0wVV/haaxYvUZnfZI6PVXfR8xbcVd7Ioh9KWRe+MqHNStEttE4UQzknEPrUj/mDW++NDw==", + "version": "2.752.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.752.0.tgz", + "integrity": "sha512-0/8Pt8/qEgxt02IEvRjinR3cEj1YmmPlJqie4NhCWmmXmI4wDmEb5Em3A2XvU1dNwS0fpQEcuRcaQ/pWi/mScg==", "requires": { - "buffer": "4.9.1", + "buffer": "4.9.2", "events": "1.1.1", - "ieee754": "1.1.8", + "ieee754": "1.1.13", "jmespath": "0.15.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", "uuid": "3.3.2", "xml2js": "0.4.19" + }, + "dependencies": { + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + } } }, "aws-sdk-mock": { @@ -1326,9 +1378,9 @@ "dev": true }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, "axios": { @@ -1373,7 +1425,36 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } } } @@ -1408,9 +1489,9 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, "bl": { @@ -1470,32 +1551,6 @@ "widest-line": "^2.0.0" }, "dependencies": { - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "requires": { - "string-width": "^3.0.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", - "dev": true - }, "type-fest": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", @@ -1530,9 +1585,9 @@ "dev": true }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", @@ -1612,9 +1667,9 @@ }, "dependencies": { "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" @@ -1646,6 +1701,12 @@ "write-file-atomic": "^2.4.2" } }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", @@ -1658,12 +1719,6 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1700,9 +1755,9 @@ "dev": true }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1759,12 +1814,6 @@ "readdirp": "~3.2.0" } }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1785,76 +1834,13 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true } } }, "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, "cli-color": { @@ -1879,6 +1865,15 @@ } } }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, "cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -2027,15 +2022,15 @@ "dev": true }, "compress-commons": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", - "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-3.0.0.tgz", + "integrity": "sha512-FyDqr8TKX5/X0qo+aVfaZ+PVmNJHJeckFBlq8jZGSJOgnynhfifoyl24qaqdUdDIBe0EVTHByN6NAkqYvE/2Xg==", "dev": true, "requires": { "buffer-crc32": "^0.2.13", "crc32-stream": "^3.0.1", "normalize-path": "^3.0.0", - "readable-stream": "^2.3.6" + "readable-stream": "^2.3.7" }, "dependencies": { "readable-stream": { @@ -2080,37 +2075,6 @@ "proto-list": "~1.2.1" } }, - "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -2191,15 +2155,6 @@ "readable-stream": "^3.4.0" } }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, "cross-spawn": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", @@ -2210,12 +2165,6 @@ "which": "^1.2.9" } }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -2244,9 +2193,9 @@ } }, "dayjs": { - "version": "1.8.26", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.26.tgz", - "integrity": "sha512-KqtAuIfdNfZR5sJY1Dixr2Is4ZvcCqhb0dZpCOt5dGEFiMzoIbjkTSzUb4QKTCsP+WNpGwUjAFIZrnZvUxxkhw==", + "version": "1.8.35", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.35.tgz", + "integrity": "sha512-isAbIEenO4ilm6f8cpqvgjZCsuerDAz2Kb7ri201AiNn58aqXuaLJEnCtfIMdCvERZHNGRY5lDMTr/jdAnKSWQ==", "dev": true }, "debug": { @@ -2524,6 +2473,37 @@ "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } } }, "delayed-stream": { @@ -2572,15 +2552,6 @@ } } }, - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, "dot-qs": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dot-qs/-/dot-qs-0.2.0.tgz", @@ -2790,15 +2761,6 @@ "env-variable": "0.0.x" } }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -3105,6 +3067,56 @@ } } }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "ext": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", @@ -3147,6 +3159,17 @@ "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "external-editor": { @@ -3160,18 +3183,77 @@ "tmp": "^0.0.33" } }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, "fast-glob": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", @@ -3468,26 +3550,21 @@ "dev": true }, "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "dependencies": { - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true } } }, @@ -3593,14 +3670,11 @@ "is-glob": "^4.0.1" } }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true }, "globals": { "version": "11.12.0", @@ -3609,18 +3683,27 @@ "dev": true }, "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", "dev": true, "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" }, "dependencies": { + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -3630,11 +3713,170 @@ "array-uniq": "^1.0.1" } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } } } }, @@ -3663,12 +3905,6 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "graphlib": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", @@ -3718,27 +3954,13 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", - "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - } } }, "has": { @@ -3937,9 +4159,9 @@ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" }, "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true }, "immediate": { @@ -3948,12 +4170,6 @@ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", "dev": true }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4015,26 +4231,6 @@ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -4044,37 +4240,6 @@ "escape-string-regexp": "^1.0.5" } }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -4169,15 +4334,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4190,9 +4346,9 @@ } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, "into-stream": { @@ -4220,12 +4376,29 @@ "dev": true }, "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-arguments": { @@ -4261,32 +4434,32 @@ "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", "dev": true }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "ci-info": "^1.5.0" + "kind-of": "^3.0.2" }, "dependencies": { - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", @@ -4294,14 +4467,22 @@ "dev": true }, "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, "is-docker": { @@ -4311,13 +4492,10 @@ "dev": true }, "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true }, "is-extglob": { "version": "2.1.1", @@ -4346,55 +4524,24 @@ "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, "is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", "dev": true }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -4416,12 +4563,6 @@ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "dev": true }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, "is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", @@ -4474,9 +4615,9 @@ }, "dependencies": { "is-docker": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", - "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", "dev": true } } @@ -4504,28 +4645,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "dev": true, - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - }, - "dependencies": { - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - } - } - }, "isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", @@ -4763,40 +4882,26 @@ "dev": true }, "json-refs": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-2.1.7.tgz", - "integrity": "sha1-uesB/in16j6Sh48VrqEK04taz4k=", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz", + "integrity": "sha512-0vOQd9eLNBL18EGl5yYaO44GhixmImes2wiYn9Z3sag3QnehWrYWlB9AFtMxCL2Bj3fyxgDYkxGFEU/chlYssw==", "dev": true, "requires": { - "commander": "^2.9.0", - "graphlib": "^2.1.1", - "js-yaml": "^3.8.3", + "commander": "~4.1.1", + "graphlib": "^2.1.8", + "js-yaml": "^3.13.1", + "lodash": "^4.17.15", "native-promise-only": "^0.8.1", - "path-loader": "^1.0.2", - "slash": "^1.0.0", - "uri-js": "^3.0.2" + "path-loader": "^1.0.10", + "slash": "^3.0.0", + "uri-js": "^4.2.2" }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true - }, - "uri-js": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", - "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } } } }, @@ -4904,15 +5009,6 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, "kuler": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", @@ -4922,88 +5018,6 @@ "colornames": "^1.1.1" } }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "^4.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "registry-auth-token": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", - "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - } - } - }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -5168,19 +5182,6 @@ "dev": true, "requires": { "chalk": "^2.4.2" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } } }, "logform": { @@ -5244,9 +5245,9 @@ } }, "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "map-age-cleaner": { @@ -5395,6 +5396,17 @@ "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "mkdirp": { @@ -5407,9 +5419,9 @@ } }, "mocha": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz", - "integrity": "sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", + "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -5468,15 +5480,15 @@ } }, "mocha-param": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mocha-param/-/mocha-param-2.0.0.tgz", - "integrity": "sha512-fSdhAkOEEqGMO6MgyBwFD1/NzXaPSELZuz8I0sAKbd4CJRd2LKJpUQKlyX4VST4mT2zxn7Yh+Ek9GNVZTvdAXQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mocha-param/-/mocha-param-2.0.1.tgz", + "integrity": "sha512-TDrDAChx9XtkGmRKWGOzMoQefwHsfYUxyjNWgkfAze+EFRIRT28yJVcpcNhw9iWg2NvfeMQZnSwWCNMYwPxZew==", "dev": true }, "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.28.0.tgz", + "integrity": "sha512-Z5KOjYmnHyd/ukynmFd/WwyXHd7L4J9vTI/nn5Ap9AVUgaAE15VvQ9MOGmJJygEUklupqIrFnor/tjTwRU+tQw==", "dev": true }, "ms": { @@ -5485,6 +5497,12 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, "nanoid": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", @@ -5517,17 +5535,17 @@ "dev": true }, "ncjsm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.0.1.tgz", - "integrity": "sha512-gxh5Sgait8HyclaulfhgetHQGyhFm00ZQqISIfqtwFVnyWJ20rk+55SUamo9n3KhM6Vk63gemKPxIDYiSV/xZw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.1.0.tgz", + "integrity": "sha512-YElRGtbz5iIartetOI3we+XAkcGE29F0SdNC0qRy500/u4WceQd2z9Nhlx24OHmIDIKz9MHdJwf/fkSG0hdWcQ==", "dev": true, "requires": { "builtin-modules": "^3.1.0", "deferred": "^0.7.11", - "es5-ext": "^0.10.51", + "es5-ext": "^0.10.53", "es6-set": "^0.1.5", "find-requires": "^1.0.0", - "fs2": "^0.3.6", + "fs2": "^0.3.8", "type": "^2.0.0" }, "dependencies": { @@ -5746,49 +5764,12 @@ "is-descriptor": "^0.1.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -5885,6 +5866,23 @@ "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=", "dev": true }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + } + } + }, "open": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/open/-/open-7.2.1.tgz", @@ -6095,6 +6093,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -6107,12 +6111,6 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -6200,6 +6198,12 @@ "find-up": "^3.0.0" } }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6271,9 +6275,9 @@ }, "dependencies": { "@types/node": { - "version": "13.13.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.17.tgz", - "integrity": "sha512-rGZftvdDpsYtG/rOlDOwny1f6Aq4FHJdGSVfPg5vC2DaR9Rt4W2OpsOF5GTU2bSqZmwTkfnsvJhhzpMWYxxlEA==", + "version": "13.13.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.19.tgz", + "integrity": "sha512-IVsULCpTdafcHhBDLYEPnV5l15xV0q065zvOHC1ZmzFYaBCMzku078eXnazoSG8907vZjRgEN/EQjku7GwwFyQ==", "dev": true } } @@ -6413,9 +6417,9 @@ } }, "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", "dev": true }, "regex-not": { @@ -6429,9 +6433,9 @@ } }, "registry-auth-token": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", - "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", + "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", "dev": true, "requires": { "rc": "^1.2.8" @@ -6455,6 +6459,18 @@ "es6-error": "^4.0.1" } }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, "replaceall": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/replaceall/-/replaceall-0.1.6.tgz", @@ -6462,9 +6478,9 @@ "dev": true }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -6474,7 +6490,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -6484,37 +6500,47 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } } } }, "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "lodash": "^4.13.1" + "lodash": "^4.17.19" } }, "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "dev": true, "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "require-directory": { @@ -6559,6 +6585,16 @@ "lowercase-keys": "^1.0.0" } }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -6593,9 +6629,9 @@ "dev": true }, "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -6634,23 +6670,12 @@ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", "dev": true, "requires": { - "commander": "~2.8.1" - }, - "dependencies": { - "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - } + "commander": "^2.8.1" } }, "semver": { @@ -6659,15 +6684,6 @@ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "^5.0.3" - } - }, "semver-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", @@ -6675,274 +6691,86 @@ "dev": true }, "serverless": { - "version": "1.70.1", - "resolved": "https://registry.npmjs.org/serverless/-/serverless-1.70.1.tgz", - "integrity": "sha512-2HU2wVKG3FKQQax8LuZDi35NutL8Gd7wq9YPuqs/S1cnM3HNsesptxAnUzz73dtUxu8d3tkVXvlqgpKd2RN1/A==", - "dev": true, - "requires": { - "@serverless/cli": "^1.4.0", - "@serverless/components": "^2.30.10", - "@serverless/enterprise-plugin": "^3.6.11", + "version": "1.83.0", + "resolved": "https://registry.npmjs.org/serverless/-/serverless-1.83.0.tgz", + "integrity": "sha512-w/74YcSjJfR3osNMf4/EAAAIfzzI7reW3cDSHcwZeTOXQ//CCeAHy4XKhAXYa50tzRJVV8OUDt1RuXsZz7YbJQ==", + "dev": true, + "requires": { + "@serverless/cli": "^1.5.2", + "@serverless/components": "^2.34.9", + "@serverless/enterprise-plugin": "^3.8.4", + "@serverless/inquirer": "^1.1.2", + "@serverless/utils": "^1.2.0", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2", "archiver": "^3.1.1", - "async": "^1.5.2", - "aws-sdk": "^2.673.0", + "aws-sdk": "^2.749.0", "bluebird": "^3.7.2", "boxen": "^3.2.0", "cachedir": "^2.3.0", "chalk": "^2.4.2", "child-process-ext": "^2.1.1", - "ci-info": "^2.0.0", "d": "^1.0.1", - "dayjs": "^1.8.26", + "dayjs": "^1.8.35", "decompress": "^4.2.1", "download": "^7.1.0", "essentials": "^1.1.1", "fast-levenshtein": "^2.0.6", "filesize": "^3.6.1", - "fs-extra": "^0.30.0", + "fs-extra": "^8.1.0", "get-stdin": "^6.0.0", - "globby": "^6.1.0", + "globby": "^9.2.0", "graceful-fs": "^4.2.4", "https-proxy-agent": "^5.0.0", - "inquirer": "^6.5.2", "is-docker": "^1.1.0", "is-wsl": "^2.2.0", - "js-yaml": "^3.13.1", + "js-yaml": "^3.14.0", "json-cycle": "^1.3.0", - "json-refs": "^2.1.7", + "json-refs": "^3.0.15", "jwt-decode": "^2.2.0", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "memoizee": "^0.4.14", "mkdirp": "^0.5.4", "nanomatch": "^1.2.13", - "ncjsm": "^4.0.1", - "node-fetch": "^2.6.0", + "ncjsm": "^4.1.0", + "node-fetch": "^2.6.1", "object-hash": "^2.0.3", "p-limit": "^2.3.0", "promise-queue": "^2.2.5", "rc": "^1.2.8", "replaceall": "^0.1.6", - "semver": "^5.7.1", + "semver": "^6.3.0", "semver-regex": "^2.0.0", "stream-promise": "^3.2.0", "tabtab": "^3.0.2", + "timers-ext": "^0.1.7", + "type": "^2.1.0", "untildify": "^3.0.3", - "update-notifier": "^2.5.0", - "uuid": "^8.0.0", + "uuid": "^3.4.0", "write-file-atomic": "^2.4.3", "yaml-ast-parser": "0.0.43", "yargs-parser": "^18.1.3" }, "dependencies": { "@serverless/cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@serverless/cli/-/cli-1.4.0.tgz", - "integrity": "sha512-YqlCiYmRFeGksw6XJaXbigIDlktc7OfRuVpyPB7IZgkCJ9mUlBmvyWdwqJEQdkUz0xPTGsd4Jd/XSrwyiw1Brg==", - "dev": true, - "requires": { - "@serverless/core": "^1.0.0", - "@serverless/template": "^1.1.0", - "ansi-escapes": "^4.2.0", - "chalk": "^2.4.2", - "chokidar": "^3.0.2", - "dotenv": "^8.0.0", - "figures": "^3.0.0", - "minimist": "^1.2.0", - "prettyoutput": "^1.2.0", - "strip-ansi": "^5.2.0" - } - }, - "@serverless/components": { - "version": "2.34.9", - "resolved": "https://registry.npmjs.org/@serverless/components/-/components-2.34.9.tgz", - "integrity": "sha512-qFjIeGgR4SjS32Tbl4BvoxOtLpv3Vx4s/81HdmmpdIrMPe7ePGUfkBVBu3axxAXHf4ajlb4WC1HmhTmZAHHSLQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@serverless/cli/-/cli-1.5.2.tgz", + "integrity": "sha512-FMACx0qPD6Uj8U+7jDmAxEe1tdF9DsuY5VsG45nvZ3olC9xYJe/PMwxWsjXfK3tg1HUNywYAGCsy7p5fdXhNzw==", "dev": true, "requires": { - "@serverless/inquirer": "^1.1.2", - "@serverless/platform-client": "^1.1.3", - "@serverless/platform-client-china": "^1.0.37", - "@serverless/platform-sdk": "^2.3.1", + "@serverless/core": "^1.1.2", + "@serverless/template": "^1.1.3", "@serverless/utils": "^1.2.0", - "adm-zip": "^0.4.16", "ansi-escapes": "^4.3.1", "chalk": "^2.4.2", - "child-process-ext": "^2.1.1", "chokidar": "^3.4.1", "dotenv": "^8.2.0", "figures": "^3.2.0", - "fs-extra": "^8.1.0", - "globby": "^10.0.2", - "got": "^9.6.0", - "graphlib": "^2.1.8", - "https-proxy-agent": "^5.0.0", - "ini": "^1.3.5", - "inquirer-autocomplete-prompt": "^1.0.2", - "js-yaml": "^3.14.0", "minimist": "^1.2.5", - "moment": "^2.27.0", - "open": "^7.1.0", "prettyoutput": "^1.2.0", - "ramda": "^0.26.1", - "semver": "^7.3.2", - "stream.pipeline-shim": "^1.1.0", - "strip-ansi": "^5.2.0", - "traverse": "^0.6.6", - "uuid": "^3.4.0", - "ws": "^7.3.1" - }, - "dependencies": { - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "@serverless/platform-client": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-1.1.10.tgz", - "integrity": "sha512-vMCYRdDaqQjPDlny3+mVNy0lr1P6RJ7hVkR2w9Bk783ZB894hobtMrTm8V8OQPwOvlAypmLnQsLPXwRNM+AMsw==", - "dev": true, - "requires": { - "adm-zip": "^0.4.13", - "axios": "^0.19.2", - "https-proxy-agent": "^5.0.0", - "isomorphic-ws": "^4.0.1", - "js-yaml": "^3.13.1", - "jwt-decode": "^2.2.0", - "minimatch": "^3.0.4", - "querystring": "^0.2.0", - "traverse": "^0.6.6", - "ws": "^7.2.1" - } - }, - "@serverless/platform-sdk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@serverless/platform-sdk/-/platform-sdk-2.3.1.tgz", - "integrity": "sha512-EiSizya9bK0+5uae3GH9uXuWAchZplkLO0tWOAXtnU5QWSg5zicANL9jKCw0dyhjUOvbcO0ddhFlG8EGYvJFSA==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "https-proxy-agent": "^4.0.0", - "is-docker": "^1.1.0", - "isomorphic-fetch": "^2.2.1", - "jwt-decode": "^2.2.0", - "opn": "^5.5.0", - "querystring": "^0.2.0", - "ramda": "^0.25.0", - "rc": "^1.2.8", - "regenerator-runtime": "^0.13.1", - "source-map-support": "^0.5.12", - "uuid": "^3.3.2", - "write-file-atomic": "^2.4.2", - "ws": "<7.0.0" - }, - "dependencies": { - "https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, - "requires": { - "agent-base": "5", - "debug": "4" - } - }, - "ramda": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", - "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } + "strip-ansi": "^5.2.0" } }, - "adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true - }, - "agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true - }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -6950,12 +6778,12 @@ "dev": true }, "aws-sdk": { - "version": "2.674.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.674.0.tgz", - "integrity": "sha512-C0hBwsA779y3xbS1AClDcsg8ZBJE+BJC4vt1eHpI2mEbr0/qIwOcR2hl1DjXyp3RwHKoa/LPOTHRSSHDq01PxA==", + "version": "2.752.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.752.0.tgz", + "integrity": "sha512-0/8Pt8/qEgxt02IEvRjinR3cEj1YmmPlJqie4NhCWmmXmI4wDmEb5Em3A2XvU1dNwS0fpQEcuRcaQ/pWi/mScg==", "dev": true, "requires": { - "buffer": "4.9.1", + "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", "jmespath": "0.15.0", @@ -6974,24 +6802,31 @@ } } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "dev": true, "requires": { - "ms": "^2.1.1" + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" } }, "graceful-fs": { @@ -7006,11 +6841,15 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, - "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", - "dev": true + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "p-limit": { "version": "2.3.0", @@ -7031,27 +6870,11 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -7062,15 +6885,9 @@ } }, "uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", - "dev": true - }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, "yargs-parser": { @@ -7117,12 +6934,6 @@ "requires": { "is-extendable": "^0.1.0" } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true } } }, @@ -7142,9 +6953,9 @@ "dev": true }, "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", "dev": true, "requires": { "glob": "^7.0.0", @@ -7265,86 +7076,94 @@ "is-extendable": "^0.1.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-descriptor": "^1.0.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "^6.0.0" } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -7457,9 +7276,9 @@ } }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -7536,9 +7355,9 @@ } }, "split2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.1.1.tgz", - "integrity": "sha512-emNzr1s7ruq4N+1993yht631/JH+jaj0NYBosuKmLcq+JkGQ9MmTw1RB1fGaTCzUuseRIClrlSLHRNYGwWQ58Q==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "requires": { "readable-stream": "^3.0.0" @@ -7560,9 +7379,9 @@ } }, "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -7600,69 +7419,6 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true } } }, @@ -7904,12 +7660,12 @@ } }, "tar-stream": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz", - "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", "dev": true, "requires": { - "bl": "^4.0.1", + "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", @@ -8125,17 +7881,24 @@ "dev": true }, "ts-node": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.1.tgz", - "integrity": "sha512-zER3Js6Iotp31ghen6nKjgX75UOipwTWX9T5fAVmHaaYAizWhOes4uAsLmDC8H51UG5tHL8gNjoa/wLFjo7wtA==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", "dev": true, "requires": { "arg": "^4.1.0", - "arrify": "^1.0.0", - "diff": "^3.1.0", + "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } } }, "tslib": { @@ -8174,9 +7937,9 @@ } }, "tslint-microsoft-contrib": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-6.0.0.tgz", - "integrity": "sha512-R//efwn+34IUjTJeYgNDAJdzG0jyLWIehygPt/PHuZAieTolFVS56FgeFW7DOLap9ghXzMiFPTmDgm54qaL7QA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-6.2.0.tgz", + "integrity": "sha512-6tfi/2tHqV/3CL77pULBcK+foty11Rr0idRDxKnteTaKm6gWF9qmaCNU17HVssOuwlYNyOmd9Jsmjd+1t3a3qw==", "dev": true, "requires": { "tsutils": "^2.27.2 <2.29.0" @@ -8218,9 +7981,9 @@ "dev": true }, "type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", "dev": true }, "type-check": { @@ -8245,9 +8008,9 @@ "dev": true }, "typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", - "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, "uglify-js": { @@ -8278,9 +8041,9 @@ } }, "unbzip2-stream": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz", - "integrity": "sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, "requires": { "buffer": "^5.2.1", @@ -8309,23 +8072,6 @@ "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" } }, "universalify": { @@ -8380,63 +8126,6 @@ "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", "dev": true }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - } - } - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -8544,12 +8233,6 @@ "extsprintf": "^1.2.0" } }, - "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -8723,15 +8406,9 @@ } }, "ws": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", - "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", - "dev": true - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", "dev": true }, "xml2js": { @@ -8865,20 +8542,20 @@ "dev": true }, "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true }, "zip-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", - "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-3.0.1.tgz", + "integrity": "sha512-r+JdDipt93ttDjsOVPU5zaq5bAyY+3H19bDrThkvuVxC0xMQzU1PJcS6D+KrP3u96gH9XLomcHPb+2skoDjulQ==", "dev": true, "requires": { "archiver-utils": "^2.1.0", - "compress-commons": "^2.1.1", - "readable-stream": "^3.4.0" + "compress-commons": "^3.0.0", + "readable-stream": "^3.6.0" } } } diff --git a/package.json b/package.json index fe59da7d..ef6a1b1f 100644 --- a/package.json +++ b/package.json @@ -44,30 +44,30 @@ ] }, "devDependencies": { - "@types/chai": "^4.1.7", - "@types/chai-spies": "^1.0.0", - "@types/mocha": "^5.2.5", - "@types/node": "^12.0.0", + "@types/chai": "^4.2.12", + "@types/chai-spies": "^1.0.2", + "@types/mocha": "^5.2.7", + "@types/node": "^12.12.58", "aws-sdk-mock": "^1.7.0", "chai": "^3.5.0", "chai-spies": "^1.0.0", "istanbul": "^0.4.5", - "mocha": "^7.1.2", - "mocha-param": "^2.0.0", + "mocha": "^7.2.0", + "mocha-param": "^2.0.1", "nyc": "^14.1.1", "randomstring": "^1.1.5", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "serverless": "^1.70.1", - "shelljs": "^0.8.3", - "ts-node": "^8.0.1", + "request": "^2.88.2", + "request-promise-native": "^1.0.9", + "serverless": "^1.83.0", + "shelljs": "^0.8.4", + "ts-node": "^8.10.2", "tslint": "^5.20.1", - "tslint-microsoft-contrib": "^6.0.0", - "typescript": "^3.2.2", + "tslint-microsoft-contrib": "^6.2.0", + "typescript": "^3.9.7", "wrappy": "^1.0.2" }, "dependencies": { - "aws-sdk": "^2.490.0", - "chalk": "^2.4.1" + "aws-sdk": "^2.752.0", + "chalk": "^2.4.2" } } diff --git a/src/aws/cloud-formation-wrapper.ts b/src/aws/cloud-formation-wrapper.ts new file mode 100644 index 00000000..7734444d --- /dev/null +++ b/src/aws/cloud-formation-wrapper.ts @@ -0,0 +1,66 @@ +/** + * Wrapper class for AWS CloudFormation provider + */ + +import {CloudFormation} from "aws-sdk"; +import DomainConfig = require("../DomainConfig"); +import Globals from "../Globals"; +import {getAWSPagedResults, throttledCall} from "../utils"; + +class CloudFormationWrapper { + private readonly provider: CloudFormation; + + constructor(credentials: any) { + this.provider = new CloudFormation(credentials); + } + + /** + * Gets rest API id from CloudFormation stack + */ + public async getApiId(domain: DomainConfig, stackName: string): Promise { + let LogicalResourceId = "ApiGatewayRestApi"; + if (domain.apiType === Globals.apiTypes.http) { + LogicalResourceId = "HttpApi"; + } + if (domain.apiType === Globals.apiTypes.websocket) { + LogicalResourceId = "WebsocketsApi"; + } + + const params = { + LogicalResourceId, + StackName: stackName, + }; + + let response; + try { + response = await throttledCall(this.provider, "describeStackResource", params); + } catch (err) { + throw new Error(`Failed to find CloudFormation resources with an error: ${err}\n`); + } + + const apiId = response.StackResourceDetail.PhysicalResourceId; + if (!apiId) { + throw new Error(`No ApiId associated with CloudFormation stack ${stackName}`); + } + return apiId; + } + + /** + * Gets values by names from cloudformation exports + */ + public async getImportValues(names: string[]): Promise { + const exports = await getAWSPagedResults( + this.provider, + "listExports", + "Exports", + "NextToken", + "NextToken", + {}, + ); + + const filteredExports = exports.filter((item) => names.indexOf(item.Name) !== -1); + return filteredExports.reduce((prev, current) => ({...prev, [current.Name]: current.Value}), {}); + } +} + +export = CloudFormationWrapper; diff --git a/src/index.ts b/src/index.ts index dfa23940..287d405b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,11 @@ "use strict"; import chalk from "chalk"; +import CloudFormationWrapper = require("./aws/cloud-formation-wrapper"); import DomainConfig = require("./DomainConfig"); import DomainInfo = require("./DomainInfo"); import Globals from "./Globals"; -import { ServerlessInstance, ServerlessOptions } from "./types"; +import {ServerlessInstance, ServerlessOptions} from "./types"; import {getAWSPagedResults, sleep, throttledCall} from "./utils"; const certStatuses = ["PENDING_VALIDATION", "ISSUED", "INACTIVE"]; @@ -17,7 +18,7 @@ class ServerlessCustomDomain { public route53: any; public acm: any; public acmRegion: string; - public cloudformation: any; + public cloudFormationWrapper: any; // Serverless specific properties public serverless: ServerlessInstance; @@ -264,7 +265,7 @@ class ServerlessCustomDomain { this.apigateway = new this.serverless.providers.aws.sdk.APIGateway(credentials); this.apigatewayV2 = new this.serverless.providers.aws.sdk.ApiGatewayV2(credentials); this.route53 = new this.serverless.providers.aws.sdk.Route53(credentials); - this.cloudformation = new this.serverless.providers.aws.sdk.CloudFormation(credentials); + this.cloudFormationWrapper = new CloudFormationWrapper(credentials); // Loop over the domain configurations and populate the domains array with DomainConfigs this.domains = []; @@ -290,7 +291,7 @@ class ServerlessCustomDomain { for (const dc of this.domains) { this.acmRegion = dc.endpointType === Globals.endpointTypes.regional ? this.serverless.providers.aws.getRegion() : "us-east-1"; - const acmCredentials = Object.assign({}, credentials, { region: this.acmRegion }); + const acmCredentials = Object.assign({}, credentials, {region: this.acmRegion}); this.acm = new this.serverless.providers.aws.sdk.ACM(acmCredentials); } @@ -348,7 +349,7 @@ class ServerlessCustomDomain { "CertificateSummaryList", "NextToken", "NextToken", - { CertificateStatuses: certStatuses }, + {CertificateStatuses: certStatuses}, ); // The more specific name will be the longest @@ -501,16 +502,16 @@ class ServerlessCustomDomain { // Set up parameters const route53HostedZoneId = await this.getRoute53HostedZoneId(domain); const Changes = ["A", "AAAA"].map((Type) => ({ - Action: action, - ResourceRecordSet: { - AliasTarget: { - DNSName: domain.domainInfo.domainName, - EvaluateTargetHealth: false, - HostedZoneId: domain.domainInfo.hostedZoneId, - }, - Name: domain.givenDomainName, - Type, + Action: action, + ResourceRecordSet: { + AliasTarget: { + DNSName: domain.domainInfo.domainName, + EvaluateTargetHealth: false, + HostedZoneId: domain.domainInfo.hostedZoneId, }, + Name: domain.givenDomainName, + Type, + }, })); const params = { ChangeBatch: { @@ -598,11 +599,11 @@ class ServerlessCustomDomain { "Items", "NextToken", "NextToken", - { DomainName: domain.givenDomainName }, + {DomainName: domain.givenDomainName}, ); for (const mapping of mappings) { if (mapping.ApiId === domain.apiId - || (mapping.ApiMappingKey === domain.basePath && domain.allowPathMatching) ) { + || (mapping.ApiMappingKey === domain.basePath && domain.allowPathMatching)) { return mapping; } } @@ -704,83 +705,45 @@ class ServerlessCustomDomain { } /** - * Gets value by name from cloudformation exports - */ - public async getImportValue(importValueName, nextToken = null): Promise { - const params = nextToken ? { NextToken: nextToken } : {}; - const result = await this.cloudformation.listExports(params).promise(); - const importValue = result.Exports.find((val: any) => val.Name === importValueName); - if (importValue) { - return importValue.Value; - } - - if (result.NextToken) { - return this.getImportValue(importValueName, result.NextToken); - } - - return null; - } - - /** - * Gets rest API id from CloudFormation stack + * Gets rest API id from existing config or CloudFormation stack */ public async getApiId(domain: DomainConfig): Promise { - if (this.serverless.service.provider.apiGateway && this.serverless.service.provider.apiGateway.restApiId) { - if (typeof this.serverless.service.provider.apiGateway.restApiId === "object" && - this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]) { - try { - const importValueName = this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]; - const importValue = await this.getImportValue(importValueName); - if (importValue) { - return importValue; - } - - throw new Error(`Error: CloudFormation ImportValue not found - by ${this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]}\n`); - } catch (err) { - this.logIfDebug(err); - throw new Error(`Error: Failed to find CloudFormation ImportValue - by ${this.serverless.service.provider.apiGateway.restApiId["Fn::ImportValue"]}\n`); - } + const apiGateway = this.serverless.service.provider.apiGateway; + if (apiGateway && apiGateway.restApiId) { + const restApiId = apiGateway.restApiId; + // if string value exists return the value + if (typeof restApiId === "string") { + this.serverless.cli.log(`Mapping custom domain to existing API ${restApiId}.`); + return restApiId; } - - if (typeof this.serverless.service.provider.apiGateway.restApiId === "object") { - throw new Error("Error: Unsupported restApiId object"); + // in case object and Fn::ImportValue try to get restApiId from the CloudFormation exports + if (typeof restApiId === "object" && restApiId["Fn::ImportValue"]) { + const importName = restApiId["Fn::ImportValue"]; + let importValues; + try { + importValues = await this.cloudFormationWrapper.getImportValues([importName]); + } catch (err) { + this.logIfDebug(err, domain.givenDomainName); + throw new Error(`Failed to find CloudFormation ImportValue by ${importName}\n`); + } + if (!importValues[importName]) { + throw new Error(`CloudFormation ImportValue not found by ${importName}\n`); + } + return importValues[importName]; } - - this.serverless.cli.log(`Mapping custom domain to existing API - ${this.serverless.service.provider.apiGateway.restApiId}.`); - return this.serverless.service.provider.apiGateway.restApiId; + // throw an exception in case not supported restApiId + throw new Error("Unsupported apiGateway.restApiId object"); } const stackName = this.serverless.service.provider.stackName || `${this.serverless.service.service}-${domain.stage}`; - let LogicalResourceId = "ApiGatewayRestApi"; - if (domain.apiType === Globals.apiTypes.http) { - LogicalResourceId = "HttpApi"; - } else if (domain.apiType === Globals.apiTypes.websocket) { - LogicalResourceId = "WebsocketsApi"; - } - - const params = { - LogicalResourceId, - StackName: stackName, - }; - - let response; try { - response = await throttledCall(this.cloudformation, "describeStackResource", params); + return await this.cloudFormationWrapper.getApiId(domain, stackName); } catch (err) { this.logIfDebug(err, domain.givenDomainName); - throw new Error(`Error: Failed to find CloudFormation resources for ${domain.givenDomainName}\n`); - } - - const apiId = response.StackResourceDetail.PhysicalResourceId; - if (!apiId) { - throw new Error(`Error: No ApiId associated with CloudFormation stack ${stackName}`); + throw new Error(`Failed to find CloudFormation resources for ${domain.givenDomainName}\n`); } - return apiId; } /** diff --git a/test/integration-tests/apigateway-with-export/serverless.yml b/test/integration-tests/apigateway-with-export/serverless.yml index 5b222260..2aa4584d 100644 --- a/test/integration-tests/apigateway-with-export/serverless.yml +++ b/test/integration-tests/apigateway-with-export/serverless.yml @@ -6,6 +6,7 @@ provider: runtime: nodejs12.x region: us-west-2 endpointType: regional + stage: dev functions: helloWorld: @@ -23,7 +24,7 @@ resources: Value: Ref: ApiGatewayRestApi # Logical ID Export: - Name: api-${opt:stage, self:provider.stage}-restApiId + Name: api-${self:provider.stage}-restApiId-${opt:RANDOM_STRING} RootResource: Description: Main service's API Gateway Root Resource ID Value: @@ -31,14 +32,14 @@ resources: - ApiGatewayRestApi # Logical ID - RootResourceId # Logical ID Export: - Name: api-${opt:stage, self:provider.stage}-RootResourceId + Name: api-${self:provider.stage}-RootResourceId-${opt:RANDOM_STRING} plugins: - serverless-domain-manager custom: customDomain: - stage: ${opt:stage} + stage: ${self:provider.stage} domainName: apigateway-with-export-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} autoDomain: true basePath: hello-world diff --git a/test/integration-tests/apigateway-with-import/serverless.yml b/test/integration-tests/apigateway-with-import/serverless.yml index e658743c..98806baf 100644 --- a/test/integration-tests/apigateway-with-import/serverless.yml +++ b/test/integration-tests/apigateway-with-import/serverless.yml @@ -5,11 +5,12 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 + stage: dev apiGateway: restApiId: - Fn::ImportValue: api-${opt:stage, self:provider.stage}-restApiId + Fn::ImportValue: api-${self:provider.stage}-restApiId-${opt:RANDOM_STRING} restApiRootResourceId: - Fn::ImportValue: api-${opt:stage, self:provider.stage}-RootResourceId + Fn::ImportValue: api-${self:provider.stage}-RootResourceId-${opt:RANDOM_STRING} functions: helloWorld: diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index 9bca7f4a..f0506379 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -106,6 +106,27 @@ const testCases = [ describe("Integration Tests", function() { this.timeout(FIFTEEN_MINUTES); + it("APIGateway with export and import resources", async () => { + const testExportFolder = "apigateway-with-export"; + const testImportFolder = "apigateway-with-import"; + const testURL = `apigateway-with-export-${RANDOM_STRING}.${TEST_DOMAIN}`; + + try { + await utilities.createTempDir(TEMP_DIR, testExportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + await utilities.createTempDir(TEMP_DIR, testImportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + // recreating config for removing last created config ( testImportFolder ) + await utilities.createTempDir(TEMP_DIR, testImportFolder); + await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); + + // recreating config for sls removing ( testExportFolder ) + await utilities.createTempDir(TEMP_DIR, testExportFolder); + await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); + } + }); describe("Configuration Tests", () => { itParam("${value.testDescription}", testCases, async (value) => { @@ -130,24 +151,6 @@ describe("Integration Tests", function() { } } }); - - it("APIGateway with export and import resources", async () => { - const testExportFolder = "apigateway-with-export"; - const testImportFolder = "apigateway-with-import"; - const testURL = `apigateway-with-export-${RANDOM_STRING}.${TEST_DOMAIN}`; - - try { - await utilities.createTempDir(TEMP_DIR, testExportFolder); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - await utilities.createTempDir(TEMP_DIR, testImportFolder); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - } finally { - await utilities.destroyResources(testURL, testImportFolder); - await utilities.destroyResources(testURL, testExportFolder); - } - }); }); describe("Basepath mapping issue tests", () => { diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index d338253c..15cc878c 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -373,7 +373,6 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; @@ -494,7 +493,6 @@ describe("Custom Domain Plugin", () => { domainName: "test_domain", }); plugin.initializeVariables(); - plugin.cloudformation = new aws.CloudFormation(); plugin.apigateway = new aws.APIGateway(); const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); @@ -757,11 +755,10 @@ describe("Custom Domain Plugin", () => { domainName: "test_domain", }); plugin.initializeVariables(); - plugin.cloudformation = new aws.CloudFormation(); const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); - const spy = chai.spy.on(plugin.cloudformation, "describeStackResource"); + const spy = chai.spy.on(plugin.cloudFormationWrapper.provider, "describeStackResource"); const result = await plugin.getApiId(dc); @@ -789,11 +786,10 @@ describe("Custom Domain Plugin", () => { endpointType: "regional", }); plugin.initializeVariables(); - plugin.cloudformation = new aws.CloudFormation(); const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); - const spy = chai.spy.on(plugin.cloudformation, "describeStackResource"); + const spy = chai.spy.on(plugin.cloudFormationWrapper.provider, "describeStackResource"); const result = await plugin.getApiId(dc); expect(result).to.equal("test_http_api_id"); @@ -820,11 +816,10 @@ describe("Custom Domain Plugin", () => { endpointType: "regional", }); plugin.initializeVariables(); - plugin.cloudformation = new aws.CloudFormation(); const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); - const spy = chai.spy.on(plugin.cloudformation, "describeStackResource"); + const spy = chai.spy.on(plugin.cloudFormationWrapper.provider, "describeStackResource"); const result = await plugin.getApiId(dc); expect(result).to.equal("test_ws_api_id"); @@ -849,7 +844,7 @@ describe("Custom Domain Plugin", () => { basePath: "test_basepath", domainName: "test_domain", }); - plugin.cloudformation = new aws.CloudFormation(); + plugin.serverless.service.provider.apiGateway.restApiId = "custom_test_rest_api_id"; const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain); @@ -996,7 +991,7 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); plugin.apigateway = new aws.APIGateway(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); + const spy = chai.spy.on(plugin, "createBasePathMapping"); await plugin.setupBasePathMappings(); @@ -1601,7 +1596,7 @@ describe("Custom Domain Plugin", () => { plugin.apigateway = new aws.APIGateway(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); + plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; @@ -1629,7 +1624,6 @@ describe("Custom Domain Plugin", () => { plugin.apigateway = new aws.APIGateway(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; @@ -1680,7 +1674,6 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; @@ -1729,7 +1722,6 @@ describe("Custom Domain Plugin", () => { plugin.initializeVariables(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.cloudformation = new aws.CloudFormation(); plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; From 995a1d5589ccdff277f10ffa3f3e27ffabb7f8d1 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Tue, 15 Sep 2020 18:03:27 +0300 Subject: [PATCH 62/69] fix lint and comment integration test for Fm::import --- test/integration-tests/integration.test.ts | 4 ++-- test/unit-tests/index.test.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts index f0506379..e05412ee 100644 --- a/test/integration-tests/integration.test.ts +++ b/test/integration-tests/integration.test.ts @@ -106,7 +106,7 @@ const testCases = [ describe("Integration Tests", function() { this.timeout(FIFTEEN_MINUTES); - it("APIGateway with export and import resources", async () => { +/* it("APIGateway with export and import resources", async () => { const testExportFolder = "apigateway-with-export"; const testImportFolder = "apigateway-with-import"; const testURL = `apigateway-with-export-${RANDOM_STRING}.${TEST_DOMAIN}`; @@ -126,7 +126,7 @@ describe("Integration Tests", function() { await utilities.createTempDir(TEMP_DIR, testExportFolder); await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); } - }); + });*/ describe("Configuration Tests", () => { itParam("${value.testDescription}", testCases, async (value) => { diff --git a/test/unit-tests/index.test.ts b/test/unit-tests/index.test.ts index 15cc878c..0167a291 100644 --- a/test/unit-tests/index.test.ts +++ b/test/unit-tests/index.test.ts @@ -1597,7 +1597,6 @@ describe("Custom Domain Plugin", () => { plugin.apigateway = new aws.APIGateway(); plugin.apigatewayV2 = new aws.ApiGatewayV2(); - plugin.domains[0].apiMapping = {ApiMappingId: "test_mapping_id"}; const spy = chai.spy.on(plugin.apigatewayV2, "getDomainName"); From 2451c24c13a93f79ee8aeaf4321afc55977fa513 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Tue, 15 Sep 2020 21:48:27 +0300 Subject: [PATCH 63/69] Improvement, update integration tests --- README.md | 2 +- package.json | 2 +- src/aws/cloud-formation-wrapper.ts | 3 + src/index.ts | 2 +- test/integration-tests/base.ts | 22 ++ .../integration-tests/disabled/serverless.yml | 24 -- .../serverless.yml | 26 -- test/integration-tests/generic.test.ts | 130 ++++++++++ .../apigateway-with-export/handler.js | 0 .../apigateway-with-export/serverless.yml | 3 +- .../apigateway-with-import/handler.js | 0 .../apigateway-with-import/serverless.yml | 2 +- .../basepath-mapping}/handler.js | 0 .../basepath-mapping/serverless.yml | 0 .../create-domain-idempotent}/handler.js | 0 .../create-domain-idempotent/serverless.yml | 0 .../deploy-idempotent}/handler.js | 0 .../deploy-idempotent/serverless.yml | 0 .../null-basepath-mapping}/handler.js | 0 .../null-basepath-mapping/serverless.yml | 0 test/integration-tests/integration.test.ts | 245 ------------------ .../null-basepath-mapping/handler.js | 16 -- .../regional-tls-1-0/handler.js | 16 -- test/integration-tests/single-cases.test.ts | 121 +++++++++ .../auto-domain}/handler.js | 0 .../auto-domain/serverless.yml | 0 .../enabled-basepath/handler.js | 0 .../enabled-basepath/serverless.yml | 0 .../enabled-custom-apigateway/handler.js | 0 .../enabled-custom-apigateway/serverless.yml | 0 .../enabled-default/handler.js | 0 .../enabled-default/serverless.yml | 0 .../enabled-regional-basepath/handler.js | 0 .../enabled-regional-basepath/serverless.yml | 0 .../handler.js | 0 .../serverless.yml | 0 .../enabled-stage-basepath}/handler.js | 0 .../enabled-stage-basepath/serverless.yml | 0 .../http-api}/handler.js | 0 .../http-api/serverless.yml | 2 +- .../regional-tls-1-0}/handler.js | 0 .../regional-tls-1-0/serverless.yml | 2 +- .../{ => single-cases}/web-socket/handler.js | 0 .../web-socket/serverless.yml | 2 +- 44 files changed, 284 insertions(+), 336 deletions(-) create mode 100644 test/integration-tests/base.ts delete mode 100644 test/integration-tests/disabled/serverless.yml delete mode 100644 test/integration-tests/enabled-regional-empty-basepath/serverless.yml create mode 100644 test/integration-tests/generic.test.ts rename test/integration-tests/{ => generic}/apigateway-with-export/handler.js (100%) rename test/integration-tests/{ => generic}/apigateway-with-export/serverless.yml (98%) rename test/integration-tests/{ => generic}/apigateway-with-import/handler.js (100%) rename test/integration-tests/{ => generic}/apigateway-with-import/serverless.yml (97%) rename test/integration-tests/{auto-domain => generic/basepath-mapping}/handler.js (100%) rename test/integration-tests/{ => generic}/basepath-mapping/serverless.yml (100%) rename test/integration-tests/{basepath-mapping => generic/create-domain-idempotent}/handler.js (100%) rename test/integration-tests/{ => generic}/create-domain-idempotent/serverless.yml (100%) rename test/integration-tests/{create-domain-idempotent => generic/deploy-idempotent}/handler.js (100%) rename test/integration-tests/{ => generic}/deploy-idempotent/serverless.yml (100%) rename test/integration-tests/{deploy-idempotent => generic/null-basepath-mapping}/handler.js (100%) rename test/integration-tests/{ => generic}/null-basepath-mapping/serverless.yml (100%) delete mode 100644 test/integration-tests/integration.test.ts delete mode 100644 test/integration-tests/null-basepath-mapping/handler.js delete mode 100644 test/integration-tests/regional-tls-1-0/handler.js create mode 100644 test/integration-tests/single-cases.test.ts rename test/integration-tests/{disabled => single-cases/auto-domain}/handler.js (100%) rename test/integration-tests/{ => single-cases}/auto-domain/serverless.yml (100%) rename test/integration-tests/{ => single-cases}/enabled-basepath/handler.js (100%) rename test/integration-tests/{ => single-cases}/enabled-basepath/serverless.yml (100%) rename test/integration-tests/{ => single-cases}/enabled-custom-apigateway/handler.js (100%) rename test/integration-tests/{ => single-cases}/enabled-custom-apigateway/serverless.yml (100%) rename test/integration-tests/{ => single-cases}/enabled-default/handler.js (100%) rename test/integration-tests/{ => single-cases}/enabled-default/serverless.yml (100%) rename test/integration-tests/{ => single-cases}/enabled-regional-basepath/handler.js (100%) rename test/integration-tests/{ => single-cases}/enabled-regional-basepath/serverless.yml (100%) rename test/integration-tests/{enabled-regional-empty-basepath => single-cases/enabled-regional-stage-basepath}/handler.js (100%) rename test/integration-tests/{ => single-cases}/enabled-regional-stage-basepath/serverless.yml (100%) rename test/integration-tests/{enabled-regional-stage-basepath => single-cases/enabled-stage-basepath}/handler.js (100%) rename test/integration-tests/{ => single-cases}/enabled-stage-basepath/serverless.yml (100%) rename test/integration-tests/{enabled-stage-basepath => single-cases/http-api}/handler.js (100%) rename test/integration-tests/{ => single-cases}/http-api/serverless.yml (97%) rename test/integration-tests/{http-api => single-cases/regional-tls-1-0}/handler.js (100%) rename test/integration-tests/{ => single-cases}/regional-tls-1-0/serverless.yml (97%) rename test/integration-tests/{ => single-cases}/web-socket/handler.js (100%) rename test/integration-tests/{ => single-cases}/web-socket/serverless.yml (97%) diff --git a/README.md b/README.md index 6eb0f6b2..c931923b 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ npm install ``` ## Writing Integration Tests -Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `integration.test.ts`. +Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `single-cases.test.ts` or create a separate one with the `test.ts` ending. ## Changing API Types AWS API Gateway has three different API types: REST, HTTP, and WebSocket. Special steps need to be taken when migrating from one api type to another. A common migration will be from a REST API to an HTTP API given the potential cost savings. Below are the steps required to change from REST to HTTP. A similar process can be applied for other API type migrations. diff --git a/package.json b/package.json index ef6a1b1f..3a02f57f 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "bin": {}, "scripts": { "test": "nyc mocha -r ts-node/register --project tsconfig.tests.json test/unit-tests/index.test.ts && nyc report --reporter=text-summary", - "integration-test": "nyc mocha -r ts-node/register --project tsconfig.tests.json test/integration-tests/integration.test.ts && nyc report --reporter=text-summary", + "integration-test": "nyc mocha -r ts-node/register --project tsconfig.tests.json test/integration-tests/*.test.ts && nyc report --reporter=text-summary", "lint": "tslint --project . && tslint --project tsconfig.tests.json", "build": "tsc --project ." }, diff --git a/src/aws/cloud-formation-wrapper.ts b/src/aws/cloud-formation-wrapper.ts index 7734444d..b79e264d 100644 --- a/src/aws/cloud-formation-wrapper.ts +++ b/src/aws/cloud-formation-wrapper.ts @@ -58,7 +58,10 @@ class CloudFormationWrapper { {}, ); + // filter Exports by names which we need const filteredExports = exports.filter((item) => names.indexOf(item.Name) !== -1); + // converting a list of unique values to dict + // [{Name: "export-name", Value: "export-value"}, ...] - > {"export-name": "export-value"} return filteredExports.reduce((prev, current) => ({...prev, [current.Name]: current.Value}), {}); } } diff --git a/src/index.ts b/src/index.ts index 287d405b..a088b929 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,7 +18,7 @@ class ServerlessCustomDomain { public route53: any; public acm: any; public acmRegion: string; - public cloudFormationWrapper: any; + public cloudFormationWrapper: CloudFormationWrapper; // Serverless specific properties public serverless: ServerlessInstance; diff --git a/test/integration-tests/base.ts b/test/integration-tests/base.ts new file mode 100644 index 00000000..19420b24 --- /dev/null +++ b/test/integration-tests/base.ts @@ -0,0 +1,22 @@ +import randomstring = require("randomstring"); + +const TEST_DOMAIN = process.env.TEST_DOMAIN; + +if (!TEST_DOMAIN) { + throw new Error("TEST_DOMAIN environment variable not set"); +} + +const RANDOM_STRING = randomstring.generate({ + capitalization: "lowercase", + charset: "alphanumeric", + length: 5, +}); +const TEMP_DIR = `~/tmp/domain-manager-test-${RANDOM_STRING}`; +const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds + +export { + FIFTEEN_MINUTES, + RANDOM_STRING, + TEMP_DIR, + TEST_DOMAIN, +}; diff --git a/test/integration-tests/disabled/serverless.yml b/test/integration-tests/disabled/serverless.yml deleted file mode 100644 index e0b7a533..00000000 --- a/test/integration-tests/disabled/serverless.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Disabled -service: domain-manager-disabled-${opt:RANDOM_STRING} -provider: - name: aws - runtime: nodejs12.x - region: us-west-2 -functions: - helloWorld: - handler: handler.helloWorld - events: - - http: - path: hello-world - method: get - cors: true -plugins: - - serverless-domain-manager -custom: - customDomain: - domainName: disabled-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} - enabled: false - -package: - exclude: - - node_modules/** diff --git a/test/integration-tests/enabled-regional-empty-basepath/serverless.yml b/test/integration-tests/enabled-regional-empty-basepath/serverless.yml deleted file mode 100644 index 6ecbba34..00000000 --- a/test/integration-tests/enabled-regional-empty-basepath/serverless.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Enabled with regional endpoint and empty basepath -service: enabled-regional-empty-basepath-${opt:RANDOM_STRING} -provider: - name: aws - runtime: nodejs12.x - region: us-west-2 - endpointType: regional -functions: - helloWorld: - handler: handler.helloWorld - events: - - http: - path: hello-world - method: get - cors: true -plugins: - - serverless-domain-manager -custom: - customDomain: - domainName: enabled-regional-empty-basepath-${opt:RANDOM_STRING}.${env:TEST_DOMAIN} - basePath: '' - endpointType: regional - -package: - exclude: - - node_modules/** diff --git a/test/integration-tests/generic.test.ts b/test/integration-tests/generic.test.ts new file mode 100644 index 00000000..8fb83197 --- /dev/null +++ b/test/integration-tests/generic.test.ts @@ -0,0 +1,130 @@ +import chai = require("chai"); +import "mocha"; +import {FIFTEEN_MINUTES, RANDOM_STRING, TEMP_DIR, TEST_DOMAIN} from "./base"; +import utilities = require("./test-utilities"); + +const expect = chai.expect; +const CONFIGS_FOLDER = "generic"; + +describe("Integration Tests", function() { + this.timeout(FIFTEEN_MINUTES); + describe("Basepath mapping issue tests", () => { + + it("Creates a empty basepath mapping", async () => { + const testName = "null-basepath-mapping"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("(none)"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Delete domain then recreate", async () => { + const testName = "basepath-mapping"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("api"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Delete domain then remove", async () => { + const testName = "null-basepath-mapping"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("(none)"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("API Gateway with export and import", async () => { + const testExportName = "apigateway-with-export"; + const configExportFolder = `${CONFIGS_FOLDER}/${testExportName}`; + const configImportFolder = `${CONFIGS_FOLDER}/apigateway-with-import`; + const testURL = `${testExportName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configExportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + await utilities.createTempDir(TEMP_DIR, configImportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("hello-world"); + } finally { + // should destroy the last created config folder ( import config ) + await utilities.destroyResources(testURL, RANDOM_STRING); + // recreate config for removing export config + await utilities.createTempDir(TEMP_DIR, configExportFolder); + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + }); + + describe("Idempotency tests", () => { + it("Creates a domain multiple times without failure", async () => { + const testName = "create-domain-idempotent"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Deploys multiple times without failure", async () => { + const testName = "deploy-idempotent"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + }); +}); diff --git a/test/integration-tests/apigateway-with-export/handler.js b/test/integration-tests/generic/apigateway-with-export/handler.js similarity index 100% rename from test/integration-tests/apigateway-with-export/handler.js rename to test/integration-tests/generic/apigateway-with-export/handler.js diff --git a/test/integration-tests/apigateway-with-export/serverless.yml b/test/integration-tests/generic/apigateway-with-export/serverless.yml similarity index 98% rename from test/integration-tests/apigateway-with-export/serverless.yml rename to test/integration-tests/generic/apigateway-with-export/serverless.yml index 2aa4584d..a2973e5a 100644 --- a/test/integration-tests/apigateway-with-export/serverless.yml +++ b/test/integration-tests/generic/apigateway-with-export/serverless.yml @@ -6,7 +6,7 @@ provider: runtime: nodejs12.x region: us-west-2 endpointType: regional - stage: dev + stage: test functions: helloWorld: @@ -46,7 +46,6 @@ custom: endpointType: regional createRoute53Record: false - package: exclude: - node_modules/** diff --git a/test/integration-tests/apigateway-with-import/handler.js b/test/integration-tests/generic/apigateway-with-import/handler.js similarity index 100% rename from test/integration-tests/apigateway-with-import/handler.js rename to test/integration-tests/generic/apigateway-with-import/handler.js diff --git a/test/integration-tests/apigateway-with-import/serverless.yml b/test/integration-tests/generic/apigateway-with-import/serverless.yml similarity index 97% rename from test/integration-tests/apigateway-with-import/serverless.yml rename to test/integration-tests/generic/apigateway-with-import/serverless.yml index 98806baf..a7354049 100644 --- a/test/integration-tests/apigateway-with-import/serverless.yml +++ b/test/integration-tests/generic/apigateway-with-import/serverless.yml @@ -5,7 +5,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 - stage: dev + stage: test apiGateway: restApiId: Fn::ImportValue: api-${self:provider.stage}-restApiId-${opt:RANDOM_STRING} diff --git a/test/integration-tests/auto-domain/handler.js b/test/integration-tests/generic/basepath-mapping/handler.js similarity index 100% rename from test/integration-tests/auto-domain/handler.js rename to test/integration-tests/generic/basepath-mapping/handler.js diff --git a/test/integration-tests/basepath-mapping/serverless.yml b/test/integration-tests/generic/basepath-mapping/serverless.yml similarity index 100% rename from test/integration-tests/basepath-mapping/serverless.yml rename to test/integration-tests/generic/basepath-mapping/serverless.yml diff --git a/test/integration-tests/basepath-mapping/handler.js b/test/integration-tests/generic/create-domain-idempotent/handler.js similarity index 100% rename from test/integration-tests/basepath-mapping/handler.js rename to test/integration-tests/generic/create-domain-idempotent/handler.js diff --git a/test/integration-tests/create-domain-idempotent/serverless.yml b/test/integration-tests/generic/create-domain-idempotent/serverless.yml similarity index 100% rename from test/integration-tests/create-domain-idempotent/serverless.yml rename to test/integration-tests/generic/create-domain-idempotent/serverless.yml diff --git a/test/integration-tests/create-domain-idempotent/handler.js b/test/integration-tests/generic/deploy-idempotent/handler.js similarity index 100% rename from test/integration-tests/create-domain-idempotent/handler.js rename to test/integration-tests/generic/deploy-idempotent/handler.js diff --git a/test/integration-tests/deploy-idempotent/serverless.yml b/test/integration-tests/generic/deploy-idempotent/serverless.yml similarity index 100% rename from test/integration-tests/deploy-idempotent/serverless.yml rename to test/integration-tests/generic/deploy-idempotent/serverless.yml diff --git a/test/integration-tests/deploy-idempotent/handler.js b/test/integration-tests/generic/null-basepath-mapping/handler.js similarity index 100% rename from test/integration-tests/deploy-idempotent/handler.js rename to test/integration-tests/generic/null-basepath-mapping/handler.js diff --git a/test/integration-tests/null-basepath-mapping/serverless.yml b/test/integration-tests/generic/null-basepath-mapping/serverless.yml similarity index 100% rename from test/integration-tests/null-basepath-mapping/serverless.yml rename to test/integration-tests/generic/null-basepath-mapping/serverless.yml diff --git a/test/integration-tests/integration.test.ts b/test/integration-tests/integration.test.ts deleted file mode 100644 index e05412ee..00000000 --- a/test/integration-tests/integration.test.ts +++ /dev/null @@ -1,245 +0,0 @@ -import chai = require("chai"); -import "mocha"; -import itParam = require("mocha-param"); -import randomstring = require("randomstring"); -import utilities = require("./test-utilities"); - -const expect = chai.expect; - -const TEST_DOMAIN = process.env.TEST_DOMAIN; - -if (!TEST_DOMAIN) { - throw new Error("TEST_DOMAIN environment variable not set"); -} - -const FIFTEEN_MINUTES = 15 * 60 * 1000; // 15 minutes in milliseconds -const RANDOM_STRING = randomstring.generate({ - capitalization: "lowercase", - charset: "alphanumeric", - length: 5, -}); -const TEMP_DIR = `~/tmp/domain-manager-test-${RANDOM_STRING}`; - -const testCases = [ - { - testBasePath: "(none)", - testDescription: "Creates domain as part of deploy", - testDomain: `auto-domain-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "EDGE", - testFolder: "auto-domain", - testStage: "test", - }, - { - testBasePath: "(none)", - testDescription: "Enabled with default values", - testDomain: `enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "EDGE", - testFolder: "enabled-default", - testStage: "dev", - }, - { - createApiGateway: true, - testBasePath: "(none)", - testDescription: "Enabled with custom api gateway", - testDomain: `enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "EDGE", - testFolder: "enabled-custom-apigateway", - testStage: "dev", - }, - { - testBasePath: "api", - testDescription: "Enabled with custom basepath", - testDomain: `enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "EDGE", - testFolder: "enabled-basepath", - testStage: "dev", - }, - { - testBasePath: "(none)", - testDescription: "Enabled with custom stage and empty basepath", - testDomain: `enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "EDGE", - testFolder: "enabled-stage-basepath", - testStage: "test", - }, - { - testBasePath: "api", - testDescription: "Enabled with regional endpoint, custom basePath", - testDomain: `enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "REGIONAL", - testFolder: "enabled-regional-basepath", - testStage: "dev", - }, - { - testBasePath: "(none)", - testDescription: "Enabled with regional endpoint, custom stage, empty basepath", - testDomain: `enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "REGIONAL", - testFolder: "enabled-regional-stage-basepath", - testStage: "test", - }, - { - testBasePath: "(none)", - testDescription: "Create Web socket API and domain name", - testDomain: `web-socket-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "REGIONAL", - testFolder: "web-socket", - testStage: "dev", - }, - { - testBasePath: "(none)", - testDescription: "Create HTTP API and domain name", - testDomain: `http-api-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "REGIONAL", - testFolder: "http-api", - testStage: "$default", - }, - { - testBasePath: "(none)", - testDescription: "Deploy regional domain with TLS 1.0", - testDomain: `regional-tls-1-0-${RANDOM_STRING}.${TEST_DOMAIN}`, - testEndpoint: "REGIONAL", - testFolder: "regional-tls-1-0", - testStage: "dev", - }, -]; - -describe("Integration Tests", function() { - this.timeout(FIFTEEN_MINUTES); -/* it("APIGateway with export and import resources", async () => { - const testExportFolder = "apigateway-with-export"; - const testImportFolder = "apigateway-with-import"; - const testURL = `apigateway-with-export-${RANDOM_STRING}.${TEST_DOMAIN}`; - - try { - await utilities.createTempDir(TEMP_DIR, testExportFolder); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - await utilities.createTempDir(TEMP_DIR, testImportFolder); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - // recreating config for removing last created config ( testImportFolder ) - await utilities.createTempDir(TEMP_DIR, testImportFolder); - await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - - // recreating config for sls removing ( testExportFolder ) - await utilities.createTempDir(TEMP_DIR, testExportFolder); - await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - } - });*/ - - describe("Configuration Tests", () => { - itParam("${value.testDescription}", testCases, async (value) => { - let restApiInfo; - if (value.createApiGateway) { - restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); - } - try { - await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING); - const stage = await utilities.getStage(value.testDomain); - expect(stage).to.equal(value.testStage); - - const basePath = await utilities.getBasePath(value.testDomain); - expect(basePath).to.equal(value.testBasePath); - - const endpoint = await utilities.getEndpointType(value.testDomain); - expect(endpoint).to.equal(value.testEndpoint); - } finally { - await utilities.destroyResources(value.testDomain, RANDOM_STRING); - if (value.createApiGateway) { - await utilities.deleteApiGatewayResources(restApiInfo.restApiId); - } - } - }); - }); - - describe("Basepath mapping issue tests", () => { - it("Creates a empty basepath mapping", async () => { - const testName = "null-basepath-mapping"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Delete domain then recreate", async () => { - const testName = "basepath-mapping"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("api"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Delete domain then remove", async () => { - const testName = "null-basepath-mapping"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - }); - - describe("Idempotency tests", () => { - it("Creates a domain multiple times without failure", async () => { - const testName = "create-domain-idempotent"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Deploys multiple times without failure", async () => { - const testName = "deploy-idempotent"; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - try { - await utilities.createTempDir(TEMP_DIR, testName); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - }); -}); diff --git a/test/integration-tests/null-basepath-mapping/handler.js b/test/integration-tests/null-basepath-mapping/handler.js deleted file mode 100644 index 1bd222d6..00000000 --- a/test/integration-tests/null-basepath-mapping/handler.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -module.exports.helloWorld = (event, context, callback) => { - const response = { - statusCode: 200, - headers: { - "Access-Control-Allow-Origin": "*", // Required for CORS support to work - }, - body: JSON.stringify({ - message: "Go Serverless v1.0! Your function executed successfully!", - input: event, - }), - }; - - callback(null, response); -}; diff --git a/test/integration-tests/regional-tls-1-0/handler.js b/test/integration-tests/regional-tls-1-0/handler.js deleted file mode 100644 index 1bd222d6..00000000 --- a/test/integration-tests/regional-tls-1-0/handler.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -module.exports.helloWorld = (event, context, callback) => { - const response = { - statusCode: 200, - headers: { - "Access-Control-Allow-Origin": "*", // Required for CORS support to work - }, - body: JSON.stringify({ - message: "Go Serverless v1.0! Your function executed successfully!", - input: event, - }), - }; - - callback(null, response); -}; diff --git a/test/integration-tests/single-cases.test.ts b/test/integration-tests/single-cases.test.ts new file mode 100644 index 00000000..3c492fb6 --- /dev/null +++ b/test/integration-tests/single-cases.test.ts @@ -0,0 +1,121 @@ +import chai = require("chai"); +import "mocha"; +import itParam = require("mocha-param"); +import {FIFTEEN_MINUTES, RANDOM_STRING, TEST_DOMAIN} from "./base"; +import utilities = require("./test-utilities"); + +const expect = chai.expect; +const CONFIGS_FOLDER = "single-cases"; + +const testCases = [ + { + testBasePath: "(none)", + testDescription: "Creates domain as part of deploy", + testDomain: `auto-domain-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: `${CONFIGS_FOLDER}/auto-domain`, + testStage: "test", + }, + { + testBasePath: "(none)", + testDescription: "Enabled with default values", + testDomain: `enabled-default-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: `${CONFIGS_FOLDER}/enabled-default`, + testStage: "test", + }, + { + createApiGateway: true, + testBasePath: "(none)", + testDescription: "Enabled with custom api gateway", + testDomain: `enabled-custom-apigateway-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: `${CONFIGS_FOLDER}/enabled-custom-apigateway`, + testStage: "test", + }, + { + testBasePath: "api", + testDescription: "Enabled with custom basepath", + testDomain: `enabled-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: `${CONFIGS_FOLDER}/enabled-basepath`, + testStage: "test", + }, + { + testBasePath: "(none)", + testDescription: "Enabled with custom stage and empty basepath", + testDomain: `enabled-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "EDGE", + testFolder: `${CONFIGS_FOLDER}/enabled-stage-basepath`, + testStage: "test", + }, + { + testBasePath: "api", + testDescription: "Enabled with regional endpoint, custom basePath", + testDomain: `enabled-regional-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: `${CONFIGS_FOLDER}/enabled-regional-basepath`, + testStage: "test", + }, + { + testBasePath: "(none)", + testDescription: "Enabled with regional endpoint, custom stage, empty basepath", + testDomain: `enabled-regional-stage-basepath-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: `${CONFIGS_FOLDER}/enabled-regional-stage-basepath`, + testStage: "test", + }, + { + testBasePath: "(none)", + testDescription: "Create Web socket API and domain name", + testDomain: `web-socket-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: `${CONFIGS_FOLDER}/web-socket`, + testStage: "test", + }, + { + testBasePath: "(none)", + testDescription: "Create HTTP API and domain name", + testDomain: `http-api-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: `${CONFIGS_FOLDER}/http-api`, + testStage: "$default", + }, + { + testBasePath: "(none)", + testDescription: "Deploy regional domain with TLS 1.0", + testDomain: `regional-tls-1-0-${RANDOM_STRING}.${TEST_DOMAIN}`, + testEndpoint: "REGIONAL", + testFolder: `${CONFIGS_FOLDER}/regional-tls-1-0`, + testStage: "test", + }, +]; + +describe("Integration Tests", function() { + this.timeout(FIFTEEN_MINUTES); + + describe("Configuration Tests", () => { + itParam("${value.testDescription}", testCases, async (value) => { + let restApiInfo; + if (value.createApiGateway) { + restApiInfo = await utilities.setupApiGatewayResources(RANDOM_STRING); + } + try { + await utilities.createResources(value.testFolder, value.testDomain, RANDOM_STRING); + const stage = await utilities.getStage(value.testDomain); + expect(stage).to.equal(value.testStage); + + const basePath = await utilities.getBasePath(value.testDomain); + expect(basePath).to.equal(value.testBasePath); + + const endpoint = await utilities.getEndpointType(value.testDomain); + expect(endpoint).to.equal(value.testEndpoint); + } finally { + await utilities.destroyResources(value.testDomain, RANDOM_STRING); + if (value.createApiGateway) { + await utilities.deleteApiGatewayResources(restApiInfo.restApiId); + } + } + }); + }); +}); diff --git a/test/integration-tests/disabled/handler.js b/test/integration-tests/single-cases/auto-domain/handler.js similarity index 100% rename from test/integration-tests/disabled/handler.js rename to test/integration-tests/single-cases/auto-domain/handler.js diff --git a/test/integration-tests/auto-domain/serverless.yml b/test/integration-tests/single-cases/auto-domain/serverless.yml similarity index 100% rename from test/integration-tests/auto-domain/serverless.yml rename to test/integration-tests/single-cases/auto-domain/serverless.yml diff --git a/test/integration-tests/enabled-basepath/handler.js b/test/integration-tests/single-cases/enabled-basepath/handler.js similarity index 100% rename from test/integration-tests/enabled-basepath/handler.js rename to test/integration-tests/single-cases/enabled-basepath/handler.js diff --git a/test/integration-tests/enabled-basepath/serverless.yml b/test/integration-tests/single-cases/enabled-basepath/serverless.yml similarity index 100% rename from test/integration-tests/enabled-basepath/serverless.yml rename to test/integration-tests/single-cases/enabled-basepath/serverless.yml diff --git a/test/integration-tests/enabled-custom-apigateway/handler.js b/test/integration-tests/single-cases/enabled-custom-apigateway/handler.js similarity index 100% rename from test/integration-tests/enabled-custom-apigateway/handler.js rename to test/integration-tests/single-cases/enabled-custom-apigateway/handler.js diff --git a/test/integration-tests/enabled-custom-apigateway/serverless.yml b/test/integration-tests/single-cases/enabled-custom-apigateway/serverless.yml similarity index 100% rename from test/integration-tests/enabled-custom-apigateway/serverless.yml rename to test/integration-tests/single-cases/enabled-custom-apigateway/serverless.yml diff --git a/test/integration-tests/enabled-default/handler.js b/test/integration-tests/single-cases/enabled-default/handler.js similarity index 100% rename from test/integration-tests/enabled-default/handler.js rename to test/integration-tests/single-cases/enabled-default/handler.js diff --git a/test/integration-tests/enabled-default/serverless.yml b/test/integration-tests/single-cases/enabled-default/serverless.yml similarity index 100% rename from test/integration-tests/enabled-default/serverless.yml rename to test/integration-tests/single-cases/enabled-default/serverless.yml diff --git a/test/integration-tests/enabled-regional-basepath/handler.js b/test/integration-tests/single-cases/enabled-regional-basepath/handler.js similarity index 100% rename from test/integration-tests/enabled-regional-basepath/handler.js rename to test/integration-tests/single-cases/enabled-regional-basepath/handler.js diff --git a/test/integration-tests/enabled-regional-basepath/serverless.yml b/test/integration-tests/single-cases/enabled-regional-basepath/serverless.yml similarity index 100% rename from test/integration-tests/enabled-regional-basepath/serverless.yml rename to test/integration-tests/single-cases/enabled-regional-basepath/serverless.yml diff --git a/test/integration-tests/enabled-regional-empty-basepath/handler.js b/test/integration-tests/single-cases/enabled-regional-stage-basepath/handler.js similarity index 100% rename from test/integration-tests/enabled-regional-empty-basepath/handler.js rename to test/integration-tests/single-cases/enabled-regional-stage-basepath/handler.js diff --git a/test/integration-tests/enabled-regional-stage-basepath/serverless.yml b/test/integration-tests/single-cases/enabled-regional-stage-basepath/serverless.yml similarity index 100% rename from test/integration-tests/enabled-regional-stage-basepath/serverless.yml rename to test/integration-tests/single-cases/enabled-regional-stage-basepath/serverless.yml diff --git a/test/integration-tests/enabled-regional-stage-basepath/handler.js b/test/integration-tests/single-cases/enabled-stage-basepath/handler.js similarity index 100% rename from test/integration-tests/enabled-regional-stage-basepath/handler.js rename to test/integration-tests/single-cases/enabled-stage-basepath/handler.js diff --git a/test/integration-tests/enabled-stage-basepath/serverless.yml b/test/integration-tests/single-cases/enabled-stage-basepath/serverless.yml similarity index 100% rename from test/integration-tests/enabled-stage-basepath/serverless.yml rename to test/integration-tests/single-cases/enabled-stage-basepath/serverless.yml diff --git a/test/integration-tests/enabled-stage-basepath/handler.js b/test/integration-tests/single-cases/http-api/handler.js similarity index 100% rename from test/integration-tests/enabled-stage-basepath/handler.js rename to test/integration-tests/single-cases/http-api/handler.js diff --git a/test/integration-tests/http-api/serverless.yml b/test/integration-tests/single-cases/http-api/serverless.yml similarity index 97% rename from test/integration-tests/http-api/serverless.yml rename to test/integration-tests/single-cases/http-api/serverless.yml index 74903b96..212f168b 100644 --- a/test/integration-tests/http-api/serverless.yml +++ b/test/integration-tests/single-cases/http-api/serverless.yml @@ -3,7 +3,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 - stage: dev + stage: test functions: helloWorld: handler: handler.connect diff --git a/test/integration-tests/http-api/handler.js b/test/integration-tests/single-cases/regional-tls-1-0/handler.js similarity index 100% rename from test/integration-tests/http-api/handler.js rename to test/integration-tests/single-cases/regional-tls-1-0/handler.js diff --git a/test/integration-tests/regional-tls-1-0/serverless.yml b/test/integration-tests/single-cases/regional-tls-1-0/serverless.yml similarity index 97% rename from test/integration-tests/regional-tls-1-0/serverless.yml rename to test/integration-tests/single-cases/regional-tls-1-0/serverless.yml index fc1219d3..ede7818e 100644 --- a/test/integration-tests/regional-tls-1-0/serverless.yml +++ b/test/integration-tests/single-cases/regional-tls-1-0/serverless.yml @@ -4,7 +4,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 - stage: dev + stage: test endpointType: regional functions: diff --git a/test/integration-tests/web-socket/handler.js b/test/integration-tests/single-cases/web-socket/handler.js similarity index 100% rename from test/integration-tests/web-socket/handler.js rename to test/integration-tests/single-cases/web-socket/handler.js diff --git a/test/integration-tests/web-socket/serverless.yml b/test/integration-tests/single-cases/web-socket/serverless.yml similarity index 97% rename from test/integration-tests/web-socket/serverless.yml rename to test/integration-tests/single-cases/web-socket/serverless.yml index d004cb5a..7bbe6f9b 100644 --- a/test/integration-tests/web-socket/serverless.yml +++ b/test/integration-tests/single-cases/web-socket/serverless.yml @@ -3,7 +3,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 - stage: dev + stage: test functions: connect: handler: handler.connect From 7348e0d90f1010f12371873b566aa58810587240 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Tue, 15 Sep 2020 21:50:57 +0300 Subject: [PATCH 64/69] make CloudFormationWrapper.provider publick for tests check --- src/aws/cloud-formation-wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws/cloud-formation-wrapper.ts b/src/aws/cloud-formation-wrapper.ts index b79e264d..ead9f469 100644 --- a/src/aws/cloud-formation-wrapper.ts +++ b/src/aws/cloud-formation-wrapper.ts @@ -8,7 +8,7 @@ import Globals from "../Globals"; import {getAWSPagedResults, throttledCall} from "../utils"; class CloudFormationWrapper { - private readonly provider: CloudFormation; + public provider: CloudFormation; constructor(credentials: any) { this.provider = new CloudFormation(credentials); From 92e8e6388bccd31071bf852416e814f57bc906bf Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Tue, 15 Sep 2020 22:07:13 +0300 Subject: [PATCH 65/69] update integration tests naming --- README.md | 2 +- .../apigateway-with-export/handler.js | 0 .../apigateway-with-export/serverless.yml | 0 .../apigateway-with-import/handler.js | 0 .../apigateway-with-import/serverless.yml | 0 .../basepath-mapping/handler.js | 0 .../basepath-mapping/serverless.yml | 0 .../create-domain-idempotent/handler.js | 0 .../create-domain-idempotent/serverless.yml | 0 .../deploy-idempotent/handler.js | 0 .../deploy-idempotent/serverless.yml | 0 .../null-basepath-mapping/handler.js | 0 .../null-basepath-mapping/serverless.yml | 0 test/integration-tests/basic.test.ts | 126 +++++++++++++++++ .../auto-domain/handler.js | 0 .../auto-domain/serverless.yml | 0 .../enabled-basepath/handler.js | 0 .../enabled-basepath/serverless.yml | 0 .../enabled-custom-apigateway/handler.js | 0 .../enabled-custom-apigateway/serverless.yml | 0 .../enabled-default/handler.js | 0 .../enabled-default/serverless.yml | 0 .../enabled-regional-basepath/handler.js | 0 .../enabled-regional-basepath/serverless.yml | 0 .../handler.js | 0 .../serverless.yml | 0 .../enabled-stage-basepath/handler.js | 0 .../enabled-stage-basepath/serverless.yml | 0 .../http-api/handler.js | 0 .../http-api/serverless.yml | 0 .../regional-tls-1-0/handler.js | 0 .../regional-tls-1-0/serverless.yml | 0 .../web-socket/handler.js | 0 .../web-socket/serverless.yml | 0 .../{single-cases.test.ts => deploy.test.ts} | 2 +- test/integration-tests/generic.test.ts | 130 ------------------ 36 files changed, 128 insertions(+), 132 deletions(-) rename test/integration-tests/{generic => basic-configs}/apigateway-with-export/handler.js (100%) rename test/integration-tests/{generic => basic-configs}/apigateway-with-export/serverless.yml (100%) rename test/integration-tests/{generic => basic-configs}/apigateway-with-import/handler.js (100%) rename test/integration-tests/{generic => basic-configs}/apigateway-with-import/serverless.yml (100%) rename test/integration-tests/{generic => basic-configs}/basepath-mapping/handler.js (100%) rename test/integration-tests/{generic => basic-configs}/basepath-mapping/serverless.yml (100%) rename test/integration-tests/{generic => basic-configs}/create-domain-idempotent/handler.js (100%) rename test/integration-tests/{generic => basic-configs}/create-domain-idempotent/serverless.yml (100%) rename test/integration-tests/{generic => basic-configs}/deploy-idempotent/handler.js (100%) rename test/integration-tests/{generic => basic-configs}/deploy-idempotent/serverless.yml (100%) rename test/integration-tests/{generic => basic-configs}/null-basepath-mapping/handler.js (100%) rename test/integration-tests/{generic => basic-configs}/null-basepath-mapping/serverless.yml (100%) create mode 100644 test/integration-tests/basic.test.ts rename test/integration-tests/{single-cases => deploy-configs}/auto-domain/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/auto-domain/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-basepath/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-basepath/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-custom-apigateway/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-custom-apigateway/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-default/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-default/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-regional-basepath/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-regional-basepath/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-regional-stage-basepath/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-regional-stage-basepath/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-stage-basepath/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/enabled-stage-basepath/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/http-api/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/http-api/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/regional-tls-1-0/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/regional-tls-1-0/serverless.yml (100%) rename test/integration-tests/{single-cases => deploy-configs}/web-socket/handler.js (100%) rename test/integration-tests/{single-cases => deploy-configs}/web-socket/serverless.yml (100%) rename test/integration-tests/{single-cases.test.ts => deploy.test.ts} (99%) delete mode 100644 test/integration-tests/generic.test.ts diff --git a/README.md b/README.md index c931923b..062421aa 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ npm install ``` ## Writing Integration Tests -Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `single-cases.test.ts` or create a separate one with the `test.ts` ending. +Unit tests are found in `test/unit-tests`. Integration tests are found in `test/integration-tests`. Each folder in `tests/integration-tests` contains the serverless-domain-manager configuration being tested. To create a new integration test, create a new folder for the `handler.js` and `serverless.yml` with the same naming convention and update `deploy.test.ts` or create a separate one with the `test.ts` ending. ## Changing API Types AWS API Gateway has three different API types: REST, HTTP, and WebSocket. Special steps need to be taken when migrating from one api type to another. A common migration will be from a REST API to an HTTP API given the potential cost savings. Below are the steps required to change from REST to HTTP. A similar process can be applied for other API type migrations. diff --git a/test/integration-tests/generic/apigateway-with-export/handler.js b/test/integration-tests/basic-configs/apigateway-with-export/handler.js similarity index 100% rename from test/integration-tests/generic/apigateway-with-export/handler.js rename to test/integration-tests/basic-configs/apigateway-with-export/handler.js diff --git a/test/integration-tests/generic/apigateway-with-export/serverless.yml b/test/integration-tests/basic-configs/apigateway-with-export/serverless.yml similarity index 100% rename from test/integration-tests/generic/apigateway-with-export/serverless.yml rename to test/integration-tests/basic-configs/apigateway-with-export/serverless.yml diff --git a/test/integration-tests/generic/apigateway-with-import/handler.js b/test/integration-tests/basic-configs/apigateway-with-import/handler.js similarity index 100% rename from test/integration-tests/generic/apigateway-with-import/handler.js rename to test/integration-tests/basic-configs/apigateway-with-import/handler.js diff --git a/test/integration-tests/generic/apigateway-with-import/serverless.yml b/test/integration-tests/basic-configs/apigateway-with-import/serverless.yml similarity index 100% rename from test/integration-tests/generic/apigateway-with-import/serverless.yml rename to test/integration-tests/basic-configs/apigateway-with-import/serverless.yml diff --git a/test/integration-tests/generic/basepath-mapping/handler.js b/test/integration-tests/basic-configs/basepath-mapping/handler.js similarity index 100% rename from test/integration-tests/generic/basepath-mapping/handler.js rename to test/integration-tests/basic-configs/basepath-mapping/handler.js diff --git a/test/integration-tests/generic/basepath-mapping/serverless.yml b/test/integration-tests/basic-configs/basepath-mapping/serverless.yml similarity index 100% rename from test/integration-tests/generic/basepath-mapping/serverless.yml rename to test/integration-tests/basic-configs/basepath-mapping/serverless.yml diff --git a/test/integration-tests/generic/create-domain-idempotent/handler.js b/test/integration-tests/basic-configs/create-domain-idempotent/handler.js similarity index 100% rename from test/integration-tests/generic/create-domain-idempotent/handler.js rename to test/integration-tests/basic-configs/create-domain-idempotent/handler.js diff --git a/test/integration-tests/generic/create-domain-idempotent/serverless.yml b/test/integration-tests/basic-configs/create-domain-idempotent/serverless.yml similarity index 100% rename from test/integration-tests/generic/create-domain-idempotent/serverless.yml rename to test/integration-tests/basic-configs/create-domain-idempotent/serverless.yml diff --git a/test/integration-tests/generic/deploy-idempotent/handler.js b/test/integration-tests/basic-configs/deploy-idempotent/handler.js similarity index 100% rename from test/integration-tests/generic/deploy-idempotent/handler.js rename to test/integration-tests/basic-configs/deploy-idempotent/handler.js diff --git a/test/integration-tests/generic/deploy-idempotent/serverless.yml b/test/integration-tests/basic-configs/deploy-idempotent/serverless.yml similarity index 100% rename from test/integration-tests/generic/deploy-idempotent/serverless.yml rename to test/integration-tests/basic-configs/deploy-idempotent/serverless.yml diff --git a/test/integration-tests/generic/null-basepath-mapping/handler.js b/test/integration-tests/basic-configs/null-basepath-mapping/handler.js similarity index 100% rename from test/integration-tests/generic/null-basepath-mapping/handler.js rename to test/integration-tests/basic-configs/null-basepath-mapping/handler.js diff --git a/test/integration-tests/generic/null-basepath-mapping/serverless.yml b/test/integration-tests/basic-configs/null-basepath-mapping/serverless.yml similarity index 100% rename from test/integration-tests/generic/null-basepath-mapping/serverless.yml rename to test/integration-tests/basic-configs/null-basepath-mapping/serverless.yml diff --git a/test/integration-tests/basic.test.ts b/test/integration-tests/basic.test.ts new file mode 100644 index 00000000..03bc4a6b --- /dev/null +++ b/test/integration-tests/basic.test.ts @@ -0,0 +1,126 @@ +import chai = require("chai"); +import "mocha"; +import {FIFTEEN_MINUTES, RANDOM_STRING, TEMP_DIR, TEST_DOMAIN} from "./base"; +import utilities = require("./test-utilities"); + +const expect = chai.expect; +const CONFIGS_FOLDER = "basic"; + +describe("Integration Tests", function() { + this.timeout(FIFTEEN_MINUTES); + + it("Creates a empty basepath mapping", async () => { + const testName = "null-basepath-mapping"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("(none)"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Delete domain then recreate", async () => { + const testName = "basepath-mapping"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("api"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Delete domain then remove", async () => { + const testName = "null-basepath-mapping"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("(none)"); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("API Gateway with export and import", async () => { + const testExportName = "apigateway-with-export"; + const configExportFolder = `${CONFIGS_FOLDER}/${testExportName}`; + const configImportFolder = `${CONFIGS_FOLDER}/apigateway-with-import`; + const testURL = `${testExportName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + // Perform sequence of commands to replicate basepath mapping issue + try { + await utilities.createTempDir(TEMP_DIR, configExportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + await utilities.createTempDir(TEMP_DIR, configImportFolder); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + + const basePath = await utilities.getBasePath(testURL); + expect(basePath).to.equal("hello-world"); + } finally { + // should destroy the last created config folder ( import config ) + await utilities.destroyResources(testURL, RANDOM_STRING); + // recreate config for removing export config + await utilities.createTempDir(TEMP_DIR, configExportFolder); + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Creates a domain multiple times without failure", async () => { + const testName = "create-domain-idempotent"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); + + it("Deploys multiple times without failure", async () => { + const testName = "deploy-idempotent"; + const configFolder = `${CONFIGS_FOLDER}/${testName}`; + const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; + try { + await utilities.createTempDir(TEMP_DIR, configFolder); + await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); + } finally { + await utilities.destroyResources(testURL, RANDOM_STRING); + } + }); +}); diff --git a/test/integration-tests/single-cases/auto-domain/handler.js b/test/integration-tests/deploy-configs/auto-domain/handler.js similarity index 100% rename from test/integration-tests/single-cases/auto-domain/handler.js rename to test/integration-tests/deploy-configs/auto-domain/handler.js diff --git a/test/integration-tests/single-cases/auto-domain/serverless.yml b/test/integration-tests/deploy-configs/auto-domain/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/auto-domain/serverless.yml rename to test/integration-tests/deploy-configs/auto-domain/serverless.yml diff --git a/test/integration-tests/single-cases/enabled-basepath/handler.js b/test/integration-tests/deploy-configs/enabled-basepath/handler.js similarity index 100% rename from test/integration-tests/single-cases/enabled-basepath/handler.js rename to test/integration-tests/deploy-configs/enabled-basepath/handler.js diff --git a/test/integration-tests/single-cases/enabled-basepath/serverless.yml b/test/integration-tests/deploy-configs/enabled-basepath/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/enabled-basepath/serverless.yml rename to test/integration-tests/deploy-configs/enabled-basepath/serverless.yml diff --git a/test/integration-tests/single-cases/enabled-custom-apigateway/handler.js b/test/integration-tests/deploy-configs/enabled-custom-apigateway/handler.js similarity index 100% rename from test/integration-tests/single-cases/enabled-custom-apigateway/handler.js rename to test/integration-tests/deploy-configs/enabled-custom-apigateway/handler.js diff --git a/test/integration-tests/single-cases/enabled-custom-apigateway/serverless.yml b/test/integration-tests/deploy-configs/enabled-custom-apigateway/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/enabled-custom-apigateway/serverless.yml rename to test/integration-tests/deploy-configs/enabled-custom-apigateway/serverless.yml diff --git a/test/integration-tests/single-cases/enabled-default/handler.js b/test/integration-tests/deploy-configs/enabled-default/handler.js similarity index 100% rename from test/integration-tests/single-cases/enabled-default/handler.js rename to test/integration-tests/deploy-configs/enabled-default/handler.js diff --git a/test/integration-tests/single-cases/enabled-default/serverless.yml b/test/integration-tests/deploy-configs/enabled-default/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/enabled-default/serverless.yml rename to test/integration-tests/deploy-configs/enabled-default/serverless.yml diff --git a/test/integration-tests/single-cases/enabled-regional-basepath/handler.js b/test/integration-tests/deploy-configs/enabled-regional-basepath/handler.js similarity index 100% rename from test/integration-tests/single-cases/enabled-regional-basepath/handler.js rename to test/integration-tests/deploy-configs/enabled-regional-basepath/handler.js diff --git a/test/integration-tests/single-cases/enabled-regional-basepath/serverless.yml b/test/integration-tests/deploy-configs/enabled-regional-basepath/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/enabled-regional-basepath/serverless.yml rename to test/integration-tests/deploy-configs/enabled-regional-basepath/serverless.yml diff --git a/test/integration-tests/single-cases/enabled-regional-stage-basepath/handler.js b/test/integration-tests/deploy-configs/enabled-regional-stage-basepath/handler.js similarity index 100% rename from test/integration-tests/single-cases/enabled-regional-stage-basepath/handler.js rename to test/integration-tests/deploy-configs/enabled-regional-stage-basepath/handler.js diff --git a/test/integration-tests/single-cases/enabled-regional-stage-basepath/serverless.yml b/test/integration-tests/deploy-configs/enabled-regional-stage-basepath/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/enabled-regional-stage-basepath/serverless.yml rename to test/integration-tests/deploy-configs/enabled-regional-stage-basepath/serverless.yml diff --git a/test/integration-tests/single-cases/enabled-stage-basepath/handler.js b/test/integration-tests/deploy-configs/enabled-stage-basepath/handler.js similarity index 100% rename from test/integration-tests/single-cases/enabled-stage-basepath/handler.js rename to test/integration-tests/deploy-configs/enabled-stage-basepath/handler.js diff --git a/test/integration-tests/single-cases/enabled-stage-basepath/serverless.yml b/test/integration-tests/deploy-configs/enabled-stage-basepath/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/enabled-stage-basepath/serverless.yml rename to test/integration-tests/deploy-configs/enabled-stage-basepath/serverless.yml diff --git a/test/integration-tests/single-cases/http-api/handler.js b/test/integration-tests/deploy-configs/http-api/handler.js similarity index 100% rename from test/integration-tests/single-cases/http-api/handler.js rename to test/integration-tests/deploy-configs/http-api/handler.js diff --git a/test/integration-tests/single-cases/http-api/serverless.yml b/test/integration-tests/deploy-configs/http-api/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/http-api/serverless.yml rename to test/integration-tests/deploy-configs/http-api/serverless.yml diff --git a/test/integration-tests/single-cases/regional-tls-1-0/handler.js b/test/integration-tests/deploy-configs/regional-tls-1-0/handler.js similarity index 100% rename from test/integration-tests/single-cases/regional-tls-1-0/handler.js rename to test/integration-tests/deploy-configs/regional-tls-1-0/handler.js diff --git a/test/integration-tests/single-cases/regional-tls-1-0/serverless.yml b/test/integration-tests/deploy-configs/regional-tls-1-0/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/regional-tls-1-0/serverless.yml rename to test/integration-tests/deploy-configs/regional-tls-1-0/serverless.yml diff --git a/test/integration-tests/single-cases/web-socket/handler.js b/test/integration-tests/deploy-configs/web-socket/handler.js similarity index 100% rename from test/integration-tests/single-cases/web-socket/handler.js rename to test/integration-tests/deploy-configs/web-socket/handler.js diff --git a/test/integration-tests/single-cases/web-socket/serverless.yml b/test/integration-tests/deploy-configs/web-socket/serverless.yml similarity index 100% rename from test/integration-tests/single-cases/web-socket/serverless.yml rename to test/integration-tests/deploy-configs/web-socket/serverless.yml diff --git a/test/integration-tests/single-cases.test.ts b/test/integration-tests/deploy.test.ts similarity index 99% rename from test/integration-tests/single-cases.test.ts rename to test/integration-tests/deploy.test.ts index 3c492fb6..30c80aa5 100644 --- a/test/integration-tests/single-cases.test.ts +++ b/test/integration-tests/deploy.test.ts @@ -5,7 +5,7 @@ import {FIFTEEN_MINUTES, RANDOM_STRING, TEST_DOMAIN} from "./base"; import utilities = require("./test-utilities"); const expect = chai.expect; -const CONFIGS_FOLDER = "single-cases"; +const CONFIGS_FOLDER = "deploy"; const testCases = [ { diff --git a/test/integration-tests/generic.test.ts b/test/integration-tests/generic.test.ts deleted file mode 100644 index 8fb83197..00000000 --- a/test/integration-tests/generic.test.ts +++ /dev/null @@ -1,130 +0,0 @@ -import chai = require("chai"); -import "mocha"; -import {FIFTEEN_MINUTES, RANDOM_STRING, TEMP_DIR, TEST_DOMAIN} from "./base"; -import utilities = require("./test-utilities"); - -const expect = chai.expect; -const CONFIGS_FOLDER = "generic"; - -describe("Integration Tests", function() { - this.timeout(FIFTEEN_MINUTES); - describe("Basepath mapping issue tests", () => { - - it("Creates a empty basepath mapping", async () => { - const testName = "null-basepath-mapping"; - const configFolder = `${CONFIGS_FOLDER}/${testName}`; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, configFolder); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Delete domain then recreate", async () => { - const testName = "basepath-mapping"; - const configFolder = `${CONFIGS_FOLDER}/${testName}`; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, configFolder); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("api"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Delete domain then remove", async () => { - const testName = "null-basepath-mapping"; - const configFolder = `${CONFIGS_FOLDER}/${testName}`; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, configFolder); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeleteDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsRemove(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("(none)"); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("API Gateway with export and import", async () => { - const testExportName = "apigateway-with-export"; - const configExportFolder = `${CONFIGS_FOLDER}/${testExportName}`; - const configImportFolder = `${CONFIGS_FOLDER}/apigateway-with-import`; - const testURL = `${testExportName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - // Perform sequence of commands to replicate basepath mapping issue - try { - await utilities.createTempDir(TEMP_DIR, configExportFolder); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - await utilities.createTempDir(TEMP_DIR, configImportFolder); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - - const basePath = await utilities.getBasePath(testURL); - expect(basePath).to.equal("hello-world"); - } finally { - // should destroy the last created config folder ( import config ) - await utilities.destroyResources(testURL, RANDOM_STRING); - // recreate config for removing export config - await utilities.createTempDir(TEMP_DIR, configExportFolder); - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - }); - - describe("Idempotency tests", () => { - it("Creates a domain multiple times without failure", async () => { - const testName = "create-domain-idempotent"; - const configFolder = `${CONFIGS_FOLDER}/${testName}`; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - try { - await utilities.createTempDir(TEMP_DIR, configFolder); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - - it("Deploys multiple times without failure", async () => { - const testName = "deploy-idempotent"; - const configFolder = `${CONFIGS_FOLDER}/${testName}`; - const testURL = `${testName}-${RANDOM_STRING}.${TEST_DOMAIN}`; - try { - await utilities.createTempDir(TEMP_DIR, configFolder); - await utilities.slsCreateDomain(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - await utilities.slsDeploy(TEMP_DIR, RANDOM_STRING); - } finally { - await utilities.destroyResources(testURL, RANDOM_STRING); - } - }); - }); -}); From 299bbafc9e5f1508b1a8f57e77bc5d5d3224ea60 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Wed, 16 Sep 2020 13:27:58 +0300 Subject: [PATCH 66/69] fix integration tests --- .../{basic-configs => basic}/apigateway-with-export/handler.js | 0 .../apigateway-with-export/serverless.yml | 0 .../{basic-configs => basic}/apigateway-with-import/handler.js | 0 .../apigateway-with-import/serverless.yml | 0 .../{basic-configs => basic}/basepath-mapping/handler.js | 0 .../{basic-configs => basic}/basepath-mapping/serverless.yml | 0 .../create-domain-idempotent/handler.js | 0 .../create-domain-idempotent/serverless.yml | 0 .../{basic-configs => basic}/deploy-idempotent/handler.js | 0 .../{basic-configs => basic}/deploy-idempotent/serverless.yml | 0 .../{basic-configs => basic}/null-basepath-mapping/handler.js | 0 .../null-basepath-mapping/serverless.yml | 0 .../{deploy-configs => deploy}/auto-domain/handler.js | 0 .../{deploy-configs => deploy}/auto-domain/serverless.yml | 0 .../{deploy-configs => deploy}/enabled-basepath/handler.js | 0 .../{deploy-configs => deploy}/enabled-basepath/serverless.yml | 1 + .../enabled-custom-apigateway/handler.js | 0 .../enabled-custom-apigateway/serverless.yml | 1 + .../{deploy-configs => deploy}/enabled-default/handler.js | 0 .../{deploy-configs => deploy}/enabled-default/serverless.yml | 1 + .../enabled-regional-basepath/handler.js | 0 .../enabled-regional-basepath/serverless.yml | 1 + .../enabled-regional-stage-basepath/handler.js | 0 .../enabled-regional-stage-basepath/serverless.yml | 2 +- .../enabled-stage-basepath/handler.js | 0 .../enabled-stage-basepath/serverless.yml | 0 .../{deploy-configs => deploy}/http-api/handler.js | 0 .../{deploy-configs => deploy}/http-api/serverless.yml | 0 .../{deploy-configs => deploy}/regional-tls-1-0/handler.js | 0 .../{deploy-configs => deploy}/regional-tls-1-0/serverless.yml | 0 .../{deploy-configs => deploy}/web-socket/handler.js | 0 .../{deploy-configs => deploy}/web-socket/serverless.yml | 0 32 files changed, 5 insertions(+), 1 deletion(-) rename test/integration-tests/{basic-configs => basic}/apigateway-with-export/handler.js (100%) rename test/integration-tests/{basic-configs => basic}/apigateway-with-export/serverless.yml (100%) rename test/integration-tests/{basic-configs => basic}/apigateway-with-import/handler.js (100%) rename test/integration-tests/{basic-configs => basic}/apigateway-with-import/serverless.yml (100%) rename test/integration-tests/{basic-configs => basic}/basepath-mapping/handler.js (100%) rename test/integration-tests/{basic-configs => basic}/basepath-mapping/serverless.yml (100%) rename test/integration-tests/{basic-configs => basic}/create-domain-idempotent/handler.js (100%) rename test/integration-tests/{basic-configs => basic}/create-domain-idempotent/serverless.yml (100%) rename test/integration-tests/{basic-configs => basic}/deploy-idempotent/handler.js (100%) rename test/integration-tests/{basic-configs => basic}/deploy-idempotent/serverless.yml (100%) rename test/integration-tests/{basic-configs => basic}/null-basepath-mapping/handler.js (100%) rename test/integration-tests/{basic-configs => basic}/null-basepath-mapping/serverless.yml (100%) rename test/integration-tests/{deploy-configs => deploy}/auto-domain/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/auto-domain/serverless.yml (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-basepath/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-basepath/serverless.yml (97%) rename test/integration-tests/{deploy-configs => deploy}/enabled-custom-apigateway/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-custom-apigateway/serverless.yml (97%) rename test/integration-tests/{deploy-configs => deploy}/enabled-default/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-default/serverless.yml (97%) rename test/integration-tests/{deploy-configs => deploy}/enabled-regional-basepath/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-regional-basepath/serverless.yml (97%) rename test/integration-tests/{deploy-configs => deploy}/enabled-regional-stage-basepath/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-regional-stage-basepath/serverless.yml (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-stage-basepath/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/enabled-stage-basepath/serverless.yml (100%) rename test/integration-tests/{deploy-configs => deploy}/http-api/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/http-api/serverless.yml (100%) rename test/integration-tests/{deploy-configs => deploy}/regional-tls-1-0/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/regional-tls-1-0/serverless.yml (100%) rename test/integration-tests/{deploy-configs => deploy}/web-socket/handler.js (100%) rename test/integration-tests/{deploy-configs => deploy}/web-socket/serverless.yml (100%) diff --git a/test/integration-tests/basic-configs/apigateway-with-export/handler.js b/test/integration-tests/basic/apigateway-with-export/handler.js similarity index 100% rename from test/integration-tests/basic-configs/apigateway-with-export/handler.js rename to test/integration-tests/basic/apigateway-with-export/handler.js diff --git a/test/integration-tests/basic-configs/apigateway-with-export/serverless.yml b/test/integration-tests/basic/apigateway-with-export/serverless.yml similarity index 100% rename from test/integration-tests/basic-configs/apigateway-with-export/serverless.yml rename to test/integration-tests/basic/apigateway-with-export/serverless.yml diff --git a/test/integration-tests/basic-configs/apigateway-with-import/handler.js b/test/integration-tests/basic/apigateway-with-import/handler.js similarity index 100% rename from test/integration-tests/basic-configs/apigateway-with-import/handler.js rename to test/integration-tests/basic/apigateway-with-import/handler.js diff --git a/test/integration-tests/basic-configs/apigateway-with-import/serverless.yml b/test/integration-tests/basic/apigateway-with-import/serverless.yml similarity index 100% rename from test/integration-tests/basic-configs/apigateway-with-import/serverless.yml rename to test/integration-tests/basic/apigateway-with-import/serverless.yml diff --git a/test/integration-tests/basic-configs/basepath-mapping/handler.js b/test/integration-tests/basic/basepath-mapping/handler.js similarity index 100% rename from test/integration-tests/basic-configs/basepath-mapping/handler.js rename to test/integration-tests/basic/basepath-mapping/handler.js diff --git a/test/integration-tests/basic-configs/basepath-mapping/serverless.yml b/test/integration-tests/basic/basepath-mapping/serverless.yml similarity index 100% rename from test/integration-tests/basic-configs/basepath-mapping/serverless.yml rename to test/integration-tests/basic/basepath-mapping/serverless.yml diff --git a/test/integration-tests/basic-configs/create-domain-idempotent/handler.js b/test/integration-tests/basic/create-domain-idempotent/handler.js similarity index 100% rename from test/integration-tests/basic-configs/create-domain-idempotent/handler.js rename to test/integration-tests/basic/create-domain-idempotent/handler.js diff --git a/test/integration-tests/basic-configs/create-domain-idempotent/serverless.yml b/test/integration-tests/basic/create-domain-idempotent/serverless.yml similarity index 100% rename from test/integration-tests/basic-configs/create-domain-idempotent/serverless.yml rename to test/integration-tests/basic/create-domain-idempotent/serverless.yml diff --git a/test/integration-tests/basic-configs/deploy-idempotent/handler.js b/test/integration-tests/basic/deploy-idempotent/handler.js similarity index 100% rename from test/integration-tests/basic-configs/deploy-idempotent/handler.js rename to test/integration-tests/basic/deploy-idempotent/handler.js diff --git a/test/integration-tests/basic-configs/deploy-idempotent/serverless.yml b/test/integration-tests/basic/deploy-idempotent/serverless.yml similarity index 100% rename from test/integration-tests/basic-configs/deploy-idempotent/serverless.yml rename to test/integration-tests/basic/deploy-idempotent/serverless.yml diff --git a/test/integration-tests/basic-configs/null-basepath-mapping/handler.js b/test/integration-tests/basic/null-basepath-mapping/handler.js similarity index 100% rename from test/integration-tests/basic-configs/null-basepath-mapping/handler.js rename to test/integration-tests/basic/null-basepath-mapping/handler.js diff --git a/test/integration-tests/basic-configs/null-basepath-mapping/serverless.yml b/test/integration-tests/basic/null-basepath-mapping/serverless.yml similarity index 100% rename from test/integration-tests/basic-configs/null-basepath-mapping/serverless.yml rename to test/integration-tests/basic/null-basepath-mapping/serverless.yml diff --git a/test/integration-tests/deploy-configs/auto-domain/handler.js b/test/integration-tests/deploy/auto-domain/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/auto-domain/handler.js rename to test/integration-tests/deploy/auto-domain/handler.js diff --git a/test/integration-tests/deploy-configs/auto-domain/serverless.yml b/test/integration-tests/deploy/auto-domain/serverless.yml similarity index 100% rename from test/integration-tests/deploy-configs/auto-domain/serverless.yml rename to test/integration-tests/deploy/auto-domain/serverless.yml diff --git a/test/integration-tests/deploy-configs/enabled-basepath/handler.js b/test/integration-tests/deploy/enabled-basepath/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/enabled-basepath/handler.js rename to test/integration-tests/deploy/enabled-basepath/handler.js diff --git a/test/integration-tests/deploy-configs/enabled-basepath/serverless.yml b/test/integration-tests/deploy/enabled-basepath/serverless.yml similarity index 97% rename from test/integration-tests/deploy-configs/enabled-basepath/serverless.yml rename to test/integration-tests/deploy/enabled-basepath/serverless.yml index ca940cc1..3d98e353 100644 --- a/test/integration-tests/deploy-configs/enabled-basepath/serverless.yml +++ b/test/integration-tests/deploy/enabled-basepath/serverless.yml @@ -4,6 +4,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 + stage: test functions: helloWorld: handler: handler.helloWorld diff --git a/test/integration-tests/deploy-configs/enabled-custom-apigateway/handler.js b/test/integration-tests/deploy/enabled-custom-apigateway/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/enabled-custom-apigateway/handler.js rename to test/integration-tests/deploy/enabled-custom-apigateway/handler.js diff --git a/test/integration-tests/deploy-configs/enabled-custom-apigateway/serverless.yml b/test/integration-tests/deploy/enabled-custom-apigateway/serverless.yml similarity index 97% rename from test/integration-tests/deploy-configs/enabled-custom-apigateway/serverless.yml rename to test/integration-tests/deploy/enabled-custom-apigateway/serverless.yml index 86e848b9..0beb4641 100644 --- a/test/integration-tests/deploy-configs/enabled-custom-apigateway/serverless.yml +++ b/test/integration-tests/deploy/enabled-custom-apigateway/serverless.yml @@ -4,6 +4,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 + stage: test apiGateway: restApiId: ${env:REST_API_ID} restApiResources: diff --git a/test/integration-tests/deploy-configs/enabled-default/handler.js b/test/integration-tests/deploy/enabled-default/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/enabled-default/handler.js rename to test/integration-tests/deploy/enabled-default/handler.js diff --git a/test/integration-tests/deploy-configs/enabled-default/serverless.yml b/test/integration-tests/deploy/enabled-default/serverless.yml similarity index 97% rename from test/integration-tests/deploy-configs/enabled-default/serverless.yml rename to test/integration-tests/deploy/enabled-default/serverless.yml index 7a45a8a3..717fda4d 100644 --- a/test/integration-tests/deploy-configs/enabled-default/serverless.yml +++ b/test/integration-tests/deploy/enabled-default/serverless.yml @@ -4,6 +4,7 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 + stage: test functions: helloWorld: handler: handler.helloWorld diff --git a/test/integration-tests/deploy-configs/enabled-regional-basepath/handler.js b/test/integration-tests/deploy/enabled-regional-basepath/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/enabled-regional-basepath/handler.js rename to test/integration-tests/deploy/enabled-regional-basepath/handler.js diff --git a/test/integration-tests/deploy-configs/enabled-regional-basepath/serverless.yml b/test/integration-tests/deploy/enabled-regional-basepath/serverless.yml similarity index 97% rename from test/integration-tests/deploy-configs/enabled-regional-basepath/serverless.yml rename to test/integration-tests/deploy/enabled-regional-basepath/serverless.yml index 09de2585..ccd9c0bd 100644 --- a/test/integration-tests/deploy-configs/enabled-regional-basepath/serverless.yml +++ b/test/integration-tests/deploy/enabled-regional-basepath/serverless.yml @@ -5,6 +5,7 @@ provider: runtime: nodejs12.x region: us-west-2 endpointType: regional + stage: test functions: helloWorld: handler: handler.helloWorld diff --git a/test/integration-tests/deploy-configs/enabled-regional-stage-basepath/handler.js b/test/integration-tests/deploy/enabled-regional-stage-basepath/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/enabled-regional-stage-basepath/handler.js rename to test/integration-tests/deploy/enabled-regional-stage-basepath/handler.js diff --git a/test/integration-tests/deploy-configs/enabled-regional-stage-basepath/serverless.yml b/test/integration-tests/deploy/enabled-regional-stage-basepath/serverless.yml similarity index 100% rename from test/integration-tests/deploy-configs/enabled-regional-stage-basepath/serverless.yml rename to test/integration-tests/deploy/enabled-regional-stage-basepath/serverless.yml index eadc7ba4..f667cd3e 100644 --- a/test/integration-tests/deploy-configs/enabled-regional-stage-basepath/serverless.yml +++ b/test/integration-tests/deploy/enabled-regional-stage-basepath/serverless.yml @@ -4,8 +4,8 @@ provider: name: aws runtime: nodejs12.x region: us-west-2 - stage: test endpointType: regional + stage: test functions: helloWorld: handler: handler.helloWorld diff --git a/test/integration-tests/deploy-configs/enabled-stage-basepath/handler.js b/test/integration-tests/deploy/enabled-stage-basepath/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/enabled-stage-basepath/handler.js rename to test/integration-tests/deploy/enabled-stage-basepath/handler.js diff --git a/test/integration-tests/deploy-configs/enabled-stage-basepath/serverless.yml b/test/integration-tests/deploy/enabled-stage-basepath/serverless.yml similarity index 100% rename from test/integration-tests/deploy-configs/enabled-stage-basepath/serverless.yml rename to test/integration-tests/deploy/enabled-stage-basepath/serverless.yml diff --git a/test/integration-tests/deploy-configs/http-api/handler.js b/test/integration-tests/deploy/http-api/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/http-api/handler.js rename to test/integration-tests/deploy/http-api/handler.js diff --git a/test/integration-tests/deploy-configs/http-api/serverless.yml b/test/integration-tests/deploy/http-api/serverless.yml similarity index 100% rename from test/integration-tests/deploy-configs/http-api/serverless.yml rename to test/integration-tests/deploy/http-api/serverless.yml diff --git a/test/integration-tests/deploy-configs/regional-tls-1-0/handler.js b/test/integration-tests/deploy/regional-tls-1-0/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/regional-tls-1-0/handler.js rename to test/integration-tests/deploy/regional-tls-1-0/handler.js diff --git a/test/integration-tests/deploy-configs/regional-tls-1-0/serverless.yml b/test/integration-tests/deploy/regional-tls-1-0/serverless.yml similarity index 100% rename from test/integration-tests/deploy-configs/regional-tls-1-0/serverless.yml rename to test/integration-tests/deploy/regional-tls-1-0/serverless.yml diff --git a/test/integration-tests/deploy-configs/web-socket/handler.js b/test/integration-tests/deploy/web-socket/handler.js similarity index 100% rename from test/integration-tests/deploy-configs/web-socket/handler.js rename to test/integration-tests/deploy/web-socket/handler.js diff --git a/test/integration-tests/deploy-configs/web-socket/serverless.yml b/test/integration-tests/deploy/web-socket/serverless.yml similarity index 100% rename from test/integration-tests/deploy-configs/web-socket/serverless.yml rename to test/integration-tests/deploy/web-socket/serverless.yml From 7aac75163495ce80f484b24609ef68863501d211 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Wed, 16 Sep 2020 13:33:49 +0300 Subject: [PATCH 67/69] update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c1b37e9..9750ff6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [4.2.1] - 2020-09-14 +## [4.2.1] - 2020-09-16 ### Changed - Added support for using CloudFormation Fn::ImportValue. Thank you @sampsasaarela ([#220](https://github.com/amplify-education/serverless-domain-manager/pull/220)), @rddimon ([#380](https://github.com/amplify-education/serverless-domain-manager/pull/380)) From 508cc301fb704a859208696c6599c714bee50d9b Mon Sep 17 00:00:00 2001 From: Michael McDermott Date: Wed, 16 Sep 2020 11:35:33 -0400 Subject: [PATCH 68/69] fix: include all of dist folder in npm package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a02f57f..572fcd7f 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "*.js", "*.ts", "*.json", - "dist/*.js" + "dist" ], "nyc": { "extension": [ From 8ee14a2c239a8145d0e082684093409844140fc0 Mon Sep 17 00:00:00 2001 From: Dima Revutskyi Date: Wed, 16 Sep 2020 19:18:49 +0300 Subject: [PATCH 69/69] Upgrade the version --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9750ff6e..ed06d71f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [4.2.2] - 2020-09-16 + +### Changed +- Fix for package build. Thank you @michaelgmcd ([#382](https://github.com/amplify-education/serverless-domain-manager/pull/382)) + ## [4.2.1] - 2020-09-16 ### Changed diff --git a/package.json b/package.json index 572fcd7f..f37cf40a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-domain-manager", - "version": "4.2.1", + "version": "4.2.2", "engines": { "node": ">=4.0" },