From 80ceb69c5725e281f95ba658cf2c7464e60d6aba Mon Sep 17 00:00:00 2001 From: Diana Ionita Date: Mon, 5 Dec 2022 19:13:33 +0000 Subject: [PATCH 1/5] Added toggle for whether endpoints inherit CW settings from stage --- package-lock.json | 2 +- package.json | 2 +- src/ApiGatewayCachingSettings.js | 7 ++++++- src/stageCache.js | 34 +++++++++++++++++++++++++------- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index b6c0819..31d6370 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "serverless-api-gateway-caching", - "version": "1.9.0", + "version": "1.10.0-rc2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7852a14..b0677bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-api-gateway-caching", - "version": "1.9.0", + "version": "1.10.0-rc2", "description": "A plugin for the serverless framework which helps with configuring caching for API Gateway endpoints.", "main": "src/apiGatewayCachingPlugin.js", "scripts": { diff --git a/src/ApiGatewayCachingSettings.js b/src/ApiGatewayCachingSettings.js index be0eaeb..aeebad2 100644 --- a/src/ApiGatewayCachingSettings.js +++ b/src/ApiGatewayCachingSettings.js @@ -5,6 +5,7 @@ const DEFAULT_CACHE_CLUSTER_SIZE = '0.5'; const DEFAULT_DATA_ENCRYPTED = false; const DEFAULT_TTL = 3600; const DEFAULT_UNAUTHORIZED_INVALIDATION_REQUEST_STRATEGY = IgnoreWithWarning; +const DEFAULT_INHERIT_CLOUDWATCH_SETTINGS_FROM_STAGE = true; const mapUnauthorizedRequestStrategy = strategy => { if (!strategy) { @@ -92,6 +93,8 @@ class ApiGatewayEndpointCachingSettings { this.path = basePath.concat(this.path); } + this.inheritCloudWatchSettingsFromStage = globalSettings.endpointsInheritCloudWatchSettingsFromStage; + if (!event.http.caching) { this.cachingEnabled = false; return; @@ -160,9 +163,11 @@ class ApiGatewayCachingSettings { this.cacheClusterSize = cachingSettings.clusterSize || DEFAULT_CACHE_CLUSTER_SIZE; this.cacheTtlInSeconds = cachingSettings.ttlInSeconds >= 0 ? cachingSettings.ttlInSeconds : DEFAULT_TTL; this.dataEncrypted = cachingSettings.dataEncrypted || DEFAULT_DATA_ENCRYPTED; - + this.perKeyInvalidation = new PerKeyInvalidationSettings(cachingSettings); + this.endpointsInheritCloudWatchSettingsFromStage = cachingSettings.endpointsInheritCloudWatchSettingsFromStage || DEFAULT_INHERIT_CLOUDWATCH_SETTINGS_FROM_STAGE; + for (let functionName in serverless.service.functions) { let functionSettings = serverless.service.functions[functionName]; for (let event in functionSettings.events) { diff --git a/src/stageCache.js b/src/stageCache.js index 5588536..b7bca61 100644 --- a/src/stageCache.js +++ b/src/stageCache.js @@ -53,7 +53,7 @@ const createPatchForStage = (settings) => { return patch; } -const patchForMethod = (path, method, endpointSettings) => { +const createPatchForMethod = (path, method, endpointSettings, stageState) => { let patchPath = patchPathFor(path, method); let patch = [{ op: 'replace', @@ -86,6 +86,24 @@ const patchForMethod = (path, method, endpointSettings) => { }); } } + + if (endpointSettings.inheritCloudWatchSettingsFromStage) { + patch.push({ + op: 'replace', + path: `/${patchPath}/logging/loglevel`, + value: stageState.methodSettings['*/*'].loggingLevel, + }); + patch.push({ + op: 'replace', + path: `/${patchPath}/logging/dataTrace`, + value: stageState.methodSettings['*/*'].dataTraceEnabled ? 'true' : 'false', + }); + patch.push({ + op: 'replace', + path: `/${patchPath}/metrics/enabled`, + value: stageState.methodSettings['*/*'].metricsEnabled ? 'true' : 'false', + }); + } return patch; } @@ -115,7 +133,7 @@ const httpEventOf = (lambda, endpointSettings) => { return event; } -const createPatchForEndpoint = (endpointSettings, serverless) => { +const createPatchForEndpoint = (endpointSettings, serverless, stageState) => { let lambda = serverless.service.getFunction(endpointSettings.functionName); if (isEmpty(lambda.events)) { serverless.cli.log(`[serverless-api-gateway-caching] Lambda ${endpointSettings.functionName} has not defined events.`); @@ -132,14 +150,14 @@ const createPatchForEndpoint = (endpointSettings, serverless) => { if (method.toUpperCase() == 'ANY') { let httpMethodsToDisableCacheFor = ['DELETE', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT']; // TODO could come from settings, vNext for (let methodWithCacheDisabled of httpMethodsToDisableCacheFor) { - patch = patch.concat(patchForMethod(path, methodWithCacheDisabled, + patch = patch.concat(createPatchForMethod(path, methodWithCacheDisabled, { cachingEnabled: false })); }; - patch = patch.concat(patchForMethod(path, 'GET', endpointSettings)); + patch = patch.concat(createPatchForMethod(path, 'GET', endpointSettings, stageState)); } else { - patch = patch.concat(patchForMethod(path, method, endpointSettings)); + patch = patch.concat(createPatchForMethod(path, method, endpointSettings, stageState)); } return patch; } @@ -190,6 +208,8 @@ const updateStageCacheSettings = async (settings, serverless) => { let restApiId = await retrieveRestApiId(serverless, settings); + let stageState = await serverless.providers.aws.request('APIGateway', 'getStage', { restApiId, stageName: settings.stage }, { region: settings.region }); + let patchOps = createPatchForStage(settings); let endpointsWithCachingEnabled = settings.endpointSettings.filter(e => e.cachingEnabled) @@ -199,13 +219,13 @@ const updateStageCacheSettings = async (settings, serverless) => { } for (let endpointSettings of settings.endpointSettings) { - let endpointPatch = createPatchForEndpoint(endpointSettings, serverless); + let endpointPatch = createPatchForEndpoint(endpointSettings, serverless, stageState); patchOps = patchOps.concat(endpointPatch); } // TODO handle 'ANY' method, if possible for (let additionalEndpointSettings of settings.additionalEndpointSettings) { - let endpointPatch = patchForMethod(additionalEndpointSettings.path, additionalEndpointSettings.method, additionalEndpointSettings); + let endpointPatch = createPatchForMethod(additionalEndpointSettings.path, additionalEndpointSettings.method, additionalEndpointSettings, stageState); patchOps = patchOps.concat(endpointPatch); } From ae64ad7e1dbea64ef1d43fb100f8a1464e6c0427 Mon Sep 17 00:00:00 2001 From: "diana.ionita" Date: Wed, 7 Dec 2022 13:04:12 +0000 Subject: [PATCH 2/5] Added tests --- README.md | 4 + src/ApiGatewayCachingSettings.js | 14 +- test/configuring-a-default-base-path.js | 22 +-- test/creating-settings.js | 40 ++++- ...heriting-cloudwatch-settings-from-stage.js | 81 ++++++++++ test/model/Serverless.js | 145 +++++++++++++----- test/steps/given.js | 6 +- test/steps/when.js | 9 ++ ...cache-settings-for-additional-endpoints.js | 11 +- test/updating-stage-cache-settings.js | 45 +++--- 10 files changed, 290 insertions(+), 87 deletions(-) create mode 100644 test/inheriting-cloudwatch-settings-from-stage.js create mode 100644 test/steps/when.js diff --git a/README.md b/README.md index 33cbfc9..6566984 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ You can use the `apiGatewayCaching` section ("global settings") to quickly confi Cache `clusterSize` can only be specified under global settings, because there's only one cluster per API Gateway stage. +The setting `endpointsInheritCloudWatchSettingsFromStage` makes sure that settings like `Log Level` and whether to `Enable detailed CloudWatch metrics` are copied over from the stage to each endpoint's settings. It is `true` by default. + ```yml plugins: - serverless-api-gateway-caching @@ -76,6 +78,7 @@ custom: perKeyInvalidation: requireAuthorization: true # default is true handleUnauthorizedRequests: Ignore # default is "IgnoreWithWarning". + endpointsInheritCloudWatchSettingsFromStage: true # default is true ``` ### Configuring per-endpoint settings @@ -102,6 +105,7 @@ functions: enabled: true ttlInSeconds: 3600 # overrides the global setting for ttlInSeconds dataEncrypted: true # default is false + inheritCloudWatchSettingsFromStage: false # default is true perKeyInvalidation: requireAuthorization: true # default is true handleUnauthorizedRequests: Fail # default is "IgnoreWithWarning" diff --git a/src/ApiGatewayCachingSettings.js b/src/ApiGatewayCachingSettings.js index aeebad2..77e8062 100644 --- a/src/ApiGatewayCachingSettings.js +++ b/src/ApiGatewayCachingSettings.js @@ -93,7 +93,12 @@ class ApiGatewayEndpointCachingSettings { this.path = basePath.concat(this.path); } - this.inheritCloudWatchSettingsFromStage = globalSettings.endpointsInheritCloudWatchSettingsFromStage; + if (event.http.caching?.inheritCloudWatchSettingsFromStage != undefined) { + this.inheritCloudWatchSettingsFromStage = event.http.caching?.inheritCloudWatchSettingsFromStage; + } + else { + this.inheritCloudWatchSettingsFromStage = globalSettings.endpointsInheritCloudWatchSettingsFromStage; + } if (!event.http.caching) { this.cachingEnabled = false; @@ -117,7 +122,7 @@ class ApiGatewayAdditionalEndpointCachingSettings { constructor(method, path, caching, globalSettings) { this.method = method; this.path = path; - + this.gatewayResourceName = getApiGatewayResourceNameFor(this.path, this.method); if (!caching) { @@ -163,10 +168,11 @@ class ApiGatewayCachingSettings { this.cacheClusterSize = cachingSettings.clusterSize || DEFAULT_CACHE_CLUSTER_SIZE; this.cacheTtlInSeconds = cachingSettings.ttlInSeconds >= 0 ? cachingSettings.ttlInSeconds : DEFAULT_TTL; this.dataEncrypted = cachingSettings.dataEncrypted || DEFAULT_DATA_ENCRYPTED; - + this.perKeyInvalidation = new PerKeyInvalidationSettings(cachingSettings); - this.endpointsInheritCloudWatchSettingsFromStage = cachingSettings.endpointsInheritCloudWatchSettingsFromStage || DEFAULT_INHERIT_CLOUDWATCH_SETTINGS_FROM_STAGE; + this.endpointsInheritCloudWatchSettingsFromStage = cachingSettings.endpointsInheritCloudWatchSettingsFromStage == undefined ? + DEFAULT_INHERIT_CLOUDWATCH_SETTINGS_FROM_STAGE : cachingSettings.endpointsInheritCloudWatchSettingsFromStage; for (let functionName in serverless.service.functions) { let functionSettings = serverless.service.functions[functionName]; diff --git a/test/configuring-a-default-base-path.js b/test/configuring-a-default-base-path.js index f44e59e..00ff90e 100644 --- a/test/configuring-a-default-base-path.js +++ b/test/configuring-a-default-base-path.js @@ -24,22 +24,22 @@ describe('Configuring a default base path', () => { } ]; let settings; - + for (scenario of scenarios) { describe(`and ${scenario.description}`, () => { before(() => { const endpoint = given .a_serverless_function(functionName) .withHttpEndpoint('get', endpointPath, { enabled: true }); - + const serverless = given .a_serverless_instance(serviceName) .withApiGatewayCachingConfig({ basePath: scenario.basePath }) .withFunction(endpoint); - + settings = new ApiGatewayCachingSettings(serverless); }); - + it('should be prepended to each endpoint and form a valid path', () => { expect(path_of(functionName, settings)).to.equal(`/animals${endpointPath}`); }); @@ -52,24 +52,24 @@ describe('Configuring a default base path', () => { const endpoint = given .a_serverless_function(functionName) .withHttpEndpoint('get', endpointPath, { enabled: true }); - + const serverless = given .a_serverless_instance(serviceName) .withApiGatewayCachingConfig() .withFunction(endpoint); - settings = new ApiGatewayCachingSettings(serverless); + settings = new ApiGatewayCachingSettings(serverless); }); - it('should just use the endpoint path', () => { + it('should just use the endpoint path', () => { expect(path_of(functionName, settings)).to.equal(endpointPath); }); }); }); const path_of = (functionName, settings) => { - return settings - .endpointSettings - .find(x => x.functionName === functionName) - .path; + return settings + .endpointSettings + .find(x => x.functionName === functionName) + .path; } diff --git a/test/creating-settings.js b/test/creating-settings.js index 2b2c73a..e5ec689 100644 --- a/test/creating-settings.js +++ b/test/creating-settings.js @@ -70,6 +70,20 @@ describe('Creating settings', () => { }); }); + describe('when the endpointsInheritCloudWatchSettingsFromStage toggle is omitted from Api Gateway caching settings', () => { + before(() => { + serverless = given.a_serverless_instance() + .withApiGatewayCachingConfig(); + serverless.service.custom.apiGatewayCaching.endpointsInheritCloudWatchSettingsFromStage = undefined; + + cacheSettings = createSettingsFor(serverless); + }); + + it('should set endpointsInheritCloudWatchSettingsFromStage to true by default', () => { + expect(cacheSettings.endpointsInheritCloudWatchSettingsFromStage).to.equal(true); + }); + }); + describe('when settings are defined for Api Gateway caching', () => { let scenarios = [ { @@ -618,7 +632,7 @@ describe('Creating settings', () => { endpoint = given.a_serverless_function('list-cats') .withHttpEndpoint('get', '/cat/'); serverless = given.a_serverless_instance() - .withApiGatewayCachingConfig({basePath: '/animals'}) + .withApiGatewayCachingConfig({ basePath: '/animals' }) .withFunction(endpoint); cacheSettings = createSettingsFor(serverless); @@ -745,6 +759,30 @@ describe('Creating settings', () => { expect(cacheSettings.additionalEndpointSettings[0].cacheTtlInSeconds).to.equal(60); }); }); + + describe('when caching config for a http endpoint sets whether to inherit CloudWatch settings from stage', () => { + before(() => { + listEndpoint = given.a_serverless_function('list-cats') + .withHttpEndpoint('get', '/'); + getEndpoint = given.a_serverless_function('get-cat') + .withHttpEndpoint('get', '/cat/{id}', { inheritCloudWatchSettingsFromStage: false }); + serverless = given.a_serverless_instance() + .withApiGatewayCachingConfig() + .withFunction(listEndpoint) + .withFunction(getEndpoint) + serverless.service.custom.apiGatewayCaching.endpointsInheritCloudWatchSettingsFromStage = true; + + cacheSettings = createSettingsFor(serverless); + }); + + it('endpoint settings for whether to inherit CloudWatch settings from stage are correct', () => { + expect(cacheSettings.endpointSettings[0].path).to.equal('/'); + // propagates from global caching settings + expect(cacheSettings.endpointSettings[0].inheritCloudWatchSettingsFromStage).to.equal(true); + expect(cacheSettings.endpointSettings[1].path).to.equal('/cat/{id}'); + expect(cacheSettings.endpointSettings[1].inheritCloudWatchSettingsFromStage).to.equal(false); + }); + }); }); const createSettingsFor = (serverless, options) => { diff --git a/test/inheriting-cloudwatch-settings-from-stage.js b/test/inheriting-cloudwatch-settings-from-stage.js new file mode 100644 index 0000000..2612c14 --- /dev/null +++ b/test/inheriting-cloudwatch-settings-from-stage.js @@ -0,0 +1,81 @@ +const given = require('../test/steps/given'); +const when = require('../test/steps/when'); +const ApiGatewayCachingSettings = require(`../src/ApiGatewayCachingSettings`); +const expect = require('chai').expect; + +describe('Inheriting CloudWatch settings from stage', () => { + const apiGatewayService = 'APIGateway', updateStageMethod = 'updateStage'; + describe('when some endpoints are configured to inherit CloudWatch settings from stage and some are not', () => { + before(async () => { + let restApiId = given.a_rest_api_id(); + let endpointWithInheritedCwSettings = given.a_serverless_function('get-my-cat') + .withHttpEndpoint('get', '/', { inheritCloudWatchSettingsFromStage: true }) + let endpointWithoutInheritedCwSettings = given.a_serverless_function('get-cat-by-paw-id') + .withHttpEndpoint('get', '/cat/{pawId}', { inheritCloudWatchSettingsFromStage: false }) + serverless = given.a_serverless_instance() + .forStage('somestage') + .withRestApiId(restApiId) + .withApiGatewayCachingConfig({ endpointsInheritCloudWatchSettingsFromStage: true }) + .withFunction(endpointWithInheritedCwSettings) + .withFunction(endpointWithoutInheritedCwSettings) + .withStageSettingsForCloudWatchMetrics({ loggingLevel: 'WARN', dataTraceEnabled: false, metricsEnabled: true }); + settings = new ApiGatewayCachingSettings(serverless); + + await when.updating_stage_cache_settings(settings, serverless); + + requestsToAws = serverless.getRequestsToAws(); + }); + + describe('the request sent to AWS SDK to update stage', () => { + before(() => { + apiGatewayRequest = requestsToAws.find(r => r.awsService == apiGatewayService && r.method == updateStageMethod); + }); + + describe('for the endpoint which inherits CloudWatch settings from stage', () => { + it('should set the value of logging/logLevel the same as the stage value of logging/logLevel', () => { + expect(apiGatewayRequest.properties.patchOperations).to.deep.include({ + op: 'replace', + path: '/~1/GET/logging/loglevel', + value: 'WARN' + }); + }); + + it('should set the value of logging/dataTrace the same as the stage value of logging/dataTraceEnabled', () => { + expect(apiGatewayRequest.properties.patchOperations).to.deep.include({ + op: 'replace', + path: '/~1/GET/logging/dataTrace', + value: 'false' + }); + }); + + it('should set the value of metrics/enabled the same as the stage value of metrics/enabled', () => { + expect(apiGatewayRequest.properties.patchOperations).to.deep.include({ + op: 'replace', + path: '/~1/GET/metrics/enabled', + value: 'true' + }); + }); + }); + + describe('for the endpoint which does not inherit CloudWatch settings from stage', () => { + it('should not set the value of logging/logLevel', () => { + let operation = apiGatewayRequest.properties.patchOperations + .find(o => o.path == '/~1cat~1{pawId}/GET/logging/logLevel'); + expect(operation).to.not.exist; + }); + + it('should not set the value of logging/dataTrace', () => { + let operation = apiGatewayRequest.properties.patchOperations + .find(o => o.path == '/~1cat~1{pawId}/GET/logging/dataTrace'); + expect(operation).to.not.exist; + }); + + it('should not set the value of metrics/enabled', () => { + let operation = apiGatewayRequest.properties.patchOperations + .find(o => o.path == '/~1cat~1{pawId}/GET/metrics/enabled'); + expect(operation).to.not.exist; + }); + }); + }); + }); +}); diff --git a/test/model/Serverless.js b/test/model/Serverless.js index ff333cd..7b6272b 100644 --- a/test/model/Serverless.js +++ b/test/model/Serverless.js @@ -1,12 +1,14 @@ class Serverless { constructor(serviceName) { this._logMessages = []; - this._recordedAwsRequests = [] + this._recordedAwsRequests = []; + this._mockedRequestsToAws = []; this.cli = { log: (logMessage) => { this._logMessages.push(logMessage); } }; + this.service = { service: serviceName, custom: {}, @@ -18,7 +20,41 @@ class Serverless { getFunction(functionName) { return this.functions[functionName]; } + }; + + this.providers = { + aws: { + naming: { + getStackName: (stage) => { + if (stage != this.service.provider.stage) { + throw new Error('[Serverless Test Model] Something went wrong getting the Stack Name'); + } + return 'serverless-stack-name'; + } + }, + request: async (awsService, method, properties, stage, region) => { + this._recordedAwsRequests.push({ awsService, method, properties, stage, region }); + + if (awsService == 'APIGateway' && method == 'updateStage') { + return; + } + + const params = { awsService, method, properties, stage, region }; + const mockedFunction = this._mockedRequestsToAws[mockedRequestKeyFor(params)]; + if (!mockedFunction) { + throw new Error(`[Serverless Test Model] No mock found for request to AWS { awsService = ${awsService}, method = ${method}, properties = ${JSON.stringify(properties)}, stage = ${stage}, region = ${region} }`) + } + const mockedResponse = mockedFunction(params); + if (!mockedFunction) { + throw new Error(`[Serverless Test Model] No mock response found for request to AWS { awsService = ${awsService}, method = ${method}, properties = ${JSON.stringify(properties)}, stage = ${stage}, region = ${region} }`) + } + return mockedResponse; + } + } } + + // add default mock for getStage + this._mockedRequestsToAws[mockedRequestKeyFor({ awsService: 'APIGateway', method: 'getStage' })] = defaultMockedRequestToAWS; } forStage(stage) { @@ -31,7 +67,8 @@ class Serverless { return this; } - withApiGatewayCachingConfig({ cachingEnabled = true, clusterSize = '0.5', ttlInSeconds = 45, perKeyInvalidation, dataEncrypted, apiGatewayIsShared, restApiId, basePath } = {}) { + withApiGatewayCachingConfig({ cachingEnabled = true, clusterSize = '0.5', ttlInSeconds = 45, perKeyInvalidation, dataEncrypted, apiGatewayIsShared, + restApiId, basePath, endpointsInheritCloudWatchSettingsFromStage } = {}) { this.service.custom.apiGatewayCaching = { enabled: cachingEnabled, apiGatewayIsShared, @@ -40,7 +77,8 @@ class Serverless { clusterSize, ttlInSeconds, perKeyInvalidation, - dataEncrypted + dataEncrypted, + endpointsInheritCloudWatchSettingsFromStage }; return this; } @@ -84,6 +122,30 @@ class Serverless { return this; } + withStageSettingsForCloudWatchMetrics({ loggingLevel, dataTraceEnabled, metricsEnabled } = {}) { + const expectedAwsService = 'APIGateway'; + const expectedMethod = 'getStage'; + const mockedRequestToAws = ({ awsService, method, properties, stage, region }) => { + if (awsService == 'APIGateway' + && method == 'getStage' + && properties.restApiId == this._restApiId + && properties.stageName == this.service.provider.stage + && region == this.service.provider.region) { + return { + methodSettings: { + ['*/*']: { + loggingLevel, + dataTraceEnabled, + metricsEnabled + } + } + }; + } + }; + this._mockedRequestsToAws[mockedRequestKeyFor({ awsService: expectedAwsService, method: expectedMethod })] = mockedRequestToAws; + return this; + } + withProviderRestApiId(restApiId) { if (!this.service.provider.apiGateway) { this.service.provider.apiGateway = {} @@ -106,37 +168,29 @@ class Serverless { return this.service.provider.compiledCloudFormationTemplate.Resources[methodResourceName]; } - setRestApiId(restApiId, settings) { - this.providers = { - aws: { - naming: { - getStackName: (stage) => { - if (stage != settings.stage) { - throw new Error('[Serverless Test Model] Something went wrong getting the Stack Name'); - } - return 'serverless-stack-name'; - } - }, - request: async (awsService, method, properties, stage, region) => { - this._recordedAwsRequests.push({ awsService, method, properties, stage, region }); - - if (awsService == 'CloudFormation' - && method == 'describeStacks' - && properties.StackName == 'serverless-stack-name' - && stage == settings.stage - && region == settings.region) { - return { - Stacks: [{ - Outputs: [{ - OutputKey: 'RestApiIdForApigCaching', - OutputValue: restApiId - }] - }] - }; - } - } + withRestApiId(restApiId) { + this._restApiId = restApiId; + const expectedAwsService = 'CloudFormation'; + const expectedMethod = 'describeStacks'; + const mockedRequestToAws = ({ awsService, method, properties, stage, region }) => { + if (awsService == 'CloudFormation' + && method == 'describeStacks' + && properties.StackName == 'serverless-stack-name' + && stage == this.service.provider.stage + && region == this.service.provider.region) { + const result = { + Stacks: [{ + Outputs: [{ + OutputKey: 'RestApiIdForApigCaching', + OutputValue: restApiId + }] + }] + }; + return result; } - } + }; + this._mockedRequestsToAws[mockedRequestKeyFor({ awsService: expectedAwsService, method: expectedMethod })] = mockedRequestToAws; + return this; } getRequestsToAws() { @@ -213,14 +267,33 @@ const addFunctionToCompiledCloudFormationTemplate = (serverlessFunction, serverl const addAdditionalEndpointToCompiledCloudFormationTemplate = (additionalEndpoint, serverless) => { const { path, method } = additionalEndpoint; methodResourceName = createMethodResourceNameFor(path, method); - + let methodTemplate = clone(require('./templates/aws-api-gateway-method')); - + methodResourceName = createMethodResourceNameFor(path, method); - + let { Resources } = serverless.service.provider.compiledCloudFormationTemplate; Resources[methodResourceName] = methodTemplate return { additionalEndpoint, methodResourceName } } +const mockedRequestKeyFor = ({ awsService, method }) => { + return `${awsService}-${method}`; +} + +const defaultMockedRequestToAWS = ({ awsService, method, properties, stage, region }) => { + if (awsService == 'APIGateway' + && method == 'getStage') { + return { + methodSettings: { + ['*/*']: { + loggingLevel: 'not set', + dataTraceEnabled: 'not set', + metricsEnabled: 'not set' + } + } + }; + } +}; + module.exports = Serverless; diff --git a/test/steps/given.js b/test/steps/given.js index 95cffc8..15824ca 100644 --- a/test/steps/given.js +++ b/test/steps/given.js @@ -15,15 +15,15 @@ const a_rest_api_id = () => { return chance.guid(); } -const a_rest_api_id_for_deployment = (serverless, settings) => { +const a_rest_api_id_for_deployment = (serverless) => { let restApiId = a_rest_api_id(); - serverless.setRestApiId(restApiId, settings); + serverless = serverless.withRestApiId(restApiId); return restApiId; } const the_rest_api_id_is_not_set_for_deployment = (serverless, settings) => { - serverless.setRestApiId(undefined, settings); + serverless = serverless.withRestApiId(undefined); } const endpoints_with_caching_enabled = (endpointCount) => { diff --git a/test/steps/when.js b/test/steps/when.js new file mode 100644 index 0000000..0ceda71 --- /dev/null +++ b/test/steps/when.js @@ -0,0 +1,9 @@ +const updateStageCacheSettings = require('../../src/stageCache'); + +const updating_stage_cache_settings = async (settings, serverless) => { + return await updateStageCacheSettings(settings, serverless); +} + +module.exports = { + updating_stage_cache_settings +} diff --git a/test/updating-stage-cache-settings-for-additional-endpoints.js b/test/updating-stage-cache-settings-for-additional-endpoints.js index ee4fc34..31bf527 100644 --- a/test/updating-stage-cache-settings-for-additional-endpoints.js +++ b/test/updating-stage-cache-settings-for-additional-endpoints.js @@ -1,4 +1,5 @@ const given = require('../test/steps/given'); +const when = require('../test/steps/when'); const ApiGatewayCachingSettings = require('../src/ApiGatewayCachingSettings'); const updateStageCacheSettings = require('../src/stageCache'); const expect = require('chai').expect; @@ -22,15 +23,15 @@ describe('Updating stage cache settings for additional endpoints defined as Clou caching: { enabled: false } })]; + restApiId = given.a_rest_api_id(); serverless = given.a_serverless_instance() .withApiGatewayCachingConfig() .withAdditionalEndpoints(additionalEndpoints) + .withRestApiId(restApiId) .forStage('somestage'); settings = new ApiGatewayCachingSettings(serverless); - restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -123,7 +124,3 @@ describe('Updating stage cache settings for additional endpoints defined as Clou }); }); }); - -const when_updating_stage_cache_settings = async (settings, serverless) => { - return await updateStageCacheSettings(settings, serverless); -} diff --git a/test/updating-stage-cache-settings.js b/test/updating-stage-cache-settings.js index 4130fd3..e0fca56 100644 --- a/test/updating-stage-cache-settings.js +++ b/test/updating-stage-cache-settings.js @@ -1,8 +1,7 @@ -const APP_ROOT = '..'; -const given = require(`${APP_ROOT}/test/steps/given`); -const ApiGatewayCachingSettings = require(`${APP_ROOT}/src/ApiGatewayCachingSettings`); -const updateStageCacheSettings = require(`${APP_ROOT}/src/stageCache`); -const UnauthorizedCacheControlHeaderStrategy = require(`${APP_ROOT}/src/UnauthorizedCacheControlHeaderStrategy`); +const given = require('../test/steps/given'); +const when = require('../test/steps/when'); +const ApiGatewayCachingSettings = require('../src/ApiGatewayCachingSettings'); +const UnauthorizedCacheControlHeaderStrategy = require('../src/UnauthorizedCacheControlHeaderStrategy'); const expect = require('chai').expect; describe('Updating stage cache settings', () => { @@ -13,7 +12,7 @@ describe('Updating stage cache settings', () => { before(async () => { serverless = given.a_serverless_instance(); settings = new ApiGatewayCachingSettings(serverless); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -34,7 +33,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -89,7 +88,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -117,7 +116,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -229,7 +228,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -272,7 +271,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -350,7 +349,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); }); @@ -583,7 +582,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); apiGatewayRequest = requestsToAws.find(r => r.awsService == apiGatewayService && r.method == updateStageMethod); @@ -616,7 +615,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); apiGatewayRequest = requestsToAws.find(r => r.awsService == apiGatewayService && r.method == updateStageMethod); @@ -663,7 +662,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); apiGatewayRequest = requestsToAws.find(r => r.awsService == apiGatewayService && r.method == updateStageMethod); @@ -694,7 +693,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); apiGatewayRequest = requestsToAws.find(r => r.awsService == apiGatewayService && r.method == updateStageMethod); @@ -722,7 +721,7 @@ describe('Updating stage cache settings', () => { restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); apiGatewayRequest = requestsToAws.find(r => r.awsService == apiGatewayService && r.method == updateStageMethod); @@ -744,8 +743,10 @@ describe('Updating stage cache settings', () => { let endpoints = given.endpoints_with_caching_enabled(23); expectedStageName = 'somestage'; + restApiId = given.a_rest_api_id(); serverless = given.a_serverless_instance() - .withApiGatewayCachingConfig() + .withApiGatewayCachingConfig({ endpointsInheritCloudWatchSettingsFromStage: false }) + .withRestApiId(restApiId) .forStage(expectedStageName); for (let endpoint of endpoints) { serverless = serverless.withFunction(endpoint) @@ -753,9 +754,7 @@ describe('Updating stage cache settings', () => { settings = new ApiGatewayCachingSettings(serverless); - restApiId = await given.a_rest_api_id_for_deployment(serverless, settings); - - await when_updating_stage_cache_settings(settings, serverless); + await when.updating_stage_cache_settings(settings, serverless); requestsToAws = serverless.getRequestsToAws(); requestsToAwsToUpdateStage = requestsToAws.filter(r => r.method == 'updateStage'); @@ -789,7 +788,3 @@ describe('Updating stage cache settings', () => { }); }); }); - -const when_updating_stage_cache_settings = async (settings, serverless) => { - return await updateStageCacheSettings(settings, serverless); -} From 1e8da1a8410922551376b678037a5494c9739d8e Mon Sep 17 00:00:00 2001 From: "diana.ionita" Date: Wed, 7 Dec 2022 13:05:30 +0000 Subject: [PATCH 3/5] Fixed test --- src/ApiGatewayCachingSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ApiGatewayCachingSettings.js b/src/ApiGatewayCachingSettings.js index 77e8062..9c1ad2b 100644 --- a/src/ApiGatewayCachingSettings.js +++ b/src/ApiGatewayCachingSettings.js @@ -93,7 +93,7 @@ class ApiGatewayEndpointCachingSettings { this.path = basePath.concat(this.path); } - if (event.http.caching?.inheritCloudWatchSettingsFromStage != undefined) { + if (event.http.caching && event.http.caching.inheritCloudWatchSettingsFromStage != undefined) { this.inheritCloudWatchSettingsFromStage = event.http.caching?.inheritCloudWatchSettingsFromStage; } else { From b0c89d13e7fe52a6bb333cf583f413e1d20c1db0 Mon Sep 17 00:00:00 2001 From: "diana.ionita" Date: Wed, 7 Dec 2022 13:06:20 +0000 Subject: [PATCH 4/5] Fixed tests --- src/ApiGatewayCachingSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ApiGatewayCachingSettings.js b/src/ApiGatewayCachingSettings.js index 9c1ad2b..2fe39ae 100644 --- a/src/ApiGatewayCachingSettings.js +++ b/src/ApiGatewayCachingSettings.js @@ -94,7 +94,7 @@ class ApiGatewayEndpointCachingSettings { } if (event.http.caching && event.http.caching.inheritCloudWatchSettingsFromStage != undefined) { - this.inheritCloudWatchSettingsFromStage = event.http.caching?.inheritCloudWatchSettingsFromStage; + this.inheritCloudWatchSettingsFromStage = event.http.caching.inheritCloudWatchSettingsFromStage; } else { this.inheritCloudWatchSettingsFromStage = globalSettings.endpointsInheritCloudWatchSettingsFromStage; From f948002b8c37e88eac5e319c2ca66d6b3561e44e Mon Sep 17 00:00:00 2001 From: "diana.ionita" Date: Wed, 7 Dec 2022 13:09:26 +0000 Subject: [PATCH 5/5] Version++ --- package-lock.json | 1173 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 +- 2 files changed, 1172 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 31d6370..e4b56d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,1177 @@ { "name": "serverless-api-gateway-caching", - "version": "1.10.0-rc2", - "lockfileVersion": 1, + "version": "1.10.0", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "serverless-api-gateway-caching", + "version": "1.10.0", + "license": "ISC", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isempty": "^4.4.0" + }, + "devDependencies": { + "chai": "^4.1.2", + "chance": "^1.0.16", + "lodash.split": "^4.4.0", + "mocha": "^10.0.0", + "mocha-junit-reporter": "^2.0.2", + "proxyquire": "^2.1.0" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/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, + "engines": { + "node": "*" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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 + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "dependencies": { + "assertion-error": "^1.0.1", + "check-error": "^1.0.1", + "deep-eql": "^3.0.0", + "get-func-name": "^2.0.0", + "pathval": "^1.0.0", + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chance": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.16.tgz", + "integrity": "sha512-2bgDHH5bVfAXH05SPtjqrsASzZ7h90yCuYT2z4mkYpxxYvJXiIydBFzVieVHZx7wLH1Ag2Azaaej2/zA1XUrNQ==", + "dev": true + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/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 + }, + "node_modules/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 + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/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 + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, + "dependencies": { + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/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, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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 + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/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 + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" + }, + "node_modules/lodash.split": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.split/-/lodash.split-4.4.2.tgz", + "integrity": "sha1-p/e9nzeWi5MSQo4vOsP7MXPEw8Y=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dev": true, + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", + "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha-junit-reporter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.0.2.tgz", + "integrity": "sha512-vYwWq5hh3v1lG0gdQCBxwNipBfvDiAM1PHroQRNp96+2l72e9wEUTw+mzoK+O0SudgfQ7WvTQZ9Nh3qkAYAjfg==", + "dev": true, + "dependencies": { + "debug": "^2.2.0", + "md5": "^2.1.0", + "mkdirp": "~0.5.1", + "strip-ansi": "^6.0.1", + "xml": "^1.0.0" + }, + "peerDependencies": { + "mocha": ">=2.2.5" + } + }, + "node_modules/mocha-junit-reporter/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/mocha-junit-reporter/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxyquire": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.0.tgz", + "integrity": "sha512-kptdFArCfGRtQFv3Qwjr10lwbEV0TBJYvfqzhwucyfEXqVgmnAkyEw/S3FYzR5HI9i5QOq4rcqQjZ6AlknlCDQ==", + "dev": true, + "dependencies": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.0", + "resolve": "~1.8.1" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.5" + } + }, + "node_modules/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, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, "dependencies": { "@ungap/promise-all-settled": { "version": "1.1.2", diff --git a/package.json b/package.json index b0677bb..9361182 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "serverless-api-gateway-caching", - "version": "1.10.0-rc2", + "version": "1.10.0", "description": "A plugin for the serverless framework which helps with configuring caching for API Gateway endpoints.", "main": "src/apiGatewayCachingPlugin.js", "scripts": {