diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml index f3dbedb05b3cd..b5a04b5ca5370 100644 --- a/.github/workflows/close-stale-issues.yml +++ b/.github/workflows/close-stale-issues.yml @@ -14,14 +14,14 @@ jobs: with: # Setting messages to an empty string will cause the automation to skip # that category - ancient-issue-message: This issue has not received any attention in 3 years. If you want to keep this issue open, please leave a comment below and auto-close will be canceled. + ancient-issue-message: This issue has not received any attention in 2 years. If you want to keep this issue open, please leave a comment below and auto-close will be canceled. stale-issue-message: This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled. stale-pr-message: This PR has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled. # These labels are required stale-issue-label: closing-soon exempt-issue-label: no-autoclose - stale-pr-label: pr/no-activity + stale-pr-label: closing-soon exempt-pr-label: no-autoclose response-requested-label: response-requested @@ -32,7 +32,7 @@ jobs: # Issue timing days-before-stale: 7 days-before-close: 4 - days-before-ancient: 1095 + days-before-ancient: 730 # If you don't want to mark a issue as being ancient based on a # threshold of "upvotes", you can set this here. An "upvote" is @@ -43,4 +43,4 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} # loglevel: DEBUG # Set dry-run to true to not perform label or close actions. - dry-run: true + dry-run: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 6964e63a18106..2585012956fdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,37 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.38.0](https://github.com/aws/aws-cdk/compare/v1.37.0...v1.38.0) (2020-05-08) + + +### Features + +* **cloudfront:** support geo restrictions for cloudfront distribution ([#7345](https://github.com/aws/aws-cdk/issues/7345)) ([cf25ba0](https://github.com/aws/aws-cdk/commit/cf25ba0dc3baae8db40219611f7aa919b108c739)), closes [#3456](https://github.com/aws/aws-cdk/issues/3456) +* **cloudwatch:** legend positions in GraphWidgets ([ada0de1](https://github.com/aws/aws-cdk/commit/ada0de1f051a72768523544b5bca27e0768632a9)), closes [#3625](https://github.com/aws/aws-cdk/issues/3625) +* **codebuild:** add support for test reports ([4befefc](https://github.com/aws/aws-cdk/commit/4befefc4792c6d6415f356f8d40e115e9e602802)), closes [#7367](https://github.com/aws/aws-cdk/issues/7367) +* **core:** custom resource provider helper ([4a76973](https://github.com/aws/aws-cdk/commit/4a7697370c9d04fdbb2c9fb0be71d67122573390)) +* **ec2:** EBS volume configuration for BastionHostLinux ([207a8ec](https://github.com/aws/aws-cdk/commit/207a8ecf233511ad478827620b9caf0ff5fbb815)), closes [#6945](https://github.com/aws/aws-cdk/issues/6945) +* **ecs:** support multiple security groups when creating an ecs service ([#7850](https://github.com/aws/aws-cdk/issues/7850)) ([456c469](https://github.com/aws/aws-cdk/commit/456c469dd4b92a6a863e4c40125adf573d4df239)) +* **iam:** openid connect providers ([20621ac](https://github.com/aws/aws-cdk/commit/20621acf6c1adbf144d47a029888fe481d5abb78)), closes [#5388](https://github.com/aws/aws-cdk/issues/5388) [#3949](https://github.com/aws/aws-cdk/issues/3949) [#6308](https://github.com/aws/aws-cdk/issues/6308) +* add an example construct package ([#7748](https://github.com/aws/aws-cdk/issues/7748)) ([2223584](https://github.com/aws/aws-cdk/commit/2223584d5f9811294125c6d6068d1f5bb4e48349)) +* **lambda-nodejs:** run parcel in a docker container ([d86e500](https://github.com/aws/aws-cdk/commit/d86e5001e08c21b846c47ed051f6c17fc9826d1a)), closes [#7169](https://github.com/aws/aws-cdk/issues/7169) +* cloudformation spec v14.1.0 ([#7822](https://github.com/aws/aws-cdk/issues/7822)) ([e133027](https://github.com/aws/aws-cdk/commit/e1330273fbc700285d737e57a8d20f2857be2f82)) +* **s3:** new `s3UrlForObject` method on `IBucket` ([#7508](https://github.com/aws/aws-cdk/issues/7508)) ([8fe4015](https://github.com/aws/aws-cdk/commit/8fe4015a9357623434fb2825e3342ffc145a13f8)), closes [#7507](https://github.com/aws/aws-cdk/issues/7507) +* **stepfunctions:** custom state as an escape hatch ([c498f60](https://github.com/aws/aws-cdk/commit/c498f60d34b5bd01fc95f7999bc605e10edbb717)) + + +### Bug Fixes + +* **assets): fix(assets:** invalid fingerprint when 'exclude' captures root directory name ([#7719](https://github.com/aws/aws-cdk/issues/7719)) ([a5c06a3](https://github.com/aws/aws-cdk/commit/a5c06a3a27b39a5315d0cfd0d34b3c1b25cfc464)), closes [#7718](https://github.com/aws/aws-cdk/issues/7718) +* **aws-batch:** gpuCount was ignored in JobDefinition creation ([#7587](https://github.com/aws/aws-cdk/issues/7587)) ([0f1bf23](https://github.com/aws/aws-cdk/commit/0f1bf23817774eb94505a6c68f1daa8a117bbd42)) +* **cli:** parameter value reuse is not configurable ([44310c9](https://github.com/aws/aws-cdk/commit/44310c93af939f8aaf9ca4245c944b5c93f61ab7)), closes [#7041](https://github.com/aws/aws-cdk/issues/7041) +* **core:** docs refer to "createNamingScheme" which was renamed to "allocateLogicalId" ([#7840](https://github.com/aws/aws-cdk/issues/7840)) ([d79595d](https://github.com/aws/aws-cdk/commit/d79595d854adf160c0a6395a5f535ee270bbdf69)), closes [#7527](https://github.com/aws/aws-cdk/issues/7527) +* **ecs:** update minHealthyPercent constrain for ec2service using daemon strategy ([#7814](https://github.com/aws/aws-cdk/issues/7814)) ([19e3fd8](https://github.com/aws/aws-cdk/commit/19e3fd800af5a32dfb359f4be4717fbf3adb91df)) +* **ecs:** using secret JSON field with fargate task does not fail ([#7317](https://github.com/aws/aws-cdk/issues/7317)) ([cb03a60](https://github.com/aws/aws-cdk/commit/cb03a601599b56539081caf602647d1f431d2d59)), closes [#7272](https://github.com/aws/aws-cdk/issues/7272) +* **eks:** "vendor response doesn't contain attribute" when updating version ([#7830](https://github.com/aws/aws-cdk/issues/7830)) ([8cabae0](https://github.com/aws/aws-cdk/commit/8cabae0a03cc526f5f7fbfebf22978ad88efcb4f)), closes [#7526](https://github.com/aws/aws-cdk/issues/7526) [#7794](https://github.com/aws/aws-cdk/issues/7794) +* **s3:** grantDelete with KMS SSE ([#7528](https://github.com/aws/aws-cdk/issues/7528)) ([c6d1a21](https://github.com/aws/aws-cdk/commit/c6d1a21b09967d787404101829058106ed74852a)), closes [#4380](https://github.com/aws/aws-cdk/issues/4380) +* **secretsmanager:** add kms policy to allow secret to use kms key ([5460717](https://github.com/aws/aws-cdk/commit/54607175115663bd49d8a57cb82b814414e7e78a)) + ## [1.37.0](https://github.com/aws/aws-cdk/compare/v1.36.0...v1.37.0) (2020-05-05) @@ -23,7 +54,6 @@ maps to the domain root. * **core:** move all types from "aws-cloudformation" to "core" ([#7736](https://github.com/aws/aws-cdk/issues/7736)) ([40fa93a](https://github.com/aws/aws-cdk/commit/40fa93a22ffbdf18b0563d1cef63bbf5814dcc3f)), closes [#4896](https://github.com/aws/aws-cdk/issues/4896) [#7035](https://github.com/aws/aws-cdk/issues/7035) [#7034](https://github.com/aws/aws-cdk/issues/7034) * **core:** stack termination protection ([#7610](https://github.com/aws/aws-cdk/issues/7610)) ([7ed60b8](https://github.com/aws/aws-cdk/commit/7ed60b8a5d42e93e556e3b6e9ee3618931747ac2)), closes [#1682](https://github.com/aws/aws-cdk/issues/1682) * **ecr:** support imageScanOnPush when creating the repository ([9df5486](https://github.com/aws/aws-cdk/commit/9df5486306fda01d963f4b1195fe8c8532cc4668)), closes [#7471](https://github.com/aws/aws-cdk/issues/7471) -* **lambda-nodejs:** use docker instead of npm package for parcel-bundler ([55c4d0b](https://github.com/aws/aws-cdk/commit/55c4d0bb35aad7b026a88cf1a38a37af9af33f9f)) ### Bug Fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f556b9337daa9..a9bdea2c823e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,7 @@ For day-to-day development and normal contributions, the following SDKs and tool - [Node.js 10.13.0](https://nodejs.org/download/release/latest-v10.x/) - [Yarn >= 1.19.1](https://yarnpkg.com/lang/en/docs/install) - [Java OpenJDK 8](http://openjdk.java.net/install/) - - [.NET Core SDK 3.0](https://www.microsoft.com/net/download) + - [.NET Core SDK 3.1](https://www.microsoft.com/net/download) - [Python 3.6.5](https://www.python.org/downloads/release/python-365/) - [Ruby 2.5.1](https://www.ruby-lang.org/en/news/2018/03/28/ruby-2-5-1-released/) @@ -131,6 +131,11 @@ Work your magic. Here are some guidelines: * Try to maintain a single feature/bugfix per pull request. It's okay to introduce a little bit of housekeeping changes along the way, but try to avoid conflating multiple features. Eventually all these are going to go into a single commit, so you can use that to frame your scope. +* If your change introduces a new construct, take a look at the our + [example Construct Library](packages/@aws-cdk/example-construct-library) for an explanation of the common patterns we use. + Feel free to start your contribution by copy&pasting files from that project, + and then edit and rename them as appropriate - + it might be easier to get started that way. #### Integration Tests diff --git a/allowed-breaking-changes.txt b/allowed-breaking-changes.txt index 790b59b6edc5f..8a8b54410795f 100644 --- a/allowed-breaking-changes.txt +++ b/allowed-breaking-changes.txt @@ -49,3 +49,6 @@ incompatible-argument:@aws-cdk/aws-iam.PrincipalPolicyFragment. changed-type:@aws-cdk/aws-iam.FederatedPrincipal.conditions changed-type:@aws-cdk/aws-iam.PrincipalPolicyFragment.conditions changed-type:@aws-cdk/aws-iam.PrincipalWithConditions.conditions +# Changing untyped property blob into typed property blob +change-return-type:@aws-cdk/cloud-assembly-schema.Manifest.load +incompatible-argument:@aws-cdk/cloud-assembly-schema.Manifest.save diff --git a/buildspec-pr.yaml b/buildspec-pr.yaml index 2cbd14c7553a8..639c21a87dabe 100644 --- a/buildspec-pr.yaml +++ b/buildspec-pr.yaml @@ -5,6 +5,10 @@ version: 0.2 phases: install: commands: + # Start docker daemon inside the container + - nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2& + - timeout 15 sh -c "until docker info; do echo .; sleep 1; done" + # Install yarn if it wasn't already present in the image - yarn --version || npm -g install yarn build: diff --git a/buildspec.yaml b/buildspec.yaml index 7c5c8fcc14585..59b95d64d8b13 100644 --- a/buildspec.yaml +++ b/buildspec.yaml @@ -5,6 +5,10 @@ version: 0.2 phases: install: commands: + # Start docker daemon inside the container + - nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2& + - timeout 15 sh -c "until docker info; do echo .; sleep 1; done" + # Install yarn if it wasn't already present in the image - yarn --version || npm -g install yarn pre_build: diff --git a/lerna.json b/lerna.json index 14f1468830097..7b4d069f3a5ad 100644 --- a/lerna.json +++ b/lerna.json @@ -10,5 +10,5 @@ "tools/*" ], "rejectCycles": "true", - "version": "1.37.0" + "version": "1.38.0" } diff --git a/package.json b/package.json index 900c9ae1bd3c5..38ceba57ec54e 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,18 @@ "devDependencies": { "conventional-changelog-cli": "^2.0.31", "fs-extra": "^8.1.0", - "jsii-diff": "^1.4.1", - "jsii-pacmak": "^1.4.1", - "jsii-rosetta": "^1.4.1", + "jsii-diff": "^1.5.0", + "jsii-pacmak": "^1.5.0", + "jsii-rosetta": "^1.5.0", "lerna": "^3.20.2", - "standard-version": "^7.1.0", + "standard-version": "^8.0.0", "graceful-fs": "^4.2.4", "typescript": "~3.8.3" }, + "resolutions-comment": "should be removed or reviewed when nodeunit dependency is dropped or adjusted", + "resolutions": { + "tap-mocha-reporter": "^5.0.1" + }, "repository": { "type": "git", "url": "git://github.com/aws/aws-cdk" diff --git a/packages/@aws-cdk/assert/package.json b/packages/@aws-cdk/assert/package.json index f6ef917883eca..2bad5d64de9cb 100644 --- a/packages/@aws-cdk/assert/package.json +++ b/packages/@aws-cdk/assert/package.json @@ -33,7 +33,7 @@ "cdk-build-tools": "0.0.0", "jest": "^25.5.4", "pkglint": "0.0.0", - "ts-jest": "^25.4.0" + "ts-jest": "^25.5.0" }, "dependencies": { "@aws-cdk/cloudformation-diff": "0.0.0", diff --git a/packages/@aws-cdk/aws-batch/lib/job-definition.ts b/packages/@aws-cdk/aws-batch/lib/job-definition.ts index be1afc5482366..23aba0289c9e1 100644 --- a/packages/@aws-cdk/aws-batch/lib/job-definition.ts +++ b/packages/@aws-cdk/aws-batch/lib/job-definition.ts @@ -337,6 +337,9 @@ export class JobDefinition extends Resource implements IJobDefinition { memory: container.memoryLimitMiB || 4, mountPoints: container.mountPoints, privileged: container.privileged || false, + resourceRequirements: container.gpuCount + ? [{ type: 'GPU', value: String(container.gpuCount) }] + : undefined, readonlyRootFilesystem: container.readOnly || false, ulimits: container.ulimits, user: container.user, diff --git a/packages/@aws-cdk/aws-batch/test/job-definition.test.ts b/packages/@aws-cdk/aws-batch/test/job-definition.test.ts index de54f23fc5072..06c82b8c8e4dd 100644 --- a/packages/@aws-cdk/aws-batch/test/job-definition.test.ts +++ b/packages/@aws-cdk/aws-batch/test/job-definition.test.ts @@ -78,6 +78,7 @@ describe('Batch Job Definition', () => { MountPoints: [], Privileged: jobDefProps.container.privileged, ReadonlyRootFilesystem: jobDefProps.container.readOnly, + ResourceRequirements: [{ Type: 'GPU', Value: String(jobDefProps.container.gpuCount)}], Ulimits: [], User: jobDefProps.container.user, Vcpus: jobDefProps.container.vcpus, diff --git a/packages/@aws-cdk/aws-cloudformation/test/core-custom-resource-provider-fixture/index.ts b/packages/@aws-cdk/aws-cloudformation/test/core-custom-resource-provider-fixture/index.ts new file mode 100644 index 0000000000000..5a372f057593e --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/core-custom-resource-provider-fixture/index.ts @@ -0,0 +1,10 @@ +// tslint:disable: no-console + +export function handler(event: any) { + console.log('I am a custom resource'); + console.log(event); + return { + PhysicalResourceId: event.ResourceProperties.physicalResourceId, + Data: event.ResourceProperties.attributes, + }; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-custom-resources.expected.json b/packages/@aws-cdk/aws-cloudformation/test/integ.core-custom-resources.expected.json new file mode 100644 index 0000000000000..5e3d50351b9d3 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-custom-resources.expected.json @@ -0,0 +1,137 @@ +{ + "Resources": { + "CustomReflectCustomResourceProviderRoleB4B29AEC": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ] + } + }, + "CustomReflectCustomResourceProviderHandler2E189D0B": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3Bucket1D703CB8" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3VersionKey01A97AE3" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3VersionKey01A97AE3" + } + ] + } + ] + } + ] + ] + } + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomReflectCustomResourceProviderRoleB4B29AEC", + "Arn" + ] + }, + "Runtime": "nodejs12.x" + }, + "DependsOn": [ + "CustomReflectCustomResourceProviderRoleB4B29AEC" + ] + }, + "MyResource": { + "Type": "Custom::Reflect", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomReflectCustomResourceProviderHandler2E189D0B", + "Arn" + ] + }, + "physicalResourceId": "MyPhysicalReflectBack", + "attributes": { + "Attribute1": "foo", + "Attribute2": 1234 + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3Bucket1D703CB8": { + "Type": "String", + "Description": "S3 bucket for asset \"d46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7a\"" + }, + "AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3VersionKey01A97AE3": { + "Type": "String", + "Description": "S3 key for asset version \"d46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7a\"" + }, + "AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aArtifactHash16A571C9": { + "Type": "String", + "Description": "Artifact hash for asset \"d46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7a\"" + } + }, + "Outputs": { + "Ref": { + "Value": { + "Ref": "MyResource" + } + }, + "GetAttAttribute1": { + "Value": { + "Fn::GetAtt": [ + "MyResource", + "Attribute1" + ] + } + }, + "GetAttAttribute2": { + "Value": { + "Fn::GetAtt": [ + "MyResource", + "Attribute2" + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudformation/test/integ.core-custom-resources.ts b/packages/@aws-cdk/aws-cloudformation/test/integ.core-custom-resources.ts new file mode 100644 index 0000000000000..2c219f757825d --- /dev/null +++ b/packages/@aws-cdk/aws-cloudformation/test/integ.core-custom-resources.ts @@ -0,0 +1,42 @@ +/* + * Stack verification steps: + * - Deploy with `--no-clean` + * - Verify that the CloudFormation stack outputs have the following values: + * - Ref: "MyPhysicalReflectBack" + * - GetAtt.Attribute1: "foo" + * - GetAtt.Attribute2: 1234 + */ +import { App, CfnOutput, Construct, CustomResource, CustomResourceProvider, CustomResourceProviderRuntime, Stack, Token } from '@aws-cdk/core'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + + const resourceType = 'Custom::Reflect'; + + const serviceToken = CustomResourceProvider.getOrCreate(this, resourceType, { + codeDirectory: `${__dirname}/core-custom-resource-provider-fixture`, + runtime: CustomResourceProviderRuntime.NODEJS_12, + }); + + const cr = new CustomResource(this, 'MyResource', { + resourceType, + serviceToken, + properties: { + physicalResourceId: 'MyPhysicalReflectBack', + attributes: { + Attribute1: 'foo', + Attribute2: 1234, + }, + }, + }); + + new CfnOutput(this, 'Ref', { value: cr.ref }); + new CfnOutput(this, 'GetAtt.Attribute1', { value: Token.asString(cr.getAtt('Attribute1')) }); + new CfnOutput(this, 'GetAtt.Attribute2', { value: Token.asString(cr.getAtt('Attribute2')) }); + } +} + +const app = new App(); +new TestStack(app, 'custom-resource-test'); +app.synth(); diff --git a/packages/@aws-cdk/aws-cloudformation/test/test.nested-stack.ts b/packages/@aws-cdk/aws-cloudformation/test/test.nested-stack.ts index 84a3f81ba172e..4a71ab81e0ea3 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/test.nested-stack.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/test.nested-stack.ts @@ -912,7 +912,7 @@ export = { const app = new App(); const stack = new Stack(app, 'ParentStack', { env: { account: '1234account', region: 'us-east-44' } }); const nestedStack = new NestedStack(stack, 'nested'); - const provider = 'dummyProvider'; + const provider = 'availability-zones'; const expectedKey = ContextProvider.getKey(nestedStack, { provider, }).key; diff --git a/packages/@aws-cdk/aws-cloudfront/README.md b/packages/@aws-cdk/aws-cloudfront/README.md index ad3ec2df4301c..32c12c9959181 100644 --- a/packages/@aws-cdk/aws-cloudfront/README.md +++ b/packages/@aws-cdk/aws-cloudfront/README.md @@ -67,3 +67,17 @@ See [Importing an SSL/TLS Certificate](https://docs.aws.amazon.com/AmazonCloudFr Example: [create a distrubution with an iam certificate example](test/example.iam-cert-alias.lit.ts) + +#### Restrictions + +CloudFront supports adding restrictions to your distribution. + +See [Restricting the Geographic Distribution of Your Content](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/georestrictions.html) in the CloudFront User Guide. + +Example: +```ts +new cloudfront.CloudFrontWebDistribution(stack, 'MyDistribution', { + //... + geoRestriction: GeoRestriction.whitelist('US', 'UK') +}); +``` \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts b/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts index 7a9c29ea6bed0..6b7a530173c2d 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts @@ -482,6 +482,58 @@ export class ViewerCertificate { public readonly aliases: string[] = []) { } } +/** + * Controls the countries in which your content is distributed. + */ +export class GeoRestriction { + + /** + * Whitelist specific countries which you want CloudFront to distribute your content. + * + * @param locations Two-letter, uppercase country code for a country + * that you want to whitelist. Include one element for each country. + * See ISO 3166-1-alpha-2 code on the *International Organization for Standardization* website + */ + public static whitelist(...locations: string[]) { + return new GeoRestriction('whitelist', GeoRestriction.validateLocations(locations)); + } + + /** + * Blacklist specific countries which you don't want CloudFront to distribute your content. + * + * @param locations Two-letter, uppercase country code for a country + * that you want to blacklist. Include one element for each country. + * See ISO 3166-1-alpha-2 code on the *International Organization for Standardization* website + */ + public static blacklist(...locations: string[]) { + return new GeoRestriction('blacklist', GeoRestriction.validateLocations(locations)); + } + + private static LOCATION_REGEX = /^[A-Z]{2}$/; + + private static validateLocations(locations: string[]) { + if (locations.length === 0) { + throw new Error('Should provide at least 1 location'); + } + locations.forEach(location => { + if (!GeoRestriction.LOCATION_REGEX.test(location)) { + throw new Error(`Invalid location format for location: ${location}, location should be two-letter and uppercase country ISO 3166-1-alpha-2 code`); + } + }); + return locations; + } + + /** + * Creates an instance of GeoRestriction for internal use + * + * @param restrictionType Specifies the restriction type to impose (whitelist or blacklist) + * @param locations Two-letter, uppercase country code for a country + * that you want to whitelist/blacklist. Include one element for each country. + * See ISO 3166-1-alpha-2 code on the *International Organization for Standardization* website + */ + private constructor(readonly restrictionType: 'whitelist' | 'blacklist', readonly locations: string[]) {} +} + export interface CloudFrontWebDistributionProps { /** @@ -576,6 +628,13 @@ export interface CloudFrontWebDistributionProps { * @see https://aws.amazon.com/premiumsupport/knowledge-center/custom-ssl-certificate-cloudfront/ */ readonly viewerCertificate?: ViewerCertificate; + + /** + * Controls the countries in which your content is distributed. + * + * @default No geo restriction + */ + readonly geoRestriction?: GeoRestriction; } /** @@ -818,6 +877,18 @@ export class CloudFrontWebDistribution extends cdk.Construct implements IDistrib }; } + if (props.geoRestriction) { + distributionConfig = { + ...distributionConfig, + restrictions: { + geoRestriction: { + restrictionType: props.geoRestriction.restrictionType, + locations: props.geoRestriction.locations, + }, + }, + }; + } + const distribution = new CfnDistribution(this, 'CFDistribution', { distributionConfig }); this.node.defaultChild = distribution; this.domainName = distribution.attrDomainName; diff --git a/packages/@aws-cdk/aws-cloudfront/package.json b/packages/@aws-cdk/aws-cloudfront/package.json index a6f76f9812234..3df3ce2f1a7c3 100644 --- a/packages/@aws-cdk/aws-cloudfront/package.json +++ b/packages/@aws-cdk/aws-cloudfront/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-geo-restrictions.expected.json b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-geo-restrictions.expected.json new file mode 100644 index 0000000000000..25ae7addfd317 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-geo-restrictions.expected.json @@ -0,0 +1,61 @@ +{ + "Resources": { + "Bucket83908E77": { + "DeletionPolicy": "Delete", + "UpdateReplacePolicy": "Delete", + "Type": "AWS::S3::Bucket" + }, + "MyDistributionCFDistributionDE147309": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "DefaultCacheBehavior": { + "AllowedMethods": [ + "GET", + "HEAD" + ], + "CachedMethods": [ + "GET", + "HEAD" + ], + "ForwardedValues": { + "Cookies": { + "Forward": "none" + }, + "QueryString": false + }, + "TargetOriginId": "origin1", + "ViewerProtocolPolicy": "redirect-to-https", + "Compress": true + }, + "DefaultRootObject": "index.html", + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Origins": [ + { + "DomainName": { + "Fn::GetAtt": [ + "Bucket83908E77", + "RegionalDomainName" + ] + }, + "Id": "origin1", + "S3OriginConfig": {} + } + ], + "PriceClass": "PriceClass_100", + "ViewerCertificate": { + "CloudFrontDefaultCertificate": true + }, + "Restrictions": { + "GeoRestriction": { + "Locations": ["US", "UK"], + "RestrictionType": "whitelist" + } + } + } + } + } + } +} diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-geo-restrictions.ts b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-geo-restrictions.ts new file mode 100644 index 0000000000000..453b51df57fa4 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-geo-restrictions.ts @@ -0,0 +1,25 @@ +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as cloudfront from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'cloudfront-geo-restrictions'); + +const sourceBucket = new s3.Bucket(stack, 'Bucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +new cloudfront.CloudFrontWebDistribution(stack, 'MyDistribution', { + originConfigs: [ + { + s3OriginSource: { + s3BucketSource: sourceBucket, + }, + behaviors : [ {isDefaultBehavior: true}], + }, + ], + geoRestriction: cloudfront.GeoRestriction.whitelist('US', 'UK'), +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-cloudfront/test/test.basic.ts b/packages/@aws-cdk/aws-cloudfront/test/test.basic.ts index b21b5d8468b46..39366da64117d 100644 --- a/packages/@aws-cdk/aws-cloudfront/test/test.basic.ts +++ b/packages/@aws-cdk/aws-cloudfront/test/test.basic.ts @@ -5,8 +5,14 @@ import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; import { - CfnDistribution, CloudFrontWebDistribution, LambdaEdgeEventType, SecurityPolicyProtocol, SSLMethod, - ViewerCertificate, ViewerProtocolPolicy, + CfnDistribution, + CloudFrontWebDistribution, + GeoRestriction, + LambdaEdgeEventType, + SecurityPolicyProtocol, + SSLMethod, + ViewerCertificate, + ViewerProtocolPolicy, } from '../lib'; // tslint:disable:object-literal-key-quotes @@ -870,4 +876,181 @@ export = { expect(stack).notTo(haveResourceLike('AWS::IAM::Role')); test.done(); }, + + 'geo restriction': { + 'success' : { + 'whitelist'(test: Test) { + const stack = new cdk.Stack(); + const sourceBucket = new s3.Bucket(stack, 'Bucket'); + + new CloudFrontWebDistribution(stack, 'AnAmazingWebsiteProbably', { + originConfigs: [{ + s3OriginSource: {s3BucketSource: sourceBucket}, + behaviors: [{isDefaultBehavior: true}], + }], + geoRestriction: GeoRestriction.whitelist('US', 'UK'), + }); + + expect(stack).toMatch({ + 'Resources': { + 'Bucket83908E77': { + 'Type': 'AWS::S3::Bucket', + 'DeletionPolicy': 'Retain', + 'UpdateReplacePolicy': 'Retain', + }, + 'AnAmazingWebsiteProbablyCFDistribution47E3983B': { + 'Type': 'AWS::CloudFront::Distribution', + 'Properties': { + 'DistributionConfig': { + 'DefaultRootObject': 'index.html', + 'Origins': [ + { + 'DomainName': { + 'Fn::GetAtt': [ + 'Bucket83908E77', + 'RegionalDomainName', + ], + }, + 'Id': 'origin1', + 'S3OriginConfig': {}, + }, + ], + 'ViewerCertificate': { + 'CloudFrontDefaultCertificate': true, + }, + 'PriceClass': 'PriceClass_100', + 'DefaultCacheBehavior': { + 'AllowedMethods': [ + 'GET', + 'HEAD', + ], + 'CachedMethods': [ + 'GET', + 'HEAD', + ], + 'TargetOriginId': 'origin1', + 'ViewerProtocolPolicy': 'redirect-to-https', + 'ForwardedValues': { + 'QueryString': false, + 'Cookies': {'Forward': 'none'}, + }, + 'Compress': true, + }, + 'Enabled': true, + 'IPV6Enabled': true, + 'HttpVersion': 'http2', + 'Restrictions': { + 'GeoRestriction': { + 'Locations': ['US', 'UK'], + 'RestrictionType': 'whitelist', + }, + }, + }, + }, + }, + }, + }); + + test.done(); + }, + 'blacklist'(test: Test) { + const stack = new cdk.Stack(); + const sourceBucket = new s3.Bucket(stack, 'Bucket'); + + new CloudFrontWebDistribution(stack, 'AnAmazingWebsiteProbably', { + originConfigs: [{ + s3OriginSource: {s3BucketSource: sourceBucket}, + behaviors: [{isDefaultBehavior: true}], + }], + geoRestriction: GeoRestriction.blacklist('US'), + }); + + expect(stack).toMatch({ + 'Resources': { + 'Bucket83908E77': { + 'Type': 'AWS::S3::Bucket', + 'DeletionPolicy': 'Retain', + 'UpdateReplacePolicy': 'Retain', + }, + 'AnAmazingWebsiteProbablyCFDistribution47E3983B': { + 'Type': 'AWS::CloudFront::Distribution', + 'Properties': { + 'DistributionConfig': { + 'DefaultRootObject': 'index.html', + 'Origins': [ + { + 'DomainName': { + 'Fn::GetAtt': [ + 'Bucket83908E77', + 'RegionalDomainName', + ], + }, + 'Id': 'origin1', + 'S3OriginConfig': {}, + }, + ], + 'ViewerCertificate': { + 'CloudFrontDefaultCertificate': true, + }, + 'PriceClass': 'PriceClass_100', + 'DefaultCacheBehavior': { + 'AllowedMethods': [ + 'GET', + 'HEAD', + ], + 'CachedMethods': [ + 'GET', + 'HEAD', + ], + 'TargetOriginId': 'origin1', + 'ViewerProtocolPolicy': 'redirect-to-https', + 'ForwardedValues': { + 'QueryString': false, + 'Cookies': {'Forward': 'none'}, + }, + 'Compress': true, + }, + 'Enabled': true, + 'IPV6Enabled': true, + 'HttpVersion': 'http2', + 'Restrictions': { + 'GeoRestriction': { + 'Locations': ['US'], + 'RestrictionType': 'blacklist', + }, + }, + }, + }, + }, + }, + }); + + test.done(); + }, + }, + 'error': { + 'throws if locations is empty array'(test: Test) { + test.throws(() => { + GeoRestriction.whitelist(); + }, 'Should provide at least 1 location'); + + test.throws(() => { + GeoRestriction.blacklist(); + }, 'Should provide at least 1 location'); + + test.done(); + }, + 'throws if locations format is wrong'(test: Test) { + test.throws(() => { + GeoRestriction.whitelist('us'); + }, 'Invalid location format for location: us, location should be two-letter and uppercase country ISO 3166-1-alpha-2 code'); + + test.throws(() => { + GeoRestriction.blacklist('us'); + }, 'Invalid location format for location: us, location should be two-letter and uppercase country ISO 3166-1-alpha-2 code'); + + test.done(); + }, + }, + }, }; diff --git a/packages/@aws-cdk/aws-cloudtrail/package.json b/packages/@aws-cdk/aws-cloudtrail/package.json index a40f8c3dbc57f..18ceeb21c90c2 100644 --- a/packages/@aws-cdk/aws-cloudtrail/package.json +++ b/packages/@aws-cdk/aws-cloudtrail/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudwatch/README.md b/packages/@aws-cdk/aws-cloudwatch/README.md index 9fd06668186d7..94959b6e8de80 100644 --- a/packages/@aws-cdk/aws-cloudwatch/README.md +++ b/packages/@aws-cdk/aws-cloudwatch/README.md @@ -241,6 +241,17 @@ dashboard.addWidgets(new GraphWidget({ })); ``` +The graph legend can be adjusted from the default position at bottom of the widget. + +```ts +dashboard.addWidgets(new GraphWidget({ + // ... + // ... + + legendPosition: LegendPosition.RIGHT, +})); +``` + ### Alarm widget An alarm widget shows the graph and the alarm line of a single alarm: diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/graph.ts b/packages/@aws-cdk/aws-cloudwatch/lib/graph.ts index e085e3ea9e2d8..0c98e288c34ca 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/graph.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/graph.ts @@ -173,6 +173,13 @@ export interface GraphWidgetProps extends MetricWidgetProps { * @default - None */ readonly rightYAxis?: YAxisProps; + + /** + * Position of the legend + * + * @default - bottom + */ + readonly legendPosition?: LegendPosition; } /** @@ -210,6 +217,7 @@ export class GraphWidget extends ConcreteWidget { left: this.props.leftYAxis !== undefined ? this.props.leftYAxis : undefined, right: this.props.rightYAxis !== undefined ? this.props.rightYAxis : undefined, }, + legend: this.props.legendPosition !== undefined ? { position: this.props.legendPosition } : undefined, }, }]; } @@ -349,6 +357,26 @@ export class Color { public static readonly RED = '#d62728'; } +/** + * The position of the legend on a GraphWidget. + */ +export enum LegendPosition { + /** + * Legend appears below the graph (default). + */ + BOTTOM = 'bottom', + + /** + * Add shading above the annotation + */ + RIGHT = 'right', + + /** + * Add shading below the annotation + */ + HIDDEN = 'hidden' +} + function mapAnnotation(yAxis: string): ((x: HorizontalAnnotation) => any) { return (a: HorizontalAnnotation) => { return { ...a, yAxis }; diff --git a/packages/@aws-cdk/aws-cloudwatch/test/test.graphs.ts b/packages/@aws-cdk/aws-cloudwatch/test/test.graphs.ts index 45f58c01bfc0f..9e4724eed05c9 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/test.graphs.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/test.graphs.ts @@ -1,6 +1,6 @@ import { Stack } from '@aws-cdk/core'; import { Test } from 'nodeunit'; -import { Alarm, AlarmWidget, Color, GraphWidget, LogQueryWidget, Metric, Shading, SingleValueWidget } from '../lib'; +import { Alarm, AlarmWidget, Color, GraphWidget, LegendPosition, LogQueryWidget, Metric, Shading, SingleValueWidget } from '../lib'; export = { 'add stacked property to graphs'(test: Test) { @@ -393,4 +393,33 @@ export = { test.deepEqual(stack.resolve(widget.toJson())[0].properties.annotations.horizontal[0], { yAxis: 'left', value: 100, color: '#d62728' }); test.done(); }, + + 'legend position is respected in constructor'(test: Test) { + // WHEN + const stack = new Stack(); + const widget = new GraphWidget({ + left: [new Metric({ namespace: 'CDK', metricName: 'Test' }) ], + legendPosition: LegendPosition.RIGHT, + }); + + // THEN + test.deepEqual(stack.resolve(widget.toJson()), [{ + type: 'metric', + width: 6, + height: 6, + properties: { + view: 'timeSeries', + region: { Ref: 'AWS::Region' }, + metrics: [ + ['CDK', 'Test'], + ], + yAxis: {}, + legend: { + position: 'right', + }, + }, + }]); + + test.done(); + }, }; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index b61d736c11d29..73b4632722fc4 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -269,6 +269,68 @@ any attempt to save more than one will result in an error. You can use the [`list-source-credentials` AWS CLI operation](https://docs.aws.amazon.com/cli/latest/reference/codebuild/list-source-credentials.html) to inspect what credentials are stored in your account. +## Test reports + +You can specify a test report in your buildspec: + +```typescript +const project = new codebuild.Project(this, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + // ... + reports: { + myReport: { + files: '**/*', + 'base-directory': 'build/test-results', + }, + }, + }), +}); +``` + +This will create a new test report group, +with the name `-myReport`. + +The project's role in the CDK will always be granted permissions to create and use report groups +with names starting with the project's name; +if you'd rather not have those permissions added, +you can opt out of it when creating the project: + +```typescript +const project = new codebuild.Project(this, 'Project', { + // ... + grantReportGroupPermissions: false, +}); +``` + +Alternatively, you can specify an ARN of an existing resource group, +instead of a simple name, in your buildspec: + +```typescript +// create a new ReportGroup +const reportGroup = new codebuild.ReportGroup(this, 'ReportGroup'); + +const project = new codebuild.Project(this, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + // ... + reports: { + [reportGroup.reportGroupArn]: { + files: '**/*', + 'base-directory': 'build/test-results', + }, + }, + }), +}); +``` + +If you do that, you need to grant the project's role permissions to write reports to that report group: + +```typescript +reportGroup.grantWrite(project); +``` + +For more information on the test reports feature, +see the [AWS CodeBuild documentation](https://docs.aws.amazon.com/codebuild/latest/userguide/test-reporting.html). + ## Events CodeBuild projects can be used either as a source for events or be triggered diff --git a/packages/@aws-cdk/aws-codebuild/lib/index.ts b/packages/@aws-cdk/aws-codebuild/lib/index.ts index a1d569e5656d1..8ecdd6a743476 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/index.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/index.ts @@ -1,6 +1,7 @@ export * from './events'; export * from './pipeline-project'; export * from './project'; +export * from './report-group'; export * from './source'; export * from './source-credentials'; export * from './artifacts'; diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 7d1fef9a3f6dc..985177e86d8eb 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -16,6 +16,7 @@ import { CodePipelineArtifacts } from './codepipeline-artifacts'; import { IFileSystemLocation } from './file-location'; import { NoArtifacts } from './no-artifacts'; import { NoSource } from './no-source'; +import { renderReportGroupArn } from './report-group-utils'; import { ISource } from './source'; import { CODEPIPELINE_SOURCE_ARTIFACTS_TYPE, NO_SOURCE_TYPE } from './source-types'; @@ -519,6 +520,21 @@ export interface CommonProjectProps { * @default - no file system locations */ readonly fileSystemLocations?: IFileSystemLocation[]; + + /** + * Add permissions to this project's role to create and use test report groups with name starting with the name of this project. + * + * That is the standard report group that gets created when a simple name + * (in contrast to an ARN) + * is used in the 'reports' section of the buildspec of this project. + * This is usually harmless, but you can turn these off if you don't plan on using test + * reports in this project. + * + * @default true + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/test-report-group-naming.html + */ + readonly grantReportGroupPermissions?: boolean; } export interface ProjectProps extends CommonProjectProps { @@ -762,6 +778,20 @@ export class Project extends ProjectBase { this.projectName = this.getResourceNameAttribute(resource.ref); this.addToRolePolicy(this.createLoggingPermission()); + // add permissions to create and use test report groups + // with names starting with the project's name, + // unless the customer explicitly opts out of it + if (props.grantReportGroupPermissions !== false) { + this.addToRolePolicy(new iam.PolicyStatement({ + actions: [ + 'codebuild:CreateReportGroup', + 'codebuild:CreateReport', + 'codebuild:UpdateReport', + 'codebuild:BatchPutTestCases', + ], + resources: [renderReportGroupArn(this, `${this.projectName}-*`)], + })); + } if (props.encryptionKey) { this.encryptionKey = props.encryptionKey; diff --git a/packages/@aws-cdk/aws-codebuild/lib/report-group-utils.ts b/packages/@aws-cdk/aws-codebuild/lib/report-group-utils.ts new file mode 100644 index 0000000000000..c830737d14649 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/report-group-utils.ts @@ -0,0 +1,17 @@ +import * as cdk from '@aws-cdk/core'; + +// this file contains a bunch of functions shared +// between Project and ResourceGroup, +// which we don't want to make part of the public API of this module + +export function renderReportGroupArn(scope: cdk.Construct, reportGroupName: string): string { + return cdk.Stack.of(scope).formatArn(reportGroupArnComponents(reportGroupName)); +} + +export function reportGroupArnComponents(reportGroupName: string): cdk.ArnComponents { + return { + service: 'codebuild', + resource: 'report-group', + resourceName: reportGroupName, + }; +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/report-group.ts b/packages/@aws-cdk/aws-codebuild/lib/report-group.ts new file mode 100644 index 0000000000000..aa643b3e65cce --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/report-group.ts @@ -0,0 +1,152 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { CfnReportGroup } from './codebuild.generated'; +import { renderReportGroupArn, reportGroupArnComponents } from './report-group-utils'; + +/** + * The interface representing the ReportGroup resource - + * either an existing one, imported using the + * {@link ReportGroup.fromReportGroupName} method, + * or a new one, created with the {@link ReportGroup} class. + */ +export interface IReportGroup extends cdk.IResource { + /** + * The ARN of the ReportGroup. + * + * @attribute + */ + readonly reportGroupArn: string; + + /** + * The name of the ReportGroup. + * + * @attribute + */ + readonly reportGroupName: string; + + /** + * Grants the given entity permissions to write + * (that is, upload reports to) + * this report group. + */ + grantWrite(identity: iam.IGrantable): iam.Grant; +} + +abstract class ReportGroupBase extends cdk.Resource implements IReportGroup { + public abstract readonly reportGroupArn: string; + public abstract readonly reportGroupName: string; + protected abstract readonly exportBucket?: s3.IBucket; + + public grantWrite(identity: iam.IGrantable): iam.Grant { + const ret = iam.Grant.addToPrincipal({ + grantee: identity, + actions: [ + 'codebuild:CreateReport', + 'codebuild:UpdateReport', + 'codebuild:BatchPutTestCases', + ], + resourceArns: [this.reportGroupArn], + }); + + if (this.exportBucket) { + this.exportBucket.grantWrite(identity); + } + + return ret; + } +} + +/** + * Construction properties for {@link ReportGroup}. + */ +export interface ReportGroupProps { + /** + * The physical name of the report group. + * + * @default - CloudFormation-generated name + */ + readonly reportGroupName?: string; + + /** + * An optional S3 bucket to export the reports to. + * + * @default - the reports will not be exported + */ + readonly exportBucket?: s3.IBucket; + + /** + * Whether to output the report files into the export bucket as-is, + * or create a ZIP from them before doing the export. + * Ignored if {@link exportBucket} has not been provided. + * + * @default - false (the files will not be ZIPped) + */ + readonly zipExport?: boolean; + + /** + * What to do when this resource is deleted from a stack. + * As CodeBuild does not allow deleting a ResourceGroup that has reports inside of it, + * this is set to retain the resource by default. + * + * @default RemovalPolicy.RETAIN + */ + readonly removalPolicy?: cdk.RemovalPolicy; +} + +/** + * The ReportGroup resource class. + */ +export class ReportGroup extends ReportGroupBase { + + /** + * Reference an existing ReportGroup, + * defined outside of the CDK code, + * by name. + */ + public static fromReportGroupName(scope: cdk.Construct, id: string, reportGroupName: string): IReportGroup { + class Import extends ReportGroupBase { + public readonly reportGroupName = reportGroupName; + public readonly reportGroupArn = renderReportGroupArn(scope, reportGroupName); + protected readonly exportBucket = undefined; + } + + return new Import(scope, id); + } + + public readonly reportGroupArn: string; + public readonly reportGroupName: string; + protected readonly exportBucket?: s3.IBucket; + + constructor(scope: cdk.Construct, id: string, props: ReportGroupProps = {}) { + super(scope, id, { + physicalName: props.reportGroupName, + }); + + const resource = new CfnReportGroup(this, 'Resource', { + type: 'TEST', + exportConfig: { + exportConfigType: props.exportBucket ? 'S3' : 'NO_EXPORT', + s3Destination: props.exportBucket + ? { + bucket: props.exportBucket.bucketName, + encryptionDisabled: props.exportBucket.encryptionKey ? false : undefined, + encryptionKey: props.exportBucket.encryptionKey?.keyArn, + packaging: props.zipExport ? 'ZIP' : undefined, + } + : undefined, + }, + }); + resource.applyRemovalPolicy(props.removalPolicy, { + default: cdk.RemovalPolicy.RETAIN, + }); + this.reportGroupArn = this.getResourceArnAttribute(resource.attrArn, + reportGroupArnComponents(this.physicalName)); + this.reportGroupName = this.getResourceNameAttribute( + // there is no separate name attribute, + // so use Fn::Select + Fn::Split to make one + cdk.Fn.select(1, cdk.Fn.split('/', resource.ref)), + ); + this.exportBucket = props.exportBucket; + } +} diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 1ffebd83828ae..23017a58a7430 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -70,7 +70,7 @@ "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.caching.ts b/packages/@aws-cdk/aws-codebuild/test/integ.caching.ts index 249f470212653..f2436d6cc4504 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.caching.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.caching.ts @@ -22,6 +22,7 @@ new codebuild.Project(stack, 'MyProject', { paths: ['/root/.cache/pip/**/*'], }, }), + grantReportGroupPermissions: false, }); app.synth(); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.defaults.lit.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.defaults.lit.expected.json index 03af104a5737e..aae808b132920 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.defaults.lit.expected.json +++ b/packages/@aws-cdk/aws-codebuild/test/integ.defaults.lit.expected.json @@ -78,6 +78,39 @@ ] } ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "MyProject39F7B0AE" + }, + "-*" + ] + ] + } } ], "Version": "2012-10-17" @@ -115,4 +148,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.ts b/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.ts index d5bad90630949..a57ac77c1063d 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.ts @@ -15,6 +15,7 @@ class TestStack extends cdk.Stack { }, }, }), + grantReportGroupPermissions: false, /// !show environment: { buildImage: codebuild.LinuxBuildImage.fromAsset(this, 'MyImage', { diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts b/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts index d375dc2045cf2..efbbb01548647 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts @@ -18,6 +18,7 @@ class TestStack extends cdk.Stack { }, }, }), + grantReportGroupPermissions: false, /// !show environment: { buildImage: codebuild.LinuxBuildImage.fromDockerRegistry('my-registry/my-repo', { diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.ts b/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.ts index 20258a243e460..49319ff4d60c9 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.ts @@ -17,6 +17,7 @@ class TestStack extends cdk.Stack { }, }, }), + grantReportGroupPermissions: false, /// !show environment: { buildImage: codebuild.LinuxBuildImage.fromEcrRepository(ecrRepository, 'v1.0'), diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.github.ts b/packages/@aws-cdk/aws-codebuild/test/integ.github.ts index 22d99577468a3..e41cc722c0065 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.github.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.github.ts @@ -12,6 +12,7 @@ class TestStack extends cdk.Stack { }); new codebuild.Project(this, 'MyProject', { source, + grantReportGroupPermissions: false, }); } } diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts index 0a0eb19125b82..e78655e82f823 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts @@ -19,6 +19,7 @@ new codebuild.Project(stack, 'MyProject', { environment: { computeType: codebuild.ComputeType.LARGE, }, + grantReportGroupPermissions: false, }); app.synth(); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts index 6cf42d7a3e102..b72b25271086e 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts @@ -14,6 +14,7 @@ new codebuild.Project(stack, 'MyProject', { buildSpec: codebuild.BuildSpec.fromObject({ version: '0.2', }), + grantReportGroupPermissions: false, artifacts: codebuild.Artifacts.s3({ bucket, diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-file-system-location.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-file-system-location.ts index da84c9b39f4e4..02a6d747d361b 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-file-system-location.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-file-system-location.ts @@ -31,6 +31,7 @@ new codebuild.Project(stack, 'MyProject', { mountOptions: 'nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2', mountPoint: '/media', })], + grantReportGroupPermissions: false, }); app.synth(); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts index a69b389473fe2..cc552733c7912 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts @@ -29,6 +29,7 @@ new codebuild.Project(stack, 'MyProject', { identifier: 'AddArtifact1', }), ], + grantReportGroupPermissions: false, }); app.synth(); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts index 7784fed4779da..1e0b9cc2bc424 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts @@ -25,6 +25,7 @@ new codebuild.Project(stack, 'MyProject', { }, }, }), + grantReportGroupPermissions: false, securityGroups: [securityGroup], vpc, }); diff --git a/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts b/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts index 29cf00c193719..7badf7c9b8f46 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts @@ -99,6 +99,28 @@ export = { }, ], }, + { + 'Action': [ + 'codebuild:CreateReportGroup', + 'codebuild:CreateReport', + 'codebuild:UpdateReport', + 'codebuild:BatchPutTestCases', + ], + 'Effect': 'Allow', + 'Resource': { + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':codebuild:', + { 'Ref': 'AWS::Region' }, + ':', + { 'Ref': 'AWS::AccountId' }, + ':report-group/', + { 'Ref': 'MyProject39F7B0AE' }, + '-*', + ]], + }, + }, ], 'Version': '2012-10-17', }, @@ -248,6 +270,28 @@ export = { }, ], }, + { + 'Action': [ + 'codebuild:CreateReportGroup', + 'codebuild:CreateReport', + 'codebuild:UpdateReport', + 'codebuild:BatchPutTestCases', + ], + 'Effect': 'Allow', + 'Resource': { + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':codebuild:', + { 'Ref': 'AWS::Region' }, + ':', + { 'Ref': 'AWS::AccountId' }, + ':report-group/', + { 'Ref': 'MyProject39F7B0AE' }, + '-*', + ]], + }, + }, ], 'Version': '2012-10-17', }, @@ -423,6 +467,28 @@ export = { }, ], }, + { + 'Action': [ + 'codebuild:CreateReportGroup', + 'codebuild:CreateReport', + 'codebuild:UpdateReport', + 'codebuild:BatchPutTestCases', + ], + 'Effect': 'Allow', + 'Resource': { + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':codebuild:', + { 'Ref': 'AWS::Region' }, + ':', + { 'Ref': 'AWS::AccountId' }, + ':report-group/', + { 'Ref': 'MyProject39F7B0AE' }, + '-*', + ]], + }, + }, ], 'Version': '2012-10-17', }, @@ -737,6 +803,7 @@ export = { new codebuild.PipelineProject(stack, 'MyProject', { encryptionKey: key, + grantReportGroupPermissions: false, }); expect(stack).to(haveResourceLike('AWS::IAM::Policy', { diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index 08c62c0c4093a..19dd60ed5e758 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -496,4 +496,48 @@ export = { test.done(); }, + + 'CodeBuild test reports group': { + 'adds the appropriate permissions when reportGroup.grantWrite() is called'(test: Test) { + const stack = new cdk.Stack(); + + const reportGroup = new codebuild.ReportGroup(stack, 'ReportGroup'); + + const project = new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + reports: { + [reportGroup.reportGroupArn]: { + files: '**/*', + }, + }, + }), + grantReportGroupPermissions: false, + }); + reportGroup.grantWrite(project); + + expect(stack).to(haveResourceLike('AWS::IAM::Policy', { + 'PolicyDocument': { + 'Statement': [ + {}, + { + 'Action': [ + 'codebuild:CreateReport', + 'codebuild:UpdateReport', + 'codebuild:BatchPutTestCases', + ], + 'Resource': { + 'Fn::GetAtt': [ + 'ReportGroup8A84C76D', + 'Arn', + ], + }, + }, + ], + }, + })); + + test.done(); + }, + }, }; diff --git a/packages/@aws-cdk/aws-codebuild/test/test.report-group.ts b/packages/@aws-cdk/aws-codebuild/test/test.report-group.ts new file mode 100644 index 0000000000000..1e942413cc08f --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/test.report-group.ts @@ -0,0 +1,148 @@ +import { ABSENT, expect, haveResourceLike, ResourcePart } from '@aws-cdk/assert'; +import * as iam from '@aws-cdk/aws-iam'; +import * as kms from '@aws-cdk/aws-kms'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { Test } from 'nodeunit'; +import * as codebuild from '../lib'; + +// tslint:disable:object-literal-key-quotes +/* eslint-disable quotes */ + +export = { + 'Test Reports Groups': { + 'get created with type=TEST and exportConfig=NO_EXPORT by default'(test: Test) { + const stack = new cdk.Stack(); + + new codebuild.ReportGroup(stack, 'ReportGroup'); + + expect(stack).to(haveResourceLike('AWS::CodeBuild::ReportGroup', { + "Type": "TEST", + "ExportConfig": { + "ExportConfigType": "NO_EXPORT", + "S3Destination": ABSENT, + }, + })); + + test.done(); + }, + + 'can be imported by name'(test: Test) { + const stack = new cdk.Stack(); + + const reportGroup = codebuild.ReportGroup.fromReportGroupName(stack, + 'ReportGroup', 'my-report-group'); + + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.AnyPrincipal(), + }); + role.addToPolicy(new iam.PolicyStatement({ + actions: ['codebuild:*'], + resources: [reportGroup.reportGroupArn], + })); + + test.equal(reportGroup.reportGroupName, 'my-report-group'); + expect(stack).to(haveResourceLike('AWS::IAM::Policy', { + "PolicyDocument": { + "Statement": [ + { + "Action": "codebuild:*", + "Resource": { + "Fn::Join": ["", [ + "arn:", + { "Ref": "AWS::Partition" }, + ":codebuild:", + { "Ref": "AWS::Region" }, + ":", + { "Ref": "AWS::AccountId" }, + ":report-group/my-report-group", + ]], + }, + }, + ], + }, + })); + + test.done(); + }, + + 'specify exportConfig=S3 when providing an exportBucket'(test: Test) { + const stack = new cdk.Stack(); + + new codebuild.ReportGroup(stack, 'ReportGroup', { + exportBucket: s3.Bucket.fromBucketName(stack, 'Bucket', 'my-bucket'), + }); + + expect(stack).to(haveResourceLike('AWS::CodeBuild::ReportGroup', { + "Type": "TEST", + "ExportConfig": { + "ExportConfigType": "S3", + "S3Destination": { + "Bucket": "my-bucket", + "EncryptionKey": ABSENT, + "EncryptionDisabled": ABSENT, + "Packaging": ABSENT, + }, + }, + })); + + test.done(); + }, + + 'specify encryptionKey in ExportConfig.S3Destination if exportBucket has a Key'(test: Test) { + const stack = new cdk.Stack(); + + new codebuild.ReportGroup(stack, 'ReportGroup', { + exportBucket: s3.Bucket.fromBucketAttributes(stack, 'Bucket', { + bucketName: 'my-bucket', + encryptionKey: kms.Key.fromKeyArn(stack, 'Key', + 'arn:aws:kms:us-east-1:123456789012:key/my-key'), + }), + zipExport: true, + }); + + expect(stack).to(haveResourceLike('AWS::CodeBuild::ReportGroup', { + "Type": "TEST", + "ExportConfig": { + "ExportConfigType": "S3", + "S3Destination": { + "Bucket": "my-bucket", + "EncryptionDisabled": false, + "EncryptionKey": "arn:aws:kms:us-east-1:123456789012:key/my-key", + "Packaging": "ZIP", + }, + }, + })); + + test.done(); + }, + + 'get created with RemovalPolicy.RETAIN by default'(test: Test) { + const stack = new cdk.Stack(); + + new codebuild.ReportGroup(stack, 'ReportGroup'); + + expect(stack).to(haveResourceLike('AWS::CodeBuild::ReportGroup', { + "DeletionPolicy": "Retain", + "UpdateReplacePolicy": "Retain", + }, ResourcePart.CompleteDefinition)); + + test.done(); + }, + + 'can be created with RemovalPolicy.DESTROY'(test: Test) { + const stack = new cdk.Stack(); + + new codebuild.ReportGroup(stack, 'ReportGroup', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + + expect(stack).to(haveResourceLike('AWS::CodeBuild::ReportGroup', { + "DeletionPolicy": "Delete", + "UpdateReplacePolicy": "Delete", + }, ResourcePart.CompleteDefinition)); + + test.done(); + }, + }, +}; diff --git a/packages/@aws-cdk/aws-codecommit/package.json b/packages/@aws-cdk/aws-codecommit/package.json index 1cfef13e9218f..affeceeeca8a9 100644 --- a/packages/@aws-cdk/aws-codecommit/package.json +++ b/packages/@aws-cdk/aws-codecommit/package.json @@ -70,7 +70,7 @@ "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codepipeline-actions/package.json b/packages/@aws-cdk/aws-codepipeline-actions/package.json index a0f59a5e5ed50..70d8ff02b9ba4 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/package.json +++ b/packages/@aws-cdk/aws-codepipeline-actions/package.json @@ -50,10 +50,8 @@ }, "keywords": [ "aws", - "aws-clib", - "aws-cloudlib", "cdk", - "cloudlib", + "constructs", "codepipeline", "pipeline" ], diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.lambda-deployed-through-codepipeline.lit.expected.json b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.lambda-deployed-through-codepipeline.lit.expected.json index 36763b820707d..437b7116f5501 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.lambda-deployed-through-codepipeline.lit.expected.json +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.lambda-deployed-through-codepipeline.lit.expected.json @@ -1441,6 +1441,39 @@ } ] }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "CdkBuildProject9382C38D" + }, + "-*" + ] + ] + } + }, { "Action": [ "s3:GetObject*", @@ -1625,6 +1658,39 @@ } ] }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "LambdaBuildProject7E2DAB11" + }, + "-*" + ] + ] + } + }, { "Action": [ "s3:GetObject*", @@ -1731,4 +1797,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-build-multiple-inputs-outputs.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-build-multiple-inputs-outputs.ts index 4103f477d4bd4..c09c1a3328545 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-build-multiple-inputs-outputs.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-build-multiple-inputs-outputs.ts @@ -45,7 +45,9 @@ pipeline.addStage({ ], }); -const project = new codebuild.PipelineProject(stack, 'MyBuildProject'); +const project = new codebuild.PipelineProject(stack, 'MyBuildProject', { + grantReportGroupPermissions: false, +}); const buildAction = new cpactions.CodeBuildAction({ actionName: 'Build1', project, diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts index 7299b08576528..33311f6a5a7d6 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts @@ -21,7 +21,9 @@ const sourceAction = new cpactions.CodeCommitSourceAction({ trigger: cpactions.CodeCommitTrigger.POLL, }); -const project = new codebuild.PipelineProject(stack, 'MyBuildProject'); +const project = new codebuild.PipelineProject(stack, 'MyBuildProject', { + grantReportGroupPermissions: false, +}); const buildAction = new cpactions.CodeBuildAction({ actionName: 'build', project, diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.ts index 0f7f41277463e..4f5eba55965c1 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.ts @@ -72,6 +72,7 @@ const project = new codebuild.PipelineProject(stack, 'EcsProject', { value: repository.repositoryUri, }, }, + grantReportGroupPermissions: false, }); // needed for `docker push` repository.grantPullPush(project); diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-events.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-events.ts index 4b7d258c0d67d..399ebad05aa4f 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-events.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-events.ts @@ -18,7 +18,9 @@ const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline'); const repository = new codecommit.Repository(stack, 'CodeCommitRepo', { repositoryName: 'foo', }); -const project = new codebuild.PipelineProject(stack, 'BuildProject'); +const project = new codebuild.PipelineProject(stack, 'BuildProject', { + grantReportGroupPermissions: false, +}); const sourceOutput = new codepipeline.Artifact('Source'); const sourceAction = new cpactions.CodeCommitSourceAction({ diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts index 73f3de20ee7e2..64f9c44a41147 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts @@ -911,6 +911,9 @@ export = { { // log permissions from the CodeBuild Project Construct... }, + { + // report group permissions from the CodeBuild Project construct... + }, { 'Action': [ 's3:GetObject*', diff --git a/packages/@aws-cdk/aws-codepipeline/package.json b/packages/@aws-cdk/aws-codepipeline/package.json index 0f574afc32256..50bae2c548457 100644 --- a/packages/@aws-cdk/aws-codepipeline/package.json +++ b/packages/@aws-cdk/aws-codepipeline/package.json @@ -55,10 +55,8 @@ }, "keywords": [ "aws", - "aws-clib", - "aws-cloudlib", "cdk", - "cloudlib", + "constructs", "codepipeline", "pipeline" ], diff --git a/packages/@aws-cdk/aws-dynamodb/package.json b/packages/@aws-cdk/aws-dynamodb/package.json index 7cc73751141ea..1f5ab51d07702 100644 --- a/packages/@aws-cdk/aws-dynamodb/package.json +++ b/packages/@aws-cdk/aws-dynamodb/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/jest": "^25.2.1", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", @@ -72,7 +72,7 @@ "jest": "^25.5.4", "pkglint": "0.0.0", "sinon": "^9.0.2", - "ts-jest": "^25.4.0" + "ts-jest": "^25.5.0" }, "dependencies": { "@aws-cdk/aws-applicationautoscaling": "0.0.0", diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index eb0d83949f3b2..aa8b4aaaf3212 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -558,6 +558,19 @@ host.allowSshAccessFrom(ec2.Peer.ipv4('1.2.3.4/32')); As there are no SSH public keys deployed on this machine, you need to use [EC2 Instance Connect](https://aws.amazon.com/de/blogs/compute/new-using-amazon-ec2-instance-connect-for-ssh-access-to-your-ec2-instances/) with the command `aws ec2-instance-connect send-ssh-public-key` to provide your SSH public key. +EBS volume for the bastion host can be encrypted like: +```ts + const host = new ec2.BastionHostLinux(stack, 'BastionHost', { + vpc, + blockDevices: [{ + deviceName: 'EBSBastionHost', + volume: BlockDeviceVolume.ebs(10, { + encrypted: true, + }), + }], + }); +``` + ## Block Devices diff --git a/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts b/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts index 91c34ad17becf..00b6cd396ddf9 100644 --- a/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts +++ b/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts @@ -7,6 +7,7 @@ import { IMachineImage, MachineImage } from './machine-image'; import { IPeer } from './peer'; import { Port } from './port'; import { ISecurityGroup } from './security-group'; +import { BlockDevice } from './volume'; import { IVpc, SubnetSelection } from './vpc'; /** @@ -64,6 +65,20 @@ export interface BastionHostLinuxProps { * may be replaced on every deployment). */ readonly machineImage?: IMachineImage; + + /** + * Specifies how block devices are exposed to the instance. You can specify virtual devices and EBS volumes. + * + * Each instance that is launched has an associated root device volume, + * either an Amazon EBS volume or an instance store volume. + * You can use block device mappings to specify additional EBS volumes or + * instance store volumes to attach to an instance when it is launched. + * + * @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html + * + * @default - Uses the block device mapping of the AMI + */ + readonly blockDevices?: BlockDevice[]; } /** @@ -129,6 +144,7 @@ export class BastionHostLinux extends Construct implements IInstance { constructor(scope: Construct, id: string, props: BastionHostLinuxProps) { super(scope, id); this.stack = Stack.of(scope); + this.instance = new Instance(this, 'Resource', { vpc: props.vpc, availabilityZone: props.availabilityZone, @@ -137,6 +153,7 @@ export class BastionHostLinux extends Construct implements IInstance { instanceType: props.instanceType ?? InstanceType.of(InstanceClass.T3, InstanceSize.NANO), machineImage: props.machineImage ?? MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }), vpcSubnets: props.subnetSelection ?? {}, + blockDevices: props.blockDevices ?? undefined, }); this.instance.addToRolePolicy(new PolicyStatement({ actions: [ diff --git a/packages/@aws-cdk/aws-ec2/lib/machine-image.ts b/packages/@aws-cdk/aws-ec2/lib/machine-image.ts index b3fc7d902a82e..7f7862fce3539 100644 --- a/packages/@aws-cdk/aws-ec2/lib/machine-image.ts +++ b/packages/@aws-cdk/aws-ec2/lib/machine-image.ts @@ -1,4 +1,5 @@ import * as ssm from '@aws-cdk/aws-ssm'; +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Construct, ContextProvider, Stack, Token } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; import { UserData } from './user-data'; @@ -416,11 +417,11 @@ export class LookupMachineImage implements IMachineImage { Object.assign(filters, this.props.filters); const value = ContextProvider.getValue(scope, { - provider: cxapi.AMI_PROVIDER, + provider: cxschema.ContextProvider.AMI_PROVIDER, props: { owners: this.props.owners, filters, - } as cxapi.AmiContextQuery, + } as cxschema.AmiContextQuery, dummyValue: 'ami-1234', }).value as cxapi.AmiContextResponse; diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index a0effc595c2fd..25a3473e2d3f3 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -1,3 +1,4 @@ +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { ConcreteDependable, Construct, ContextProvider, DependableTrait, IConstruct, IDependable, IResource, Lazy, Resource, Stack, Tag, Token } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; @@ -1008,12 +1009,12 @@ export class Vpc extends VpcBase { } const attributes: cxapi.VpcContextResponse = ContextProvider.getValue(scope, { - provider: cxapi.VPC_PROVIDER, + provider: cxschema.ContextProvider.VPC_PROVIDER, props: { filter, returnAsymmetricSubnets: true, subnetGroupNameTag: options.subnetGroupNameTag, - } as cxapi.VpcContextQuery, + } as cxschema.VpcContextQuery, dummyValue: undefined, }).value; diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index 5e9c339a11057..0603d37d6ac67 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -79,6 +79,7 @@ "@aws-cdk/aws-ssm": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/region-info": "0.0.0", "constructs": "^3.0.2" }, @@ -91,6 +92,7 @@ "@aws-cdk/aws-ssm": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/region-info": "0.0.0", "constructs": "^3.0.2" }, diff --git a/packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts b/packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts index 5711f31826b57..4345718952364 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts +++ b/packages/@aws-cdk/aws-ec2/test/test.bastion-host.ts @@ -1,7 +1,7 @@ import { expect, haveResource } from '@aws-cdk/assert'; import { Stack } from '@aws-cdk/core'; import { Test } from 'nodeunit'; -import { BastionHostLinux, SubnetType, Vpc } from '../lib'; +import { BastionHostLinux, BlockDeviceVolume, SubnetType, Vpc } from '../lib'; export = { 'default instance is created in basic'(test: Test) { @@ -45,6 +45,44 @@ export = { SubnetId: {Ref: 'VPCIsolatedSubnet1SubnetEBD00FC6'}, })); + test.done(); + }, + 'ebs volume is encrypted'(test: Test) { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VPC', { + subnetConfiguration: [ + { + subnetType: SubnetType.ISOLATED, + name: 'Isolated', + }, + ], + }); + + // WHEN + new BastionHostLinux(stack, 'Bastion', { + vpc, + blockDevices: [{ + deviceName: 'EBSBastionHost', + volume: BlockDeviceVolume.ebs(10, { + encrypted: true, + }), + }], + }); + + // THEN + expect(stack).to(haveResource('AWS::EC2::Instance', { + BlockDeviceMappings: [ + { + DeviceName: 'EBSBastionHost', + Ebs: { + Encrypted: true, + VolumeSize: 10, + }, + }, + ], + })); + test.done(); }, }; diff --git a/packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts b/packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts index cbbb2550e2dcc..2cf0fac4a9e33 100644 --- a/packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts +++ b/packages/@aws-cdk/aws-ec2/test/test.vpc.from-lookup.ts @@ -1,3 +1,4 @@ +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Construct, ContextProvider, GetContextValueOptions, GetContextValueResult, Lazy, Stack } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; import { Test } from 'nodeunit'; @@ -218,12 +219,12 @@ interface MockVcpContextResponse { function mockVpcContextProviderWith( test: Test, response: MockVcpContextResponse, - paramValidator?: (options: cxapi.VpcContextQuery) => void) { + paramValidator?: (options: cxschema.VpcContextQuery) => void) { const previous = ContextProvider.getValue; ContextProvider.getValue = (_scope: Construct, options: GetContextValueOptions) => { // do some basic sanity checks - test.equal(options.provider, cxapi.VPC_PROVIDER, - `Expected provider to be: '${cxapi.VPC_PROVIDER}', got: '${options.provider}'`); + test.equal(options.provider, cxschema.ContextProvider.VPC_PROVIDER, + `Expected provider to be: '${cxschema.ContextProvider.VPC_PROVIDER}', got: '${options.provider}'`); test.equal((options.props || {}).returnAsymmetricSubnets, true, `Expected options.props.returnAsymmetricSubnets to be true, got: '${(options.props || {}).returnAsymmetricSubnets}'`); diff --git a/packages/@aws-cdk/aws-ecs/README.md b/packages/@aws-cdk/aws-ecs/README.md index 54dbb34a106fa..702c4617bace2 100644 --- a/packages/@aws-cdk/aws-ecs/README.md +++ b/packages/@aws-cdk/aws-ecs/README.md @@ -267,6 +267,8 @@ const service = new ecs.FargateService(this, 'Service', { desiredCount: 5 }); ``` +`Services` by default will create a security group if not provided. +If you'd like to specify which security groups to use you can override the `securityGroups` property. ### Include an application/network load balancer diff --git a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts index caf1cdaf93b86..ba6aa7451cdf2 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts @@ -347,7 +347,7 @@ export abstract class BaseService extends Resource propagateTags: props.propagateTags === PropagatedTagSource.NONE ? undefined : props.propagateTags, enableEcsManagedTags: props.enableECSManagedTags === undefined ? false : props.enableECSManagedTags, deploymentController: props.deploymentController, - launchType: props.launchType, + launchType: props.deploymentController?.type === DeploymentControllerType.EXTERNAL ? undefined : props.launchType, healthCheckGracePeriodSeconds: this.evaluateHealthGracePeriod(props.healthCheckGracePeriod), /* role: never specified, supplanted by Service Linked Role */ networkConfiguration: Lazy.anyValue({ produce: () => this.networkConfiguration }, { omitEmptyArray: true }), @@ -355,6 +355,10 @@ export abstract class BaseService extends Resource ...additionalProps, }); + if (props.deploymentController?.type === DeploymentControllerType.EXTERNAL) { + this.node.addWarning('taskDefinition and launchType are blanked out when using external deployment controller.'); + } + this.serviceArn = this.getResourceArnAttribute(this.resource.ref, { service: 'ecs', resource: 'service', @@ -582,6 +586,7 @@ export abstract class BaseService extends Resource /** * This method is called to create a networkConfiguration. + * @deprecated use configureAwsVpcNetworkingWithSecurityGroups instead. */ // tslint:disable-next-line:max-line-length protected configureAwsVpcNetworking(vpc: ec2.IVpc, assignPublicIp?: boolean, vpcSubnets?: ec2.SubnetSelection, securityGroup?: ec2.ISecurityGroup) { @@ -602,6 +607,29 @@ export abstract class BaseService extends Resource }; } + /** + * This method is called to create a networkConfiguration. + */ + // tslint:disable-next-line:max-line-length + protected configureAwsVpcNetworkingWithSecurityGroups(vpc: ec2.IVpc, assignPublicIp?: boolean, vpcSubnets?: ec2.SubnetSelection, securityGroups?: ec2.ISecurityGroup[]) { + if (vpcSubnets === undefined) { + vpcSubnets = assignPublicIp ? { subnetType: ec2.SubnetType.PUBLIC } : {}; + } + if (securityGroups === undefined || securityGroups.length === 0) { + securityGroups = [ new ec2.SecurityGroup(this, 'SecurityGroup', { vpc }) ]; + } + + securityGroups.forEach((sg) => { this.connections.addSecurityGroup(sg); }, this); + + this.networkConfiguration = { + awsvpcConfiguration: { + assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED', + subnets: vpc.selectSubnets(vpcSubnets).subnetIds, + securityGroups: securityGroups.map((sg) => sg.securityGroupId), + }, + }; + } + private renderServiceRegistry(registry: ServiceRegistry): CfnService.ServiceRegistryProperty { return { registryArn: registry.arn, diff --git a/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts b/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts index bf2bbe535210b..a04e51781b018 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts @@ -497,7 +497,7 @@ export class TaskDefinition extends TaskDefinitionBase { } } - return this.containers.map(x => x.renderContainerDefinition(this)); + return this.containers.map(x => x.renderContainerDefinition()); } } diff --git a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts index 0df5c0339beac..6e2a4f2868192 100644 --- a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts +++ b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts @@ -36,11 +36,24 @@ export abstract class Secret { public static fromSecretsManager(secret: secretsmanager.ISecret, field?: string): Secret { return { arn: field ? `${secret.secretArn}:${field}::` : secret.secretArn, + hasField: !!field, grantRead: grantee => secret.grantRead(grantee), }; } + /** + * The ARN of the secret + */ public abstract readonly arn: string; + + /** + * Whether this secret uses a specific JSON field + */ + public abstract readonly hasField?: boolean; + + /** + * Grants reading the secret to a principal + */ public abstract grantRead(grantee: iam.IGrantable): iam.Grant; } @@ -348,6 +361,8 @@ export class ContainerDefinition extends cdk.Construct { private readonly imageConfig: ContainerImageConfig; + private readonly secrets?: CfnTaskDefinition.SecretProperty[]; + /** * Constructs a new instance of the ContainerDefinition class. */ @@ -369,6 +384,20 @@ export class ContainerDefinition extends cdk.Construct { this.logDriverConfig = props.logging.bind(this, this); } props.taskDefinition._linkContainer(this); + + if (props.secrets) { + this.secrets = []; + for (const [name, secret] of Object.entries(props.secrets)) { + if (this.taskDefinition.isFargateCompatible && secret.hasField) { + throw new Error(`Cannot specify secret JSON field for a task using the FARGATE launch type: '${name}' in container '${this.node.id}'`); + } + secret.grantRead(this.taskDefinition.obtainExecutionRole()); + this.secrets.push({ + name, + valueFrom: secret.arn, + }); + } + } } /** @@ -519,9 +548,9 @@ export class ContainerDefinition extends cdk.Construct { /** * Render this container definition to a CloudFormation object * - * @param taskDefinition [disable-awslint:ref-via-interface] (made optional to avoid breaking change) + * @param _taskDefinition [disable-awslint:ref-via-interface] (unused but kept to avoid breaking change) */ - public renderContainerDefinition(taskDefinition?: TaskDefinition): CfnTaskDefinition.ContainerDefinitionProperty { + public renderContainerDefinition(_taskDefinition?: TaskDefinition): CfnTaskDefinition.ContainerDefinitionProperty { return { command: this.props.command, cpu: this.props.cpu, @@ -551,16 +580,7 @@ export class ContainerDefinition extends cdk.Construct { workingDirectory: this.props.workingDirectory, logConfiguration: this.logDriverConfig, environment: this.props.environment && renderKV(this.props.environment, 'name', 'value'), - secrets: this.props.secrets && Object.entries(this.props.secrets) - .map(([k, v]) => { - if (taskDefinition) { - v.grantRead(taskDefinition.obtainExecutionRole()); - } - return { - name: k, - valueFrom: v.arn, - }; - }), + secrets: this.secrets, extraHosts: this.props.extraHosts && renderKV(this.props.extraHosts, 'hostname', 'ipAddress'), healthCheck: this.props.healthCheck && renderHealthCheck(this.props.healthCheck), links: cdk.Lazy.listValue({ produce: () => this.links }, { omitEmpty: true }), diff --git a/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts b/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts index 4d3f3de89a628..d492687c3263d 100644 --- a/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts @@ -1,6 +1,6 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import { Construct, Lazy, Resource, Stack } from '@aws-cdk/core'; -import { BaseService, BaseServiceOptions, IBaseService, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; +import { BaseService, BaseServiceOptions, DeploymentControllerType, IBaseService, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; import { fromServiceAtrributes } from '../base/from-service-attributes'; import { NetworkMode, TaskDefinition } from '../base/task-definition'; import { ICluster } from '../cluster'; @@ -43,9 +43,19 @@ export interface Ec2ServiceProps extends BaseServiceOptions { * This property is only used for tasks that use the awsvpc network mode. * * @default - A new security group is created. + * @deprecated use securityGroups instead. */ readonly securityGroup?: ec2.ISecurityGroup; + /** + * The security groups to associate with the service. If you do not specify a security group, the default security group for the VPC is used. + * + * This property is only used for tasks that use the awsvpc network mode. + * + * @default - A new security group is created. + */ + readonly securityGroups?: ec2.ISecurityGroup[]; + /** * The placement constraints to use for tasks in the service. For more information, see * [Amazon ECS Task Placement Constraints](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html). @@ -154,8 +164,8 @@ export class Ec2Service extends BaseService implements IEc2Service { throw new Error('Maximum percent must be 100 for daemon mode.'); } - if (props.daemon && props.minHealthyPercent !== undefined && props.minHealthyPercent !== 0) { - throw new Error('Minimum healthy percent must be 0 for daemon mode.'); + if (props.minHealthyPercent !== undefined && props.maxHealthyPercent !== undefined && props.minHealthyPercent >= props.maxHealthyPercent) { + throw new Error('Minimum healthy percent must be less than maximum healthy percent.'); } if (!props.taskDefinition.isEc2Compatible) { @@ -166,6 +176,10 @@ export class Ec2Service extends BaseService implements IEc2Service { throw new Error('You can only specify either propagateTags or propagateTaskTagsFrom. Alternatively, you can leave both blank'); } + if (props.securityGroup !== undefined && props.securityGroups !== undefined) { + throw new Error('Only one of SecurityGroup or SecurityGroups can be populated.'); + } + const propagateTagsFromSource = props.propagateTaskTagsFrom !== undefined ? props.propagateTaskTagsFrom : (props.propagateTags !== undefined ? props.propagateTags : PropagatedTagSource.NONE); @@ -181,7 +195,7 @@ export class Ec2Service extends BaseService implements IEc2Service { }, { cluster: props.cluster.clusterName, - taskDefinition: props.taskDefinition.taskDefinitionArn, + taskDefinition: props.deploymentController?.type === DeploymentControllerType.EXTERNAL ? undefined : props.taskDefinition.taskDefinitionArn, placementConstraints: Lazy.anyValue({ produce: () => this.constraints }, { omitEmptyArray: true }), placementStrategies: Lazy.anyValue({ produce: () => this.strategies }, { omitEmptyArray: true }), schedulingStrategy: props.daemon ? 'DAEMON' : 'REPLICA', @@ -191,8 +205,15 @@ export class Ec2Service extends BaseService implements IEc2Service { this.strategies = []; this.daemon = props.daemon || false; + let securityGroups; + if (props.securityGroup !== undefined) { + securityGroups = [ props.securityGroup ]; + } else if (props.securityGroups !== undefined) { + securityGroups = props.securityGroups; + } + if (props.taskDefinition.networkMode === NetworkMode.AWS_VPC) { - this.configureAwsVpcNetworking(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, props.securityGroup); + this.configureAwsVpcNetworkingWithSecurityGroups(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, securityGroups); } else { // Either None, Bridge or Host networking. Copy SecurityGroups from ASG. // We have to be smart here -- by default future Security Group rules would be created @@ -251,11 +272,14 @@ export class Ec2Service extends BaseService implements IEc2Service { } /** - * Validate combinations of networking arguments + * Validate combinations of networking arguments. */ function validateNoNetworkingProps(props: Ec2ServiceProps) { - if (props.vpcSubnets !== undefined || props.securityGroup !== undefined || props.assignPublicIp) { - throw new Error('vpcSubnets, securityGroup and assignPublicIp can only be used in AwsVpc networking mode'); + if (props.vpcSubnets !== undefined + || props.securityGroup !== undefined + || props.securityGroups !== undefined + || props.assignPublicIp) { + throw new Error('vpcSubnets, securityGroup(s) and assignPublicIp can only be used in AwsVpc networking mode'); } } diff --git a/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts b/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts index cc1362f8ba270..185bc800e5da9 100644 --- a/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts @@ -1,6 +1,6 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; -import { BaseService, BaseServiceOptions, IBaseService, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; +import { BaseService, BaseServiceOptions, DeploymentControllerType, IBaseService, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; import { fromServiceAtrributes } from '../base/from-service-attributes'; import { TaskDefinition } from '../base/task-definition'; import { ICluster } from '../cluster'; @@ -36,9 +36,17 @@ export interface FargateServiceProps extends BaseServiceOptions { * The security groups to associate with the service. If you do not specify a security group, the default security group for the VPC is used. * * @default - A new security group is created. + * @deprecated use securityGroups instead. */ readonly securityGroup?: ec2.ISecurityGroup; + /** + * The security groups to associate with the service. If you do not specify a security group, the default security group for the VPC is used. + * + * @default - A new security group is created. + */ + readonly securityGroups?: ec2.ISecurityGroup[]; + /** * The platform version on which to run your service. * @@ -128,6 +136,10 @@ export class FargateService extends BaseService implements IFargateService { throw new Error('You can only specify either propagateTags or propagateTaskTagsFrom. Alternatively, you can leave both blank'); } + if (props.securityGroup !== undefined && props.securityGroups !== undefined) { + throw new Error('Only one of SecurityGroup or SecurityGroups can be populated.'); + } + const propagateTagsFromSource = props.propagateTaskTagsFrom !== undefined ? props.propagateTaskTagsFrom : (props.propagateTags !== undefined ? props.propagateTags : PropagatedTagSource.NONE); @@ -139,11 +151,18 @@ export class FargateService extends BaseService implements IFargateService { enableECSManagedTags: props.enableECSManagedTags, }, { cluster: props.cluster.clusterName, - taskDefinition: props.taskDefinition.taskDefinitionArn, + taskDefinition: props.deploymentController?.type === DeploymentControllerType.EXTERNAL ? undefined : props.taskDefinition.taskDefinitionArn, platformVersion: props.platformVersion, }, props.taskDefinition); - this.configureAwsVpcNetworking(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, props.securityGroup); + let securityGroups; + if (props.securityGroup !== undefined) { + securityGroups = [ props.securityGroup ]; + } else if (props.securityGroups !== undefined) { + securityGroups = props.securityGroups; + } + + this.configureAwsVpcNetworkingWithSecurityGroups(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, securityGroups); if (!props.taskDefinition.defaultContainer) { throw new Error('A TaskDefinition must have at least one essential container'); diff --git a/packages/@aws-cdk/aws-ecs/lib/firelens-log-router.ts b/packages/@aws-cdk/aws-ecs/lib/firelens-log-router.ts index 6b9394db7a92d..696da01332421 100644 --- a/packages/@aws-cdk/aws-ecs/lib/firelens-log-router.ts +++ b/packages/@aws-cdk/aws-ecs/lib/firelens-log-router.ts @@ -236,9 +236,9 @@ export class FirelensLogRouter extends ContainerDefinition { /** * Render this container definition to a CloudFormation object */ - public renderContainerDefinition(taskDefinition?: TaskDefinition): CfnTaskDefinition.ContainerDefinitionProperty { + public renderContainerDefinition(_taskDefinition?: TaskDefinition): CfnTaskDefinition.ContainerDefinitionProperty { return { - ...(super.renderContainerDefinition(taskDefinition)), + ...(super.renderContainerDefinition()), firelensConfiguration: this.firelensConfig && renderFirelensConfig(this.firelensConfig), }; } diff --git a/packages/@aws-cdk/aws-ecs/package.json b/packages/@aws-cdk/aws-ecs/package.json index be0f381abe0e3..3177fcc099d09 100644 --- a/packages/@aws-cdk/aws-ecs/package.json +++ b/packages/@aws-cdk/aws-ecs/package.json @@ -135,8 +135,6 @@ "docs-public-apis:@aws-cdk/aws-ecs.GelfCompressionType.GZIP", "docs-public-apis:@aws-cdk/aws-ecs.WindowsOptimizedVersion.SERVER_2016", "docs-public-apis:@aws-cdk/aws-ecs.WindowsOptimizedVersion.SERVER_2019", - "docs-public-apis:@aws-cdk/aws-ecs.Secret.arn", - "docs-public-apis:@aws-cdk/aws-ecs.Secret.grantRead", "props-default-doc:@aws-cdk/aws-ecs.AppMeshProxyConfigurationProps.egressIgnoredIPs", "props-default-doc:@aws-cdk/aws-ecs.AppMeshProxyConfigurationProps.egressIgnoredPorts", "props-default-doc:@aws-cdk/aws-ecs.AppMeshProxyConfigurationProps.ignoredGID", diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.secret-json-field.expected.json similarity index 94% rename from packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.expected.json rename to packages/@aws-cdk/aws-ecs/test/ec2/integ.secret-json-field.expected.json index 1a8e791bff7e1..5378fdbb03212 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.secret-json-field.expected.json @@ -33,6 +33,7 @@ { "Essential": true, "Image": "amazon/amazon-ecs-sample", + "Memory": 256, "Name": "web", "Secrets": [ { @@ -52,18 +53,16 @@ ] } ], - "Cpu": "512", "ExecutionRoleArn": { "Fn::GetAtt": [ "TaskDefExecutionRoleB4775C97", "Arn" ] }, - "Family": "awsecsintegsecretjsonkeyTaskDefC01C0E99", - "Memory": "1024", - "NetworkMode": "awsvpc", + "Family": "awsecsintegsecretjsonfieldTaskDef1C2EE990", + "NetworkMode": "bridge", "RequiresCompatibilities": [ - "FARGATE" + "EC2" ], "TaskRoleArn": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.ts b/packages/@aws-cdk/aws-ecs/test/ec2/integ.secret-json-field.ts similarity index 75% rename from packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.ts rename to packages/@aws-cdk/aws-ecs/test/ec2/integ.secret-json-field.ts index da2ca2630f032..be876a08b1bdf 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.secret-json-field.ts @@ -3,7 +3,7 @@ import * as cdk from '@aws-cdk/core'; import * as ecs from '../../lib'; const app = new cdk.App(); -const stack = new cdk.Stack(app, 'aws-ecs-integ-secret-json-key'); +const stack = new cdk.Stack(app, 'aws-ecs-integ-secret-json-field'); const secret = new secretsmanager.Secret(stack, 'Secret', { generateSecretString: { @@ -12,13 +12,11 @@ const secret = new secretsmanager.Secret(stack, 'Secret', { }, }); -const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef', { - memoryLimitMiB: 1024, - cpu: 512, -}); +const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); taskDefinition.addContainer('web', { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 256, secrets: { PASSWORD: ecs.Secret.fromSecretsManager(secret, 'password'), }, diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts index c870f53ddea35..6b74bcf656e9a 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts @@ -6,7 +6,7 @@ import * as cloudmap from '@aws-cdk/aws-servicediscovery'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; import * as ecs from '../../lib'; -import { LaunchType, PropagatedTagSource } from '../../lib/base/base-service'; +import { DeploymentControllerType, LaunchType, PropagatedTagSource } from '../../lib/base/base-service'; import { PlacementConstraint, PlacementStrategy } from '../../lib/placement'; export = { @@ -237,6 +237,165 @@ export = { test.done(); }, + 'with multiple security groups, it correctly updates the cfn template'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef', { + networkMode: ecs.NetworkMode.AWS_VPC, + }); + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + const securityGroup1 = new ec2.SecurityGroup(stack, 'SecurityGroup1', { + allowAllOutbound: true, + description: 'Example', + securityGroupName: 'Bingo', + vpc, + }); + const securityGroup2 = new ec2.SecurityGroup(stack, 'SecurityGroup2', { + allowAllOutbound: false, + description: 'Example', + securityGroupName: 'Rolly', + vpc, + }); + + // WHEN + new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + desiredCount: 2, + assignPublicIp: true, + daemon: false, + securityGroups: [ securityGroup1, securityGroup2 ], + serviceName: 'bonjour', + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + }); + + // THEN + expect(stack).to(haveResource('AWS::ECS::Service', { + TaskDefinition: { + Ref: 'Ec2TaskDef0226F28C', + }, + Cluster: { + Ref: 'EcsCluster97242B84', + }, + DesiredCount: 2, + LaunchType: LaunchType.EC2, + NetworkConfiguration: { + AwsvpcConfiguration: { + AssignPublicIp: 'ENABLED', + SecurityGroups: [ + { + 'Fn::GetAtt': [ + 'SecurityGroup1F554B36F', + 'GroupId', + ], + }, + { + 'Fn::GetAtt': [ + 'SecurityGroup23BE86BB7', + 'GroupId', + ], + }, + ], + Subnets: [ + { + Ref: 'MyVpcPublicSubnet1SubnetF6608456', + }, + { + Ref: 'MyVpcPublicSubnet2Subnet492B6BFB', + }, + ], + }, + }, + SchedulingStrategy: 'REPLICA', + ServiceName: 'bonjour', + })); + + expect(stack).to(haveResource('AWS::EC2::SecurityGroup', { + GroupDescription: 'Example', + GroupName: 'Bingo', + SecurityGroupEgress: [ + { + CidrIp: '0.0.0.0/0', + Description: 'Allow all outbound traffic by default', + IpProtocol: '-1', + }, + ], + VpcId: { + Ref: 'MyVpcF9F0CA6F', + }, + })); + + expect(stack).to(haveResource('AWS::EC2::SecurityGroup', { + GroupDescription: 'Example', + GroupName: 'Rolly', + SecurityGroupEgress: [ + { + CidrIp: '255.255.255.255/32', + Description: 'Disallow all traffic', + FromPort: 252, + IpProtocol: 'icmp', + ToPort: 86, + }, + ], + VpcId: { + Ref: 'MyVpcF9F0CA6F', + }, + })); + + test.done(); + }, + + 'throws when both securityGroup and securityGroups are supplied'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef', { + networkMode: ecs.NetworkMode.AWS_VPC, + }); + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + const securityGroup1 = new ec2.SecurityGroup(stack, 'SecurityGroup1', { + allowAllOutbound: true, + description: 'Example', + securityGroupName: 'Bingo', + vpc, + }); + const securityGroup2 = new ec2.SecurityGroup(stack, 'SecurityGroup2', { + allowAllOutbound: false, + description: 'Example', + securityGroupName: 'Rolly', + vpc, + }); + + // THEN + test.throws(() => { + new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + desiredCount: 2, + assignPublicIp: true, + maxHealthyPercent: 150, + minHealthyPercent: 55, + securityGroup: securityGroup1, + securityGroups: [ securityGroup2 ], + serviceName: 'bonjour', + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + }); + }, /Only one of SecurityGroup or SecurityGroups can be populated./); + + test.done(); + }, + 'throws when task definition is not EC2 compatible'(test: Test) { const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'MyVpc', {}); @@ -262,6 +421,45 @@ export = { test.done(); }, + 'ignore task definition and launch type if deployment controller is set to be EXTERNAL'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef'); + + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + + const service = new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + deploymentController: { + type: DeploymentControllerType.EXTERNAL, + }, + }); + + // THEN + test.deepEqual(service.node.metadata[0].data, 'taskDefinition and launchType are blanked out when using external deployment controller.'); + expect(stack).to(haveResource('AWS::ECS::Service', { + Cluster: { + Ref: 'EcsCluster97242B84', + }, + DeploymentConfiguration: { + MaximumPercent: 200, + MinimumHealthyPercent: 50, + }, + DesiredCount: 1, + SchedulingStrategy: 'REPLICA', + EnableECSManagedTags: false, + })); + + test.done(); + }, + 'errors if daemon and desiredCount both specified'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -312,7 +510,7 @@ export = { test.done(); }, - 'errors if daemon and minimum not 0'(test: Test) { + 'errors if minimum not less than maximum'(test: Test) { // GIVEN const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'MyVpc', {}); @@ -330,9 +528,10 @@ export = { cluster, taskDefinition, daemon: true, - minHealthyPercent: 50, + minHealthyPercent: 100, + maxHealthyPercent: 100, }); - }, /Minimum healthy percent must be 0 for daemon mode./); + }, /Minimum healthy percent must be less than maximum healthy percent./); test.done(); }, @@ -466,7 +665,100 @@ export = { taskDefinition, assignPublicIp: true, }); + }, /vpcSubnets, securityGroup\(s\) and assignPublicIp can only be used in AwsVpc networking mode/); + + // THEN + test.done(); + }, + + 'it errors if vpc subnets is provided'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const subnet = new ec2.Subnet(stack, 'MySubnet', { + vpcId: vpc.vpcId, + availabilityZone: 'eu-central-1a', + cidrBlock: '10.10.0.0/20', + }); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef', { + networkMode: ecs.NetworkMode.BRIDGE, }); + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + + // THEN + test.throws(() => { + new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + vpcSubnets: { + subnets: [subnet], + }, + }); + }, /vpcSubnets, securityGroup\(s\) and assignPublicIp can only be used in AwsVpc networking mode/); + + // THEN + test.done(); + }, + + 'it errors if security group is provided'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const securityGroup = new ec2.SecurityGroup(stack, 'MySG', { vpc }); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef', { + networkMode: ecs.NetworkMode.BRIDGE, + }); + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + + // THEN + test.throws(() => { + new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + securityGroup, + }); + }, /vpcSubnets, securityGroup\(s\) and assignPublicIp can only be used in AwsVpc networking mode/); + + // THEN + test.done(); + }, + + 'it errors if multiple security groups is provided'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const securityGroups = [ + new ec2.SecurityGroup(stack, 'MyFirstSG', { vpc }), + new ec2.SecurityGroup(stack, 'MySecondSG', { vpc }), + ]; + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef', { + networkMode: ecs.NetworkMode.BRIDGE, + }); + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 512, + }); + + // THEN + test.throws(() => { + new ecs.Ec2Service(stack, 'Ec2Service', { + cluster, + taskDefinition, + securityGroups, + }); + }, /vpcSubnets, securityGroup\(s\) and assignPublicIp can only be used in AwsVpc networking mode/); // THEN test.done(); diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret.expected.json new file mode 100644 index 0000000000000..919ea2bbf03d8 --- /dev/null +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret.expected.json @@ -0,0 +1,109 @@ +{ + "Resources": { + "SecretA720EF05": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "GenerateSecretString": { + "GenerateStringKey": "password", + "SecretStringTemplate": "{\"username\":\"user\"}" + } + } + }, + "TaskDefTaskRole1EDB4A67": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "TaskDef54694570": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "ContainerDefinitions": [ + { + "Essential": true, + "Image": "amazon/amazon-ecs-sample", + "Name": "web", + "Secrets": [ + { + "Name": "SECRET", + "ValueFrom": { + "Ref": "SecretA720EF05" + } + } + ] + } + ], + "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "TaskDefExecutionRoleB4775C97", + "Arn" + ] + }, + "Family": "awsecsintegsecretTaskDef58AA207D", + "Memory": "512", + "NetworkMode": "awsvpc", + "RequiresCompatibilities": [ + "FARGATE" + ], + "TaskRoleArn": { + "Fn::GetAtt": [ + "TaskDefTaskRole1EDB4A67", + "Arn" + ] + } + } + }, + "TaskDefExecutionRoleB4775C97": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "TaskDefExecutionRoleDefaultPolicy0DBB737A": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "secretsmanager:GetSecretValue", + "Effect": "Allow", + "Resource": { + "Ref": "SecretA720EF05" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "TaskDefExecutionRoleDefaultPolicy0DBB737A", + "Roles": [ + { + "Ref": "TaskDefExecutionRoleB4775C97" + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret.ts b/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret.ts new file mode 100644 index 0000000000000..7cc743c05209c --- /dev/null +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.secret.ts @@ -0,0 +1,24 @@ +import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; +import * as cdk from '@aws-cdk/core'; +import * as ecs from '../../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-ecs-integ-secret'); + +const secret = new secretsmanager.Secret(stack, 'Secret', { + generateSecretString: { + generateStringKey: 'password', + secretStringTemplate: JSON.stringify({ username: 'user' }), + }, +}); + +const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef'); + +taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + secrets: { + SECRET: ecs.Secret.fromSecretsManager(secret), + }, +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts b/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts index affc8dbcdbd50..454d904f7592f 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts @@ -7,7 +7,7 @@ import * as cloudmap from '@aws-cdk/aws-servicediscovery'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; import * as ecs from '../../lib'; -import { LaunchType } from '../../lib/base/base-service'; +import { DeploymentControllerType, LaunchType } from '../../lib/base/base-service'; export = { 'When creating a Fargate Service': { @@ -301,6 +301,66 @@ export = { test.done(); }, + 'ignore task definition and launch type if deployment controller is set to be EXTERNAL'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + const taskDefinition = new ecs.FargateTaskDefinition(stack, 'FargateTaskDef'); + + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }); + + const service = new ecs.FargateService(stack, 'FargateService', { + cluster, + taskDefinition, + deploymentController: { + type: DeploymentControllerType.EXTERNAL, + }, + }); + + // THEN + test.deepEqual(service.node.metadata[0].data, 'taskDefinition and launchType are blanked out when using external deployment controller.'); + expect(stack).to(haveResource('AWS::ECS::Service', { + Cluster: { + Ref: 'EcsCluster97242B84', + }, + DeploymentConfiguration: { + MaximumPercent: 200, + MinimumHealthyPercent: 50, + }, + DeploymentController: { + Type: 'EXTERNAL', + }, + DesiredCount: 1, + EnableECSManagedTags: false, + NetworkConfiguration: { + AwsvpcConfiguration: { + AssignPublicIp: 'DISABLED', + SecurityGroups: [ + { + 'Fn::GetAtt': [ + 'FargateServiceSecurityGroup0A0E79CB', + 'GroupId', + ], + }, + ], + Subnets: [ + { + Ref: 'MyVpcPrivateSubnet1Subnet5057CF7E', + }, + { + Ref: 'MyVpcPrivateSubnet2Subnet0040C983', + }, + ], + }, + }, + })); + + test.done(); + }, + 'errors when no container specified on task definition'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -374,6 +434,151 @@ export = { test.done(); }, + + 'throws when securityGroup and securityGroups are supplied'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + const taskDefinition = new ecs.FargateTaskDefinition(stack, 'FargateTaskDef'); + const securityGroup1 = new ec2.SecurityGroup(stack, 'SecurityGroup1', { + allowAllOutbound: true, + description: 'Example', + securityGroupName: 'Bingo', + vpc, + }); + const securityGroup2 = new ec2.SecurityGroup(stack, 'SecurityGroup2', { + allowAllOutbound: false, + description: 'Example', + securityGroupName: 'Rolly', + vpc, + }); + + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }); + + // THEN + test.throws(() => { + new ecs.FargateService(stack, 'FargateService', { + cluster, + taskDefinition, + securityGroup: securityGroup1, + securityGroups: [ securityGroup2 ], + }); + }, /Only one of SecurityGroup or SecurityGroups can be populated./); + + test.done(); + }, + + 'with multiple securty groups, it correctly updates cloudformation template'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + const taskDefinition = new ecs.FargateTaskDefinition(stack, 'FargateTaskDef'); + const securityGroup1 = new ec2.SecurityGroup(stack, 'SecurityGroup1', { + allowAllOutbound: true, + description: 'Example', + securityGroupName: 'Bingo', + vpc, + }); + const securityGroup2 = new ec2.SecurityGroup(stack, 'SecurityGroup2', { + allowAllOutbound: false, + description: 'Example', + securityGroupName: 'Rolly', + vpc, + }); + + taskDefinition.addContainer('web', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }); + + new ecs.FargateService(stack, 'FargateService', { + cluster, + taskDefinition, + securityGroups: [ securityGroup1, securityGroup2 ], + }); + + // THEN + expect(stack).to(haveResource('AWS::ECS::Service', { + TaskDefinition: { + Ref: 'FargateTaskDefC6FB60B4', + }, + Cluster: { + Ref: 'EcsCluster97242B84', + }, + DeploymentConfiguration: { + MaximumPercent: 200, + MinimumHealthyPercent: 50, + }, + DesiredCount: 1, + LaunchType: LaunchType.FARGATE, + EnableECSManagedTags: false, + NetworkConfiguration: { + AwsvpcConfiguration: { + AssignPublicIp: 'DISABLED', + SecurityGroups: [ + { + 'Fn::GetAtt': [ + 'SecurityGroup1F554B36F', + 'GroupId', + ], + }, + { + 'Fn::GetAtt': [ + 'SecurityGroup23BE86BB7', + 'GroupId', + ], + }, + ], + Subnets: [ + { + Ref: 'MyVpcPrivateSubnet1Subnet5057CF7E', + }, + { + Ref: 'MyVpcPrivateSubnet2Subnet0040C983', + }, + ], + }, + }, + })); + + expect(stack).to(haveResource('AWS::EC2::SecurityGroup', { + GroupDescription: 'Example', + GroupName: 'Bingo', + SecurityGroupEgress: [ + { + CidrIp: '0.0.0.0/0', + Description: 'Allow all outbound traffic by default', + IpProtocol: '-1', + }, + ], + VpcId: { + Ref: 'MyVpcF9F0CA6F', + }, + })); + + expect(stack).to(haveResource('AWS::EC2::SecurityGroup', { + GroupDescription: 'Example', + GroupName: 'Rolly', + SecurityGroupEgress: [ + { + CidrIp: '255.255.255.255/32', + Description: 'Disallow all traffic', + FromPort: 252, + IpProtocol: 'icmp', + ToPort: 86, + }, + ], + VpcId: { + Ref: 'MyVpcF9F0CA6F', + }, + })); + + test.done(); + }, + }, 'When setting up a health check': { diff --git a/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts b/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts index af49fe3f4054e..cccb2e9efdefb 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts @@ -843,6 +843,25 @@ export = { }, + 'throws when using a specific secret JSON field as environment variable for a Fargate task'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef'); + + const secret = new secretsmanager.Secret(stack, 'Secret'); + + // THEN + test.throws(() => taskDefinition.addContainer('cont', { + image: ecs.ContainerImage.fromRegistry('test'), + memoryLimitMiB: 1024, + secrets: { + SECRET_KEY: ecs.Secret.fromSecretsManager(secret, 'specificKey'), + }, + }), /Cannot specify secret JSON field for a task using the FARGATE launch type/); + + test.done(); + }, + 'can add AWS logging to container definition'(test: Test) { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts index 3d0c8c25e39a3..45ec209a0c15c 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster-resource-handler/cluster.ts @@ -149,7 +149,14 @@ export class ClusterResourceHandler extends ResourceHandler { // if this is an EKS update, we will monitor the update event itself if (this.event.EksUpdateId) { - return this.isEksUpdateComplete(this.event.EksUpdateId); + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. } return this.isActive(); @@ -212,9 +219,9 @@ export class ClusterResourceHandler extends ResourceHandler { switch (describeUpdateResponse.update.status) { case 'InProgress': - return { IsComplete: false }; + return false; case 'Successful': - return { IsComplete: true }; + return true; case 'Failed': case 'Cancelled': throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index 163503378762b..d856da674f46b 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json index a1476ff383d49..eabb31a0c499f 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json @@ -851,6 +851,7 @@ "Arn" ] }, + "version": "1.16", "resourcesVpcConfig": { "securityGroupIds": [ { @@ -1322,7 +1323,7 @@ "Type": "AWS::AutoScaling::LaunchConfiguration", "Properties": { "ImageId": { - "Ref": "SsmParameterValueawsserviceeksoptimizedami114amazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + "Ref": "SsmParameterValueawsserviceeksoptimizedami116amazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" }, "InstanceType": "t2.medium", "IamInstanceProfile": { @@ -1912,7 +1913,7 @@ "Type": "AWS::AutoScaling::LaunchConfiguration", "Properties": { "ImageId": { - "Ref": "SsmParameterValueawsserviceeksoptimizedami114amazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + "Ref": "SsmParameterValueawsserviceeksoptimizedami116amazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" }, "InstanceType": "t3.large", "IamInstanceProfile": { @@ -2223,7 +2224,7 @@ }, "/", { - "Ref": "AssetParametersfa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103S3Bucket4281E0A4" + "Ref": "AssetParameters222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2S3BucketC839B0E2" }, "/", { @@ -2233,7 +2234,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersfa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103S3VersionKey3B54BD32" + "Ref": "AssetParameters222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2S3VersionKeyEEF27FE8" } ] } @@ -2246,7 +2247,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParametersfa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103S3VersionKey3B54BD32" + "Ref": "AssetParameters222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2S3VersionKeyEEF27FE8" } ] } @@ -2256,11 +2257,11 @@ ] }, "Parameters": { - "referencetoawscdkeksclustertestAssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602S3Bucket38D74D5ERef": { - "Ref": "AssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602S3BucketD006BE3B" + "referencetoawscdkeksclustertestAssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5S3Bucket278A73D2Ref": { + "Ref": "AssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5S3Bucket91F3EC34" }, - "referencetoawscdkeksclustertestAssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602S3VersionKey189EBCBARef": { - "Ref": "AssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602S3VersionKeyEC71339F" + "referencetoawscdkeksclustertestAssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5S3VersionKeyD7A198A8Ref": { + "Ref": "AssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5S3VersionKey29EF2E8E" }, "referencetoawscdkeksclustertestAssetParameters5e49cf64d8027f48872790f80cdb76c5b836ecf9a70b71be1eb937a5c25a47c1S3BucketC7CBF350Ref": { "Ref": "AssetParameters5e49cf64d8027f48872790f80cdb76c5b836ecf9a70b71be1eb937a5c25a47c1S3Bucket663A709C" @@ -2405,17 +2406,17 @@ } }, "Parameters": { - "AssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602S3BucketD006BE3B": { + "AssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5S3Bucket91F3EC34": { "Type": "String", - "Description": "S3 bucket for asset \"c0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602\"" + "Description": "S3 bucket for asset \"80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5\"" }, - "AssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602S3VersionKeyEC71339F": { + "AssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5S3VersionKey29EF2E8E": { "Type": "String", - "Description": "S3 key for asset version \"c0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602\"" + "Description": "S3 key for asset version \"80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5\"" }, - "AssetParametersc0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602ArtifactHash35F5D0CC": { + "AssetParameters80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5ArtifactHash2145581C": { "Type": "String", - "Description": "Artifact hash for asset \"c0e453b77d5ccf090915fba7c771380f8370da5cbcc3c7ed757c98addd75b602\"" + "Description": "Artifact hash for asset \"80599c1e26718262302e982159fe61aff7a2bdd392db341e7e99cbfbf84a0be5\"" }, "AssetParameters5e49cf64d8027f48872790f80cdb76c5b836ecf9a70b71be1eb937a5c25a47c1S3Bucket663A709C": { "Type": "String", @@ -2441,17 +2442,17 @@ "Type": "String", "Description": "Artifact hash for asset \"a6d508eaaa0d3cddbb47a84123fc878809c8431c5466f360912f70b5b9770afb\"" }, - "AssetParametersfa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103S3Bucket4281E0A4": { + "AssetParameters222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2S3BucketC839B0E2": { "Type": "String", - "Description": "S3 bucket for asset \"fa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103\"" + "Description": "S3 bucket for asset \"222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2\"" }, - "AssetParametersfa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103S3VersionKey3B54BD32": { + "AssetParameters222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2S3VersionKeyEEF27FE8": { "Type": "String", - "Description": "S3 key for asset version \"fa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103\"" + "Description": "S3 key for asset version \"222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2\"" }, - "AssetParametersfa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103ArtifactHash733CC5DF": { + "AssetParameters222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2ArtifactHashAF96C5C2": { "Type": "String", - "Description": "Artifact hash for asset \"fa73027e9f72f21daca2d67aa5a23e88f87d90536a7e3c36de9adbfb27fa9103\"" + "Description": "Artifact hash for asset \"222a8e375c233b55d0c3e20bc9ac98ffc8e51132f82b0f12f3cd1b7b22c562c2\"" }, "AssetParameters36525a61abfaf5764fad460fd03c24215fd00da60805807d6138c51be4d03dbcS3Bucket2D824DEF": { "Type": "String", @@ -2465,9 +2466,9 @@ "Type": "String", "Description": "Artifact hash for asset \"36525a61abfaf5764fad460fd03c24215fd00da60805807d6138c51be4d03dbc\"" }, - "SsmParameterValueawsserviceeksoptimizedami114amazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "SsmParameterValueawsserviceeksoptimizedami116amazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { "Type": "AWS::SSM::Parameter::Value", - "Default": "/aws/service/eks/optimized-ami/1.14/amazon-linux-2/recommended/image_id" + "Default": "/aws/service/eks/optimized-ami/1.16/amazon-linux-2/recommended/image_id" }, "SsmParameterValueawsservicebottlerocketawsk8s115x8664latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts index dc5d383cccff4..a6eda3ab3eeee 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts @@ -18,6 +18,7 @@ class EksClusterStack extends TestStack { const cluster = new eks.Cluster(this, 'Cluster', { mastersRole, defaultCapacity: 2, + version: '1.16', }); // // fargate profile for resources in the "default" namespace diff --git a/packages/@aws-cdk/aws-eks/test/test.cluster-resource-provider.ts b/packages/@aws-cdk/aws-eks/test/test.cluster-resource-provider.ts index 0759704acead4..9b9baaafab141 100644 --- a/packages/@aws-cdk/aws-eks/test/test.cluster-resource-provider.ts +++ b/packages/@aws-cdk/aws-eks/test/test.cluster-resource-provider.ts @@ -401,7 +401,7 @@ export = { test.done(); }, - async 'with "Successful" status, returns IsComplete=true'(test: Test) { + async 'with "Successful" status, returns IsComplete=true with "Data"'(test: Test) { const event = mocks.newRequest('Update'); const isCompleteHandler = new ClusterResourceHandler(mocks.client, { ...event, @@ -413,7 +413,15 @@ export = { const response = await isCompleteHandler.isComplete(); test.deepEqual(mocks.actualRequest.describeUpdateRequest, { name: 'physical-resource-id', updateId: 'foobar' }); - test.equal(response.IsComplete, true); + test.deepEqual(response, { + IsComplete: true, + Data: { + Name: 'physical-resource-id', + Endpoint: 'http://endpoint', + Arn: 'arn:cluster-arn', + CertificateAuthorityData: 'certificateAuthority-data', + }, + }); test.done(); }, diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json index 41fc004f0d9b4..ff807a3b702cf 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-targets/package.json @@ -66,9 +66,9 @@ "keywords": [ "aws", "cdk", - "cloudlib", - "aws-cloudlib", - "aws-clib" + "constructs", + "elasticloadbalancing", + "elb" ], "author": { "name": "Amazon Web Services", diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index 304225705ae61..fa91e4b0e62b2 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -71,9 +71,7 @@ "keywords": [ "aws", "cdk", - "cloudlib", - "aws-cloudlib", - "aws-clib", + "constructs", "cloudwatch", "events" ], @@ -86,7 +84,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-codecommit": "0.0.0", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.expected.json b/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.expected.json index 6f5b91fffaefa..178bba14bbc1c 100644 --- a/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.expected.json @@ -155,6 +155,39 @@ ] } ] + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":codebuild:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":report-group/", + { + "Ref": "MyProject39F7B0AE" + }, + "-*" + ] + ] + } } ], "Version": "2012-10-17" @@ -386,4 +419,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-events/package.json b/packages/@aws-cdk/aws-events/package.json index 1cbd6a9fbfbfc..1316ef04bbb92 100644 --- a/packages/@aws-cdk/aws-events/package.json +++ b/packages/@aws-cdk/aws-events/package.json @@ -52,9 +52,9 @@ "keywords": [ "aws", "cdk", - "cloudlib", - "aws-cloudlib", - "aws-clib" + "constructs", + "cloudwatch", + "events" ], "author": { "name": "Amazon Web Services", diff --git a/packages/@aws-cdk/aws-iam/README.md b/packages/@aws-cdk/aws-iam/README.md index acc92ebfcb3a8..68b64d27c5024 100644 --- a/packages/@aws-cdk/aws-iam/README.md +++ b/packages/@aws-cdk/aws-iam/README.md @@ -238,6 +238,50 @@ const newPolicyDocument = PolicyDocument.fromJson(policyDocument); ``` +### OpenID Connect Providers + +OIDC identity providers are entities in IAM that describe an external identity +provider (IdP) service that supports the [OpenID Connect] (OIDC) standard, such +as Google or Salesforce. You use an IAM OIDC identity provider when you want to +establish trust between an OIDC-compatible IdP and your AWS account. This is +useful when creating a mobile app or web application that requires access to AWS +resources, but you don't want to create custom sign-in code or manage your own +user identities. For more information about this scenario, see [About Web +Identity Federation] and the relevant documentation in the [Amazon Cognito +Identity Pools Developer Guide]. + +[OpenID Connect]: http://openid.net/connect +[About Web Identity Federation]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html +[Amazon Cognito Identity Pools Developer Guide]: https://docs.aws.amazon.com/cognito/latest/developerguide/open-id.html + +The following examples defines an OpenID Connect provider. Two client IDs +(audiences) are will be able to send authentication requests to +https://openid/connect. + +```ts +const provider = new OpenIdConnectProvider(this, 'MyProvider', { + url: 'https://openid/connect', + clients: [ 'myclient1', 'myclient2' ] +}); +``` + +You can specify an optional list of `thumbprints`. If not specified, the +thumbprint of the root certificate authority (CA) will automatically be obtained +from the host as described +[here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html). + +Once you define an OpenID connect provider, you can use it with AWS services +that expect an IAM OIDC provider. For example, when you define an [Amazon +Cognito identity +pool](https://docs.aws.amazon.com/cognito/latest/developerguide/open-id.html) +you can reference the provider's ARN as follows: + +```ts +new cognito.CfnIdentityPool(this, 'IdentityPool', { + openIdConnectProviderARNs: [ provider.openIdConnectProviderArn ] +}); +``` + ### Features * Policy name uniqueness is enforced. If two policies by the same name are attached to the same diff --git a/packages/@aws-cdk/aws-iam/lib/index.ts b/packages/@aws-cdk/aws-iam/lib/index.ts index 0d0804ed8faca..ba9250ca1e08e 100644 --- a/packages/@aws-cdk/aws-iam/lib/index.ts +++ b/packages/@aws-cdk/aws-iam/lib/index.ts @@ -10,6 +10,7 @@ export * from './principals'; export * from './identity-base'; export * from './grant'; export * from './unknown-principal'; +export * from './oidc-provider'; // AWS::IAM CloudFormation Resources: export * from './iam.generated'; diff --git a/packages/@aws-cdk/aws-iam/lib/oidc-provider.ts b/packages/@aws-cdk/aws-iam/lib/oidc-provider.ts new file mode 100644 index 0000000000000..06fe2395f687f --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/oidc-provider.ts @@ -0,0 +1,154 @@ +import { Construct, CustomResource, CustomResourceProvider, CustomResourceProviderRuntime, IResource, Resource, Stack, Token } from '@aws-cdk/core'; +import * as path from 'path'; + +const RESOURCE_TYPE = 'Custom::AWSCDKOpenIdConnectProvider'; + +/** + * Represents an IAM OpenID Connect provider. + * + * @experimental + */ +export interface IOpenIdConnectProvider extends IResource { + /** + * The Amazon Resource Name (ARN) of the IAM OpenID Connect provider. + */ + readonly openIdConnectProviderArn: string; +} + +/** + * Initialization properties for `OpenIdConnectProvider`. + * @experimental + */ +export interface OpenIdConnectProviderProps { + /** + * The URL of the identity provider. The URL must begin with https:// and + * should correspond to the iss claim in the provider's OpenID Connect ID + * tokens. Per the OIDC standard, path components are allowed but query + * parameters are not. Typically the URL consists of only a hostname, like + * https://server.example.org or https://example.com. + * + * You cannot register the same provider multiple times in a single AWS + * account. If you try to submit a URL that has already been used for an + * OpenID Connect provider in the AWS account, you will get an error. + */ + readonly url: string; + + /** + * A list of client IDs (also known as audiences). When a mobile or web app + * registers with an OpenID Connect provider, they establish a value that + * identifies the application. (This is the value that's sent as the client_id + * parameter on OAuth requests.) + * + * You can register multiple client IDs with the same provider. For example, + * you might have multiple applications that use the same OIDC provider. You + * cannot register more than 100 client IDs with a single IAM OIDC provider. + * + * Client IDs are up to 255 characters long. + * + * @default - no clients are allowed + */ + readonly clientIds?: string[]; + + /** + * A list of server certificate thumbprints for the OpenID Connect (OIDC) + * identity provider's server certificates. + * + * Typically this list includes only one entry. However, IAM lets you have up + * to five thumbprints for an OIDC provider. This lets you maintain multiple + * thumbprints if the identity provider is rotating certificates. + * + * The server certificate thumbprint is the hex-encoded SHA-1 hash value of + * the X.509 certificate used by the domain where the OpenID Connect provider + * makes its keys available. It is always a 40-character string. + * + * You must provide at least one thumbprint when creating an IAM OIDC + * provider. For example, assume that the OIDC provider is server.example.com + * and the provider stores its keys at + * https://keys.server.example.com/openid-connect. In that case, the + * thumbprint string would be the hex-encoded SHA-1 hash value of the + * certificate used by https://keys.server.example.com. + * + * @default - If no thumbprints are specified (an empty array or `undefined`), + * the thumbprint of the root certificate authority will be obtained from the + * provider's server as described in https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html + */ + readonly thumbprints?: string[]; +} + +/** + * IAM OIDC identity providers are entities in IAM that describe an external + * identity provider (IdP) service that supports the OpenID Connect (OIDC) + * standard, such as Google or Salesforce. You use an IAM OIDC identity provider + * when you want to establish trust between an OIDC-compatible IdP and your AWS + * account. This is useful when creating a mobile app or web application that + * requires access to AWS resources, but you don't want to create custom sign-in + * code or manage your own user identities. + * + * @see http://openid.net/connect + * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html + * + * @experimental + */ +export class OpenIdConnectProvider extends Construct implements IOpenIdConnectProvider { + /** + * Imports an Open ID connect provider from an ARN. + * @param scope The definition scope + * @param id ID of the construct + * @param openIdConnectProviderArn the ARN to import + */ + public static fromOpenIdConnectProviderArn(scope: Construct, id: string, openIdConnectProviderArn: string): IOpenIdConnectProvider { + class Import extends Resource implements IOpenIdConnectProvider { + public readonly openIdConnectProviderArn = openIdConnectProviderArn; + } + return new Import(scope, id); + } + + /** + * The Amazon Resource Name (ARN) of the IAM OpenID Connect provider. + */ + public readonly openIdConnectProviderArn: string; + + /** + * Defines an OpenID Connect provider. + * @param scope The definition scope + * @param id Construct ID + * @param props Initialization properties + */ + public constructor(scope: Construct, id: string, props: OpenIdConnectProviderProps) { + super(scope, id); + + const resource = new CustomResource(this, 'Resource', { + resourceType: RESOURCE_TYPE, + serviceToken: this.getOrCreateProvider(), + properties: { + ClientIDList: props.clientIds, + ThumbprintList: props.thumbprints, + Url: props.url, + }, + }); + + this.openIdConnectProviderArn = Token.asString(resource.ref); + } + + public get stack() { return Stack.of(this); } + + private getOrCreateProvider() { + return CustomResourceProvider.getOrCreate(this, RESOURCE_TYPE, { + codeDirectory: path.join(__dirname, 'oidc-provider'), + runtime: CustomResourceProviderRuntime.NODEJS_12, + policyStatements: [ + { + Effect: 'Allow', + Resource: '*', + Action: [ + 'iam:CreateOpenIDConnectProvider', + 'iam:DeleteOpenIDConnectProvider', + 'iam:UpdateOpenIDConnectProviderThumbprint', + 'iam:AddClientIDToOpenIDConnectProvider', + 'iam:RemoveClientIDFromOpenIDConnectProvider', + ], + }, + ], + }); + } +} diff --git a/packages/@aws-cdk/aws-iam/lib/oidc-provider/diff.ts b/packages/@aws-cdk/aws-iam/lib/oidc-provider/diff.ts new file mode 100644 index 0000000000000..8a91e6ebddc53 --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/oidc-provider/diff.ts @@ -0,0 +1,17 @@ +export function arrayDiff(oldValues: string[], newValues: string[]) { + const deletes = new Set(oldValues); + const adds = new Set(); + + for (const v of new Set(newValues)) { + if (deletes.has(v)) { + deletes.delete(v); + } else { + adds.add(v); + } + } + + return { + adds: Array.from(adds), + deletes: Array.from(deletes), + }; +} diff --git a/packages/@aws-cdk/aws-iam/lib/oidc-provider/external.ts b/packages/@aws-cdk/aws-iam/lib/oidc-provider/external.ts new file mode 100644 index 0000000000000..43512b4bc7a4e --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/oidc-provider/external.ts @@ -0,0 +1,53 @@ +/* istanbul ignore file */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import * as tls from 'tls'; +import * as url from 'url'; + +let client: aws.IAM; + +function iam() { + if (!client) { client = new aws.IAM(); } + return client; +} + +function defaultLogger(fmt: string, ...args: any[]) { + // tslint:disable-next-line: no-console + console.log(fmt, ...args); +} + +/** + * Downloads the CA thumbprint from the issuer URL + */ +async function downloadThumbprint(issuerUrl: string) { + external.log(`downloading certificate authority thumbprint for ${issuerUrl}`); + return new Promise((ok, ko) => { + const purl = url.parse(issuerUrl); + const port = purl.port ? parseInt(purl.port, 10) : 443; + if (!purl.host) { + return ko(new Error(`unable to determine host from issuer url ${issuerUrl}`)); + } + const socket = tls.connect(port, purl.host, { rejectUnauthorized: false }); + socket.once('error', ko); + socket.once('secureConnect', () => { + const cert = socket.getPeerCertificate(); + socket.end(); + const thumbprint = cert.fingerprint.split(':').join(''); + external.log(`certificate authority thumbprint for ${issuerUrl} is ${thumbprint}`); + ok(thumbprint); + }); + }); +} + +// allows unit test to replace with mocks +// tslint:disable:max-line-length +export const external = { + downloadThumbprint, + log: defaultLogger, + createOpenIDConnectProvider: (req: aws.IAM.CreateOpenIDConnectProviderRequest) => iam().createOpenIDConnectProvider(req).promise(), + deleteOpenIDConnectProvider: (req: aws.IAM.DeleteOpenIDConnectProviderRequest) => iam().deleteOpenIDConnectProvider(req).promise(), + updateOpenIDConnectProviderThumbprint: (req: aws.IAM.UpdateOpenIDConnectProviderThumbprintRequest) => iam().updateOpenIDConnectProviderThumbprint(req).promise(), + addClientIDToOpenIDConnectProvider: (req: aws.IAM.AddClientIDToOpenIDConnectProviderRequest) => iam().addClientIDToOpenIDConnectProvider(req).promise(), + removeClientIDFromOpenIDConnectProvider: (req: aws.IAM.RemoveClientIDFromOpenIDConnectProviderRequest) => iam().removeClientIDFromOpenIDConnectProvider(req).promise(), +}; diff --git a/packages/@aws-cdk/aws-iam/lib/oidc-provider/index.ts b/packages/@aws-cdk/aws-iam/lib/oidc-provider/index.ts new file mode 100644 index 0000000000000..2ba997ae0252c --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/oidc-provider/index.ts @@ -0,0 +1,89 @@ +import { arrayDiff } from './diff'; +import { external } from './external'; + +export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { + if (event.RequestType === 'Create') { return onCreate(event); } + if (event.RequestType === 'Update') { return onUpdate(event); } + if (event.RequestType === 'Delete') { return onDelete(event); } + throw new Error('invalid request type'); +} + +async function onCreate(event: AWSLambda.CloudFormationCustomResourceCreateEvent) { + const issuerUrl = event.ResourceProperties.Url; + const thumbprints: string[] = (event.ResourceProperties.ThumbprintList ?? []).sort(); // keep sorted for UPDATE + const clients: string[] = (event.ResourceProperties.ClientIDList ?? []).sort(); + + if (thumbprints.length === 0) { + thumbprints.push(await external.downloadThumbprint(issuerUrl)); + } + + const resp = await external.createOpenIDConnectProvider({ + Url: issuerUrl, + ClientIDList: clients, + ThumbprintList: thumbprints, + }); + + return { + PhysicalResourceId: resp.OpenIDConnectProviderArn, + }; +} + +async function onUpdate(event: AWSLambda.CloudFormationCustomResourceUpdateEvent) { + const issuerUrl = event.ResourceProperties.Url; + const thumbprints: string[] = (event.ResourceProperties.ThumbprintList ?? []).sort(); // keep sorted for UPDATE + const clients: string[] = (event.ResourceProperties.ClientIDList ?? []).sort(); + + // determine which update we are talking about. + const oldIssuerUrl = event.OldResourceProperties.Url; + + // if this is a URL update, then we basically create a new resource and cfn will delete the old one + // since the physical resource ID will change. + if (oldIssuerUrl !== issuerUrl) { + return onCreate({ ...event, RequestType: 'Create' }); + } + + const providerArn = event.PhysicalResourceId; + + // if thumbprints changed, we can update in-place, but bear in mind that if the new thumbprint list + // is empty, we will grab it from the server like we do in CREATE + const oldThumbprints = (event.OldResourceProperties.ThumbprintList || []).sort(); + if (JSON.stringify(oldThumbprints) !== JSON.stringify(thumbprints)) { + const thumbprintList = thumbprints.length > 0 ? thumbprints : [ await external.downloadThumbprint(issuerUrl) ]; + external.log('updating thumbprint list from', oldThumbprints, 'to', thumbprints); + await external.updateOpenIDConnectProviderThumbprint({ + OpenIDConnectProviderArn: providerArn, + ThumbprintList: thumbprintList, + }); + + // don't return, we might have more updates... + } + + // if client ID list has changed, determine "diff" because the API is add/remove + const oldClients: string[] = (event.OldResourceProperties.ClientIDList || []).sort(); + const diff = arrayDiff(oldClients, clients); + external.log(`client ID diff: ${JSON.stringify(diff)}`); + + for (const addClient of diff.adds) { + external.log(`adding client id "${addClient}" to provider ${providerArn}`); + await external.addClientIDToOpenIDConnectProvider({ + OpenIDConnectProviderArn: providerArn, + ClientID: addClient, + }); + } + + for (const deleteClient of diff.deletes) { + external.log(`removing client id "${deleteClient}" from provider ${providerArn}`); + await external.removeClientIDFromOpenIDConnectProvider({ + OpenIDConnectProviderArn: providerArn, + ClientID: deleteClient, + }); + } + + return; +} + +async function onDelete(deleteEvent: AWSLambda.CloudFormationCustomResourceDeleteEvent) { + await external.deleteOpenIDConnectProvider({ + OpenIDConnectProviderArn: deleteEvent.PhysicalResourceId, + }); +} diff --git a/packages/@aws-cdk/aws-iam/package.json b/packages/@aws-cdk/aws-iam/package.json index 70bb91dab947f..e81c7b6b22b0f 100644 --- a/packages/@aws-cdk/aws-iam/package.json +++ b/packages/@aws-cdk/aws-iam/package.json @@ -52,9 +52,7 @@ "keywords": [ "aws", "cdk", - "cloudlib", - "aws-cloudlib", - "aws-clib", + "constructs", "iam" ], "author": { @@ -69,7 +67,8 @@ "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^25.5.4", - "pkglint": "0.0.0" + "pkglint": "0.0.0", + "sinon": "^9.0.2" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-iam/test/integ.oidc-provider.expected.json b/packages/@aws-cdk/aws-iam/test/integ.oidc-provider.expected.json new file mode 100644 index 0000000000000..11c2bd0f23a4c --- /dev/null +++ b/packages/@aws-cdk/aws-iam/test/integ.oidc-provider.expected.json @@ -0,0 +1,167 @@ +{ + "Resources": { + "NoClientsNoThumbprint8BF1533F": { + "Type": "Custom::AWSCDKOpenIdConnectProvider", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0", + "Arn" + ] + }, + "Url": "https://oidc.eks.us-east-1.amazonaws.com/id/test2" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": "*", + "Action": [ + "iam:CreateOpenIDConnectProvider", + "iam:DeleteOpenIDConnectProvider", + "iam:UpdateOpenIDConnectProviderThumbprint", + "iam:AddClientIDToOpenIDConnectProvider", + "iam:RemoveClientIDFromOpenIDConnectProvider" + ] + } + ] + } + } + ] + } + }, + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParameters4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319S3Bucket718B603F" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319S3VersionKey6B97A1A3" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParameters4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319S3VersionKey6B97A1A3" + } + ] + } + ] + } + ] + ] + } + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65", + "Arn" + ] + }, + "Runtime": "nodejs12.x" + }, + "DependsOn": [ + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderRole517FED65" + ] + }, + "Clients67031123": { + "Type": "Custom::AWSCDKOpenIdConnectProvider", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0", + "Arn" + ] + }, + "ClientIDList": [ + "foo", + "bar" + ], + "Url": "https://oidc.eks.us-east-1.amazonaws.com/id/test3" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "Thumbprints9CD6AB02": { + "Type": "Custom::AWSCDKOpenIdConnectProvider", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomAWSCDKOpenIdConnectProviderCustomResourceProviderHandlerF2C543E0", + "Arn" + ] + }, + "ThumbprintList": [ + "aa00aa1122aa00aa1122aa00aa1122aa00aa1122", + "aa00aa1122aa00aa1122aa00aa1122aa00aa1111" + ], + "Url": "https://oidc.eks.us-east-1.amazonaws.com/id/test4" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "AssetParameters4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319S3Bucket718B603F": { + "Type": "String", + "Description": "S3 bucket for asset \"4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319\"" + }, + "AssetParameters4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319S3VersionKey6B97A1A3": { + "Type": "String", + "Description": "S3 key for asset version \"4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319\"" + }, + "AssetParameters4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319ArtifactHash96BDDF33": { + "Type": "String", + "Description": "Artifact hash for asset \"4c04b604b3ea48cf40394c3b4b898525a99ce5f981bc13ad94bf126997416319\"" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/test/integ.oidc-provider.ts b/packages/@aws-cdk/aws-iam/test/integ.oidc-provider.ts new file mode 100644 index 0000000000000..33a241251f4bf --- /dev/null +++ b/packages/@aws-cdk/aws-iam/test/integ.oidc-provider.ts @@ -0,0 +1,24 @@ +import { App, Stack } from '@aws-cdk/core'; +import * as iam from '../lib'; + +const app = new App(); +const stack = new Stack(app, 'oidc-provider-integ-test'); + +new iam.OpenIdConnectProvider(stack, 'NoClientsNoThumbprint', { + url: 'https://oidc.eks.us-east-1.amazonaws.com/id/test2', +}); + +new iam.OpenIdConnectProvider(stack, 'Clients', { + url: 'https://oidc.eks.us-east-1.amazonaws.com/id/test3', + clientIds: [ 'foo', 'bar' ], +}); + +new iam.OpenIdConnectProvider(stack, 'Thumbprints', { + url: 'https://oidc.eks.us-east-1.amazonaws.com/id/test4', + thumbprints: [ + 'aa00aa1122aa00aa1122aa00aa1122aa00aa1122', + 'aa00aa1122aa00aa1122aa00aa1122aa00aa1111', + ], +}); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/test/oidc-provider.test.ts b/packages/@aws-cdk/aws-iam/test/oidc-provider.test.ts new file mode 100644 index 0000000000000..590744949b58d --- /dev/null +++ b/packages/@aws-cdk/aws-iam/test/oidc-provider.test.ts @@ -0,0 +1,393 @@ +import '@aws-cdk/assert/jest'; +import { App, Stack } from '@aws-cdk/core'; +import * as sinon from 'sinon'; +import * as iam from '../lib'; +import { arrayDiff } from '../lib/oidc-provider/diff'; +import { external } from '../lib/oidc-provider/external'; +import * as handler from '../lib/oidc-provider/index'; + +describe('OpenIdConnectProvider resource', () => { + + test('minimal configuration (no clients and no thumbprint)', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new iam.OpenIdConnectProvider(stack, 'MyProvider', { + url: 'https://openid-endpoint', + }); + + // THEN + expect(stack).toHaveResource('Custom::AWSCDKOpenIdConnectProvider', { + Url: 'https://openid-endpoint', + }); + }); + + test('"openIdConnectProviderArn" resolves to the ref', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const provider = new iam.OpenIdConnectProvider(stack, 'MyProvider', { + url: 'https://openid-endpoint', + }); + + // THEN + expect(stack.resolve(provider.openIdConnectProviderArn)).toStrictEqual({ Ref: 'MyProvider730BA1C8' }); + }); + + test('static fromOpenIdConnectProviderArn can be used to import a provider', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const provider = iam.OpenIdConnectProvider.fromOpenIdConnectProviderArn(stack, 'MyProvider', 'arn:of:provider'); + + // THEN + expect(stack.resolve(provider.openIdConnectProviderArn)).toStrictEqual('arn:of:provider'); + }); + + test('thumbprint list and client ids can be specified', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new iam.OpenIdConnectProvider(stack, 'MyProvider', { + url: 'https://my-url', + clientIds: [ 'client1', 'client2' ], + thumbprints: [ 'thumb1' ], + }); + + // THEN + expect(stack).toHaveResource('Custom::AWSCDKOpenIdConnectProvider', { + Url: 'https://my-url', + ClientIDList: [ 'client1', 'client2' ], + ThumbprintList: [ 'thumb1' ], + }); + }); + +}); + +describe('custom resource provider infrastructure', () => { + + test('two resources share the same cr provider', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'stack'); + + // WHEN + new iam.OpenIdConnectProvider(stack, 'Provider1', { url: 'provider1' }); + new iam.OpenIdConnectProvider(stack, 'Provider2', { url: 'provider2' }); + + // THEN + const template = app.synth().getStackArtifact(stack.artifactId).template; + const resourceTypes = Object.values(template.Resources).map((r: any) => r.Type).sort(); + expect(resourceTypes).toStrictEqual([ + // custom resource perovider resources + 'AWS::IAM::Role', + 'AWS::Lambda::Function', + + // open id connect resources + 'Custom::AWSCDKOpenIdConnectProvider', + 'Custom::AWSCDKOpenIdConnectProvider', + ]); + }); + + test('iam policy', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new iam.OpenIdConnectProvider(stack, 'Provider1', { url: 'provider1' }); + + // THEN + expect(stack).toHaveResource('AWS::IAM::Role', { + Policies: [ + { + PolicyName: 'Inline', + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Effect: 'Allow', + Resource: '*', + Action: [ + 'iam:CreateOpenIDConnectProvider', + 'iam:DeleteOpenIDConnectProvider', + 'iam:UpdateOpenIDConnectProviderThumbprint', + 'iam:AddClientIDToOpenIDConnectProvider', + 'iam:RemoveClientIDFromOpenIDConnectProvider', + ], + }, + ], + }, + }, + ], + }); + }); +}); + +describe('custom resource provider handler', () => { + external.log = () => { return; }; // disable verbosity for tests + const downloadThumbprint = external.downloadThumbprint = sinon.fake.returns('FAKE-THUMBPRINT'); + const createOpenIDConnectProvider = external.createOpenIDConnectProvider = sinon.fake.resolves({ OpenIDConnectProviderArn: 'FAKE-ARN' }); + const deleteOpenIDConnectProvider = external.deleteOpenIDConnectProvider = sinon.fake.resolves({ }); + const updateOpenIDConnectProviderThumbprint = external.updateOpenIDConnectProviderThumbprint = sinon.fake.resolves({ }); + const addClientIDToOpenIDConnectProvider = external.addClientIDToOpenIDConnectProvider = sinon.fake.resolves({ }); + const removeClientIDFromOpenIDConnectProvider = external.removeClientIDFromOpenIDConnectProvider = sinon.fake.resolves({ }); + + beforeEach(() => sinon.reset()); + + test('create with url will download thumbprint from host', async () => { + // WHEN + const response = await invokeHandler({ + RequestType: 'Create', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://my-urlx', + ThumbprintList: [ 'MyThumbprint' ], + }, + }); + + // THEN + sinon.assert.notCalled(downloadThumbprint); + sinon.assert.calledWithExactly(createOpenIDConnectProvider, { + ClientIDList: [], + Url: 'https://my-urlx', + ThumbprintList: [ 'MyThumbprint' ], + }); + + expect(response).toStrictEqual({ + PhysicalResourceId: 'FAKE-ARN', + }); + }); + + test('create without thumbprint will download from host', async () => { + // WHEN + const response = await invokeHandler({ + RequestType: 'Create', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://my-urlx', + }, + }); + + // THEN + sinon.assert.calledWithExactly(downloadThumbprint, 'https://my-urlx'); + sinon.assert.calledWithExactly(createOpenIDConnectProvider, { + ClientIDList: [], + Url: 'https://my-urlx', + ThumbprintList: [ 'FAKE-THUMBPRINT' ], + }); + + expect(response).toStrictEqual({ + PhysicalResourceId: 'FAKE-ARN', + }); + }); + + test('delete', async () => { + // WHEN + await invokeHandler({ + RequestType: 'Delete', + PhysicalResourceId: 'FAKE-ARN', + }); + + // THEN + sinon.assert.notCalled(downloadThumbprint); + sinon.assert.notCalled(createOpenIDConnectProvider); + sinon.assert.calledWithExactly(deleteOpenIDConnectProvider, { + OpenIDConnectProviderArn: 'FAKE-ARN', + }); + }); + + test('update url with explicit thumbprints (replace)', async () => { + // WHEN + const response = await invokeHandler({ + RequestType: 'Update', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://new', + ThumbprintList: [ 'THUMB1', 'THUMB2' ], + }, + OldResourceProperties: { + Url: 'https://old', + }, + }); + + // THEN + expect(response).toStrictEqual({ + PhysicalResourceId: 'FAKE-ARN', + }); + sinon.assert.notCalled(downloadThumbprint); + sinon.assert.calledWithExactly(createOpenIDConnectProvider, { + ClientIDList: [], + Url: 'https://new', + ThumbprintList: [ 'THUMB1', 'THUMB2' ], + }); + }); + + test('update url with no thumbprint (replace)', async () => { + // WHEN + const response = await invokeHandler({ + RequestType: 'Update', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://new', + }, + OldResourceProperties: { + Url: 'https://old', + }, + }); + + // THEN + expect(response).toStrictEqual({ + PhysicalResourceId: 'FAKE-ARN', + }); + sinon.assert.calledOnceWithExactly(downloadThumbprint, 'https://new'); + sinon.assert.calledOnceWithExactly(createOpenIDConnectProvider, { + ClientIDList: [], + Url: 'https://new', + ThumbprintList: [ 'FAKE-THUMBPRINT' ], + }); + sinon.assert.notCalled(deleteOpenIDConnectProvider); + }); + + test('update thumbprint list', async () => { + // WHEN + await invokeHandler({ + RequestType: 'Update', + PhysicalResourceId: 'FAKE-PhysicalResourceId', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://url', + ThumbprintList: [ 'Foo', 'Bar' ], + }, + OldResourceProperties: { + Url: 'https://url', + ThumbprintList: [ 'Foo' ], + }, + }); + + // THEN + sinon.assert.notCalled(downloadThumbprint); + sinon.assert.notCalled(createOpenIDConnectProvider); + sinon.assert.notCalled(deleteOpenIDConnectProvider); + sinon.assert.calledOnceWithExactly(updateOpenIDConnectProviderThumbprint, { + OpenIDConnectProviderArn: 'FAKE-PhysicalResourceId', + ThumbprintList: [ 'Bar', 'Foo' ], + }); + }); + + test('add/remove client ids', async () => { + // WHEN + await invokeHandler({ + RequestType: 'Update', + PhysicalResourceId: 'FAKE-PhysicalResourceId', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://url', + ClientIDList: [ 'A', 'B', 'C' ], + }, + OldResourceProperties: { + Url: 'https://url', + ClientIDList: [ 'A', 'D' ], + }, + }); + + // THEN + sinon.assert.notCalled(downloadThumbprint); + sinon.assert.notCalled(createOpenIDConnectProvider); + sinon.assert.notCalled(deleteOpenIDConnectProvider); + sinon.assert.notCalled(updateOpenIDConnectProviderThumbprint); + sinon.assert.calledTwice(addClientIDToOpenIDConnectProvider); + sinon.assert.calledWithExactly(addClientIDToOpenIDConnectProvider, { + OpenIDConnectProviderArn: 'FAKE-PhysicalResourceId', ClientID: 'B', + }); + sinon.assert.calledWithExactly(addClientIDToOpenIDConnectProvider, { + OpenIDConnectProviderArn: 'FAKE-PhysicalResourceId', ClientID: 'C', + }); + sinon.assert.calledOnceWithExactly(removeClientIDFromOpenIDConnectProvider, { + OpenIDConnectProviderArn: 'FAKE-PhysicalResourceId', ClientID: 'D', + }); + }); + + test('multiple in-place updates (no replace)', async () => { + // WHEN + await invokeHandler({ + RequestType: 'Update', + PhysicalResourceId: 'FAKE-PhysicalResourceId', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://url', + ThumbprintList: [ 'NEW-LIST' ], + ClientIDList: [ 'A' ], + }, + OldResourceProperties: { + Url: 'https://url', + ThumbprintList: [ 'OLD-LIST' ], + ClientIDList: [ ], + }, + }); + + // THEN + sinon.assert.notCalled(downloadThumbprint); + sinon.assert.notCalled(createOpenIDConnectProvider); + sinon.assert.notCalled(deleteOpenIDConnectProvider); + sinon.assert.notCalled(removeClientIDFromOpenIDConnectProvider); + sinon.assert.calledOnceWithExactly(updateOpenIDConnectProviderThumbprint, { + OpenIDConnectProviderArn: 'FAKE-PhysicalResourceId', + ThumbprintList: [ 'NEW-LIST' ], + }); + sinon.assert.calledOnceWithExactly(addClientIDToOpenIDConnectProvider, { + OpenIDConnectProviderArn: 'FAKE-PhysicalResourceId', + ClientID: 'A', + }); + }); + + test('multiple updates that include a url update, which means replacement', async () => { + // WHEN + await invokeHandler({ + RequestType: 'Update', + PhysicalResourceId: 'FAKE-PhysicalResourceId', + ResourceProperties: { + ServiceToken: 'Foo', + Url: 'https://new-url', + ClientIDList: [ 'A' ], + }, + OldResourceProperties: { + Url: 'https://old-url', + ThumbprintList: [ 'OLD-LIST' ], + ClientIDList: [ ], + }, + }); + + // THEN + sinon.assert.notCalled(deleteOpenIDConnectProvider); + sinon.assert.notCalled(removeClientIDFromOpenIDConnectProvider); + sinon.assert.notCalled(updateOpenIDConnectProviderThumbprint); + sinon.assert.notCalled(addClientIDToOpenIDConnectProvider); + sinon.assert.calledOnceWithExactly(downloadThumbprint, 'https://new-url'); // since thumbprint list is empty + sinon.assert.calledOnceWithExactly(createOpenIDConnectProvider, { + ClientIDList: [ 'A' ], + ThumbprintList: [ 'FAKE-THUMBPRINT' ], + Url: 'https://new-url', + }); + }); + +}); + +describe('arrayDiff', () => { + test('calculates the difference between two arrays', () => { + expect(arrayDiff([ 'a', 'b', 'c' ], [ 'a', 'd' ])).toStrictEqual({ adds: [ 'd' ], deletes: [ 'b', 'c' ]}); + expect(arrayDiff([ 'a', 'b', 'c' ], [ ])).toStrictEqual({ adds: [], deletes: [ 'a', 'b', 'c' ] }); + expect(arrayDiff([ 'a', 'b', 'c' ], [ 'a', 'c', 'b' ])).toStrictEqual({ adds: [], deletes: [] }); + expect(arrayDiff([ ], [ 'a', 'c', 'b' ])).toStrictEqual({ adds: [ 'a', 'c', 'b' ], deletes: [] }); + expect(arrayDiff([ 'x', 'y' ], [ 'a', 'c', 'b' ])).toStrictEqual({ adds: [ 'a', 'c', 'b' ], deletes: [ 'x', 'y' ]}); + expect(arrayDiff([ ], [ ])).toStrictEqual({ adds: [], deletes: [] }); + expect(arrayDiff([ 'a', 'a' ], [ 'a', 'b', 'a', 'b', 'b' ])).toStrictEqual({ adds: [ 'b' ], deletes: [] }); + }); +}); + +async function invokeHandler(event: Partial) { + return await handler.handler(event as any); +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index 1d0406e045a0a..2063950e3dedb 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -11,14 +11,7 @@ This library provides constructs for Node.js Lambda functions. -To use this module, you will need to add a dependency on `parcel-bundler` in your -`package.json`: - -``` -yarn add parcel-bundler@^1 -# or -npm install parcel-bundler@^1 -``` +To use this module, you will need to have Docker installed. ### Node.js Function Define a `NodejsFunction`: diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/builder.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/builder.ts index 1c0074299a44d..41ad7aa0df53a 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/builder.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/builder.ts @@ -1,7 +1,7 @@ import { spawnSync } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; -import { findPkgPath, updatePkg } from './util'; +import { findPkgPath } from './util'; /** * Builder options @@ -40,47 +40,83 @@ export interface BuilderOptions { /** * The node version to use as target for Babel */ - readonly nodeVersion?: string; + readonly nodeVersion: string; + + /** + * The docker tag of the node base image to use in the parcel-bundler docker image + * + * @see https://hub.docker.com/_/node/?tab=tags + */ + readonly nodeDockerTag: string; + + /** + * The root of the project. This will be used as the source for the volume + * mounted in the Docker container. + */ + readonly projectRoot: string; } /** * Builder */ export class Builder { - private readonly parcelBinPath: string; + private readonly pkgPath: string; - constructor(private readonly options: BuilderOptions) { - let parcelPkgPath: string; - try { - parcelPkgPath = require.resolve('parcel-bundler/package.json'); // This will throw if `parcel-bundler` cannot be found - } catch (err) { - throw new Error('It looks like parcel-bundler is not installed. Please install v1.x of parcel-bundler with yarn or npm.'); - } - const parcelDir = path.dirname(parcelPkgPath); - const parcelPkg = JSON.parse(fs.readFileSync(parcelPkgPath, 'utf8')); + private readonly originalPkg: Buffer; - if (!parcelPkg.version || !/^1\./.test(parcelPkg.version)) { // Peer dependency on parcel v1.x - throw new Error(`This module has a peer dependency on parcel-bundler v1.x. Got v${parcelPkg.version}.`); - } + private readonly originalPkgJson: { [key: string]: any }; - this.parcelBinPath = path.join(parcelDir, parcelPkg.bin.parcel); + constructor(private readonly options: BuilderOptions) { + // Original package.json + const pkgPath = findPkgPath(); + if (!pkgPath) { + throw new Error('Cannot find a `package.json` in this project.'); + } + this.pkgPath = path.join(pkgPath, 'package.json'); + this.originalPkg = fs.readFileSync(this.pkgPath); + this.originalPkgJson = JSON.parse(this.originalPkg.toString()); } + /** + * Build with parcel in a Docker container + */ public build(): void { - const pkgPath = findPkgPath(); - let originalPkg; - try { - if (this.options.nodeVersion && pkgPath) { - // Update engines.node (Babel target) - originalPkg = updatePkg(pkgPath, { - engines: { node: `>= ${this.options.nodeVersion}` }, - }); + this.updatePkg(); + + const dockerBuildArgs = [ + 'build', + '--build-arg', `NODE_TAG=${this.options.nodeDockerTag}`, + '-t', 'parcel-bundler', + path.join(__dirname, '../parcel-bundler'), + ]; + + const build = spawnSync('docker', dockerBuildArgs); + + if (build.error) { + throw build.error; + } + + if (build.status !== 0) { + throw new Error(`[Status ${build.status}] stdout: ${build.stdout?.toString().trim()}\n\n\nstderr: ${build.stderr?.toString().trim()}`); } - const args = [ - 'build', this.options.entry, - '--out-dir', this.options.outDir, + const containerProjectRoot = '/project'; + const containerOutDir = '/out'; + const containerCacheDir = '/cache'; + const containerEntryPath = path.join(containerProjectRoot, path.relative(this.options.projectRoot, path.resolve(this.options.entry))); + + const dockerRunArgs = [ + 'run', '--rm', + '-v', `${this.options.projectRoot}:${containerProjectRoot}`, + '-v', `${path.resolve(this.options.outDir)}:${containerOutDir}`, + ...(this.options.cacheDir ? ['-v', `${path.resolve(this.options.cacheDir)}:${containerCacheDir}`] : []), + '-w', path.dirname(containerEntryPath), + 'parcel-bundler', + ]; + const parcelArgs = [ + 'parcel', 'build', containerEntryPath, + '--out-dir', containerOutDir, '--out-file', 'index.js', '--global', this.options.global, '--target', 'node', @@ -88,26 +124,43 @@ export class Builder { '--log-level', '2', !this.options.minify && '--no-minify', !this.options.sourceMaps && '--no-source-maps', - ...this.options.cacheDir - ? ['--cache-dir', this.options.cacheDir] - : [], + ...(this.options.cacheDir ? ['--cache-dir', containerCacheDir] : []), ].filter(Boolean) as string[]; - const parcel = spawnSync(this.parcelBinPath, args); + const parcel = spawnSync('docker', [...dockerRunArgs, ...parcelArgs]); if (parcel.error) { throw parcel.error; } if (parcel.status !== 0) { - throw new Error(parcel.stdout.toString().trim()); + throw new Error(`[Status ${parcel.status}] stdout: ${parcel.stdout?.toString().trim()}\n\n\nstderr: ${parcel.stderr?.toString().trim()}`); } } catch (err) { throw new Error(`Failed to build file at ${this.options.entry}: ${err}`); } finally { // Always restore package.json to original - if (pkgPath && originalPkg) { - fs.writeFileSync(pkgPath, originalPkg); - } + this.restorePkg(); } } + + /** + * Updates the package.json to configure Parcel + */ + private updatePkg() { + const updateData: { [key: string]: any } = {}; + // Update engines.node (Babel target) + updateData.engines = { node: `>= ${this.options.nodeVersion}` }; + + // Write new package.json + if (Object.keys(updateData).length !== 0) { + fs.writeFileSync(this.pkgPath, JSON.stringify({ + ...this.originalPkgJson, + ...updateData, + }, null, 2)); + } + } + + private restorePkg() { + fs.writeFileSync(this.pkgPath, this.originalPkg); + } } diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts index b3646bd4b0597..276885e5a22d3 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts @@ -4,7 +4,7 @@ import * as crypto from 'crypto'; import * as fs from 'fs'; import * as path from 'path'; import { Builder } from './builder'; -import { nodeMajorVersion, parseStackTrace } from './util'; +import { findGitPath, nodeMajorVersion, parseStackTrace } from './util'; /** * Properties for a NodejsFunction @@ -65,6 +65,25 @@ export interface NodejsFunctionProps extends lambda.FunctionOptions { * @default - `.cache` in the root directory */ readonly cacheDir?: string; + + /** + * The docker tag of the node base image to use in the parcel-bundler docker image + * + * @see https://hub.docker.com/_/node/?tab=tags + * + * @default - the `process.versions.node` alpine image + */ + readonly nodeDockerTag?: string; + + /** + * The root of the project. This will be used as the source for the volume + * mounted in the Docker container. If you specify this prop, ensure that + * this path includes `entry` and any module/dependencies used by your + * function otherwise bundling will not be possible. + * + * @default - the closest path containing a .git folder + */ + readonly projectRoot?: string; } /** @@ -84,6 +103,10 @@ export class NodejsFunction extends lambda.Function { ? lambda.Runtime.NODEJS_12_X : lambda.Runtime.NODEJS_10_X; const runtime = props.runtime || defaultRunTime; + const projectRoot = props.projectRoot ?? findGitPath(); + if (!projectRoot) { + throw new Error('Cannot find project root. Please specify it with `projectRoot`.'); + } // Build with Parcel const builder = new Builder({ @@ -94,6 +117,8 @@ export class NodejsFunction extends lambda.Function { sourceMaps: props.sourceMaps, cacheDir: props.cacheDir, nodeVersion: extractVersion(runtime), + nodeDockerTag: props.nodeDockerTag || `${process.versions.node}-alpine`, + projectRoot: path.resolve(projectRoot), }); builder.build(); @@ -156,11 +181,11 @@ function findDefiningFile(): string { /** * Extracts the version from the runtime */ -function extractVersion(runtime: lambda.Runtime): string | undefined { +function extractVersion(runtime: lambda.Runtime): string { const match = runtime.name.match(/nodejs(\d+)/); if (!match) { - return undefined; + throw new Error('Cannot extract version from runtime.'); } return match[1]; diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts index b28f29a9fe373..c54b0e3ed56c4 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/util.ts @@ -1,4 +1,5 @@ import * as fs from 'fs'; +import * as path from 'path'; // From https://github.com/errwischt/stacktrace-parser/blob/master/src/stack-trace-parser.js const STACK_RE = /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i; @@ -50,35 +51,28 @@ export function nodeMajorVersion(): number { } /** - * Finds closest package.json path + * Finds the closest path containg a path */ -export function findPkgPath(): string | undefined { - let pkgPath; - - for (const path of module.paths) { - pkgPath = path.replace(/node_modules$/, 'package.json'); - if (fs.existsSync(pkgPath)) { - break; +function findClosestPathContaining(p: string): string | undefined { + for (const nodeModulesPath of module.paths) { + if (fs.existsSync(path.join(path.dirname(nodeModulesPath), p))) { + return path.dirname(nodeModulesPath); } } - return pkgPath; + return undefined; } /** - * Updates the package.json and returns the original + * Finds closest package.json path */ -export function updatePkg(pkgPath: string, data: any): Buffer { - const original = fs.readFileSync(pkgPath); - - const pkgJson = JSON.parse(original.toString()); - - const updated = { - ...pkgJson, - ...data, - }; - - fs.writeFileSync(pkgPath, JSON.stringify(updated, null, 2)); +export function findPkgPath(): string | undefined { + return findClosestPathContaining('package.json'); +} - return original; +/** + * Finds closest .git/ + */ +export function findGitPath(): string | undefined { + return findClosestPathContaining(`.git${path.sep}`); } diff --git a/packages/@aws-cdk/aws-lambda-nodejs/package.json b/packages/@aws-cdk/aws-lambda-nodejs/package.json index d86a54303988e..9d21067b2c8f0 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/package.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/package.json @@ -80,7 +80,6 @@ "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "fs-extra": "^8.1.0", - "parcel-bundler": "^1.12.4", "pkglint": "0.0.0" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-lambda-nodejs/parcel-bundler/Dockerfile b/packages/@aws-cdk/aws-lambda-nodejs/parcel-bundler/Dockerfile new file mode 100644 index 0000000000000..0a92746c6464c --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/parcel-bundler/Dockerfile @@ -0,0 +1,10 @@ +# runs the parcel-bundler npm package to package and install dependencies of nodejs lambda functions +ARG NODE_TAG +FROM node:${NODE_TAG} + +RUN yarn global add parcel-bundler@^1 + +# add the global node_modules folder to NODE_PATH so that plugins can find parcel-bundler +ENV NODE_PATH /usr/local/share/.config/yarn/global/node_modules + +CMD [ "parcel" ] diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/builder.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/builder.test.ts index e888c0f51d010..e6e32655a187e 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/builder.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/builder.test.ts @@ -1,44 +1,52 @@ import { spawnSync } from 'child_process'; -import * as fs from 'fs'; +import * as path from 'path'; import { Builder } from '../lib/builder'; -let parcelPkgPath: string; -let parcelPkg: Buffer; -beforeAll(() => { - parcelPkgPath = require.resolve('parcel-bundler/package.json'); - parcelPkg = fs.readFileSync(parcelPkgPath); -}); - -afterEach(() => { - fs.writeFileSync(parcelPkgPath, parcelPkg); -}); - jest.mock('child_process', () => ({ spawnSync: jest.fn((_cmd: string, args: string[]) => { - if (args[1] === 'error') { + if (args.includes('/project/folder/error')) { return { error: 'parcel-error' }; } - if (args[1] === 'status') { + if (args.includes('/project/folder/status')) { return { status: 1, stdout: Buffer.from('status-error') }; } + if (args.includes('/project/folder/no-docker')) { + return { error: 'Error: spawnSync docker ENOENT' }; + } + return { error: null, status: 0 }; }), })); -test('calls parcel with the correct args', () => { +test('calls docker with the correct args', () => { const builder = new Builder({ - entry: 'entry', + entry: '/project/folder/entry.ts', global: 'handler', - outDir: 'out-dir', - cacheDir: 'cache-dir', + outDir: '/out-dir', + cacheDir: '/cache-dir', + nodeDockerTag: 'lts-alpine', + nodeVersion: '12', + projectRoot: '/project', }); builder.build(); - expect(spawnSync).toHaveBeenCalledWith(expect.stringContaining('parcel-bundler'), expect.arrayContaining([ - 'build', 'entry', - '--out-dir', 'out-dir', + // docker build + expect(spawnSync).toHaveBeenNthCalledWith(1, 'docker', [ + 'build', '--build-arg', 'NODE_TAG=lts-alpine', '-t', 'parcel-bundler', path.join(__dirname, '../parcel-bundler'), + ]); + + // docker run + expect(spawnSync).toHaveBeenNthCalledWith(2, 'docker', [ + 'run', '--rm', + '-v', '/project:/project', + '-v', '/out-dir:/out', + '-v', '/cache-dir:/cache', + '-w', '/project/folder', + 'parcel-bundler', + 'parcel', 'build', '/project/folder/entry.ts', + '--out-dir', '/out', '--out-file', 'index.js', '--global', 'handler', '--target', 'node', @@ -46,36 +54,42 @@ test('calls parcel with the correct args', () => { '--log-level', '2', '--no-minify', '--no-source-maps', - '--cache-dir', 'cache-dir', - ])); + '--cache-dir', '/cache', + ]); }); test('throws in case of error', () => { const builder = new Builder({ - entry: 'error', + entry: '/project/folder/error', global: 'handler', outDir: 'out-dir', + nodeDockerTag: 'lts-alpine', + nodeVersion: '12', + projectRoot: '/project', }); expect(() => builder.build()).toThrow('parcel-error'); }); test('throws if status is not 0', () => { const builder = new Builder({ - entry: 'status', + entry: '/project/folder/status', global: 'handler', outDir: 'out-dir', + nodeDockerTag: 'lts-alpine', + nodeVersion: '12', + projectRoot: '/project', }); expect(() => builder.build()).toThrow('status-error'); }); -test('throws when parcel-bundler is not 1.x', () => { - fs.writeFileSync(parcelPkgPath, JSON.stringify({ - ...JSON.parse(parcelPkg.toString()), - version: '2.3.4', - })); - expect(() => new Builder({ - entry: 'entry', +test('throws if docker is not installed', () => { + const builder = new Builder({ + entry: '/project/folder/no-docker', global: 'handler', - outDir: 'out-dur', - })).toThrow(/This module has a peer dependency on parcel-bundler v1.x. Got v2.3.4./); + outDir: 'out-dir', + nodeDockerTag: 'lts-alpine', + nodeVersion: '12', + projectRoot: '/project', + }); + expect(() => builder.build()).toThrow('Error: spawnSync docker ENOENT'); }); diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 6c6f65e31fb34..16bd0c10c7cc4 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -71,7 +71,7 @@ "@types/lodash": "^4.14.150", "@types/nodeunit": "^0.0.30", "@types/sinon": "^9.0.0", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts b/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts index 56f25bcef2dce..f7cb345f8cc73 100644 --- a/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts +++ b/packages/@aws-cdk/aws-route53/lib/hosted-zone.ts @@ -1,6 +1,6 @@ import * as ec2 from '@aws-cdk/aws-ec2'; +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Construct, ContextProvider, Duration, Lazy, Resource, Stack } from '@aws-cdk/core'; -import * as cxapi from '@aws-cdk/cx-api'; import { HostedZoneProviderProps } from './hosted-zone-provider'; import { HostedZoneAttributes, IHostedZone } from './hosted-zone-ref'; import { CaaAmazonRecord, ZoneDelegationRecord } from './record-set'; @@ -107,7 +107,7 @@ export class HostedZone extends Resource implements IHostedZone { } const response: HostedZoneContextResponse = ContextProvider.getValue(scope, { - provider: cxapi.HOSTED_ZONE_PROVIDER, + provider: cxschema.ContextProvider.HOSTED_ZONE_PROVIDER, dummyValue: DEFAULT_HOSTED_ZONE, props: query, }).value; diff --git a/packages/@aws-cdk/aws-route53/package.json b/packages/@aws-cdk/aws-route53/package.json index 393c1d6fe47e2..ec1b1de7f9d38 100644 --- a/packages/@aws-cdk/aws-route53/package.json +++ b/packages/@aws-cdk/aws-route53/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", @@ -75,7 +75,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/core": "0.0.0", - "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/cloud-assembly-schema": "0.0.0", "constructs": "^3.0.2" }, "homepage": "https://github.com/aws/aws-cdk", @@ -83,7 +83,7 @@ "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/core": "0.0.0", - "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/cloud-assembly-schema": "0.0.0", "constructs": "^3.0.2" }, "engines": { diff --git a/packages/@aws-cdk/aws-s3-deployment/test/test.bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/test/test.bucket-deployment.ts index 547b157314305..11cf55ad65118 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/test.bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/test.bucket-deployment.ts @@ -228,7 +228,7 @@ export = { ], }, 'SourceBucketNames': [{ - 'Ref': 'AssetParameterse9b696b2a8a1f93ea8b8a9ce1e4dd4727f9243eba984e50411ca95c6b03d26b6S3Bucket1A1EC3E9', + 'Ref': 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3BucketB41AE64D', }], 'SourceObjectKeys': [{ 'Fn::Join': [ @@ -241,7 +241,7 @@ export = { 'Fn::Split': [ '||', { - 'Ref': 'AssetParameterse9b696b2a8a1f93ea8b8a9ce1e4dd4727f9243eba984e50411ca95c6b03d26b6S3VersionKeyE46A4824', + 'Ref': 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3VersionKeyF3CBA38F', }, ], }, @@ -254,7 +254,7 @@ export = { 'Fn::Split': [ '||', { - 'Ref': 'AssetParameterse9b696b2a8a1f93ea8b8a9ce1e4dd4727f9243eba984e50411ca95c6b03d26b6S3VersionKeyE46A4824', + 'Ref': 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3VersionKeyF3CBA38F', }, ], }, diff --git a/packages/@aws-cdk/aws-s3/README.md b/packages/@aws-cdk/aws-s3/README.md index 83c15d3bff6d3..6e8f002e287e0 100644 --- a/packages/@aws-cdk/aws-s3/README.md +++ b/packages/@aws-cdk/aws-s3/README.md @@ -29,8 +29,10 @@ new Bucket(this, 'MyFirstBucket'); * `arnForObjects(pattern)` - the ARN of an object or objects within the bucket (i.e. `arn:aws:s3:::bucket_name/exampleobject.png` or `arn:aws:s3:::bucket_name/Development/*`) - * `urlForObject(key)` - the URL of an object within the bucket (i.e. + * `urlForObject(key)` - the HTTP URL of an object within the bucket (i.e. `https://s3.cn-north-1.amazonaws.com.cn/china-bucket/mykey`) + * `s3UrlForObject(key)` - the S3 URL of an object within the bucket (i.e. + `s3://bucket/mykey`) ### Encryption diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 62f38dab11d8e..75b2d9d885336 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -86,6 +86,16 @@ export interface IBucket extends IResource { */ urlForObject(key?: string): string; + /** + * The S3 URL of an S3 object. For example: + * @example s3://onlybucket + * @example s3://bucket/key + * @param key The S3 key of the object. If not specified, the S3 URL of the + * bucket is returned. + * @returns an ObjectS3Url token + */ + s3UrlForObject(key?: string): string; + /** * Returns an ARN that represents all objects within the bucket that match * the key pattern specified. To represent all keys, specify ``"*"``. @@ -429,17 +439,20 @@ abstract class BucketBase extends Resource implements IBucket { */ public urlForObject(key?: string): string { const stack = Stack.of(this); - const components = [ `https://s3.${stack.region}.${stack.urlSuffix}/${this.bucketName}` ]; - if (key) { - // trim prepending '/' - if (typeof key === 'string' && key.startsWith('/')) { - key = key.substr(1); - } - components.push('/'); - components.push(key); - } + const prefix = `https://s3.${stack.region}.${stack.urlSuffix}/`; + return this.buildUrl(prefix, key); + } - return components.join(''); + /** + * The S3 URL of an S3 object. For example: + * @example s3://onlybucket + * @example s3://bucket/key + * @param key The S3 key of the object. If not specified, the S3 URL of the + * bucket is returned. + * @returns an ObjectS3Url token + */ + public s3UrlForObject(key?: string): string { + return this.buildUrl('s3://', key); } /** @@ -569,6 +582,24 @@ abstract class BucketBase extends Resource implements IBucket { }); } + private buildUrl(prefix: string, key?: string): string { + const components = [ + prefix, + this.bucketName, + ]; + + if (key) { + // trim prepending '/' + if (typeof key === 'string' && key.startsWith('/')) { + key = key.substr(1); + } + components.push('/'); + components.push(key); + } + + return components.join(''); + } + private grant( grantee: iam.IGrantable, bucketActions: string[], @@ -596,7 +627,7 @@ abstract class BucketBase extends Resource implements IBucket { }); } - if (this.encryptionKey) { + if (this.encryptionKey && keyActions && keyActions.length !== 0) { this.encryptionKey.grant(grantee, ...keyActions); } diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.expected.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.expected.json new file mode 100644 index 0000000000000..08c82035e2188 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.expected.json @@ -0,0 +1,115 @@ +{ + "Resources": { + "MyKey6AB29FA6": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": [ + "kms:Create*", + "kms:Describe*", + "kms:Enable*", + "kms:List*", + "kms:Put*", + "kms:Update*", + "kms:Revoke*", + "kms:Disable*", + "kms:Get*", + "kms:Delete*", + "kms:ScheduleKeyDeletion", + "kms:CancelKeyDeletion", + "kms:GenerateDataKey", + "kms:TagResource", + "kms:UntagResource" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "Deleter1FEDC09A": { + "Type": "AWS::IAM::User" + }, + "DeleterDefaultPolicyCD33B8A0": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:DeleteObject*", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "MyBucketF68F3FF0", + "Arn" + ] + }, + "/*" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "DeleterDefaultPolicyCD33B8A0", + "Users": [ + { + "Ref": "Deleter1FEDC09A" + } + ] + } + }, + "MyBucketF68F3FF0": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "KMSMasterKeyID": { + "Fn::GetAtt": [ + "MyKey6AB29FA6", + "Arn" + ] + }, + "SSEAlgorithm": "aws:kms" + } + } + ] + }, + "BucketName": "my-bucket-physical-name-grant-delete" + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts new file mode 100644 index 0000000000000..25dc6bf1820f7 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts @@ -0,0 +1,22 @@ +#!/usr/bin/env node +import * as iam from '@aws-cdk/aws-iam'; +import * as kms from '@aws-cdk/aws-kms'; +import * as cdk from '@aws-cdk/core'; +import * as s3 from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-s3'); + +const key = new kms.Key(stack, 'MyKey'); +const deleter = new iam.User(stack, 'Deleter'); +const bucket = new s3.Bucket(stack, 'MyBucket', { + bucketName: 'my-bucket-physical-name-grant-delete', + encryptionKey: key, + encryption: s3.BucketEncryption.KMS, +}); + +// when +bucket.grantDelete(deleter); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.expected.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.expected.json index b2e67b56a80b9..74f803ae04cb0 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.expected.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.expected.json @@ -36,6 +36,20 @@ ] ] } + }, + "S3ObjectURL": { + "Value": { + "Fn::Join": [ + "", + [ + "s3://", + { + "Ref": "MyBucketF68F3FF0" + }, + "/myfolder/myfile.txt" + ] + ] + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts index 34ef5319a05eb..34a282ac5dfb3 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts @@ -12,6 +12,7 @@ class TestStack extends cdk.Stack { new cdk.CfnOutput(this, 'BucketURL', { value: bucket.bucketWebsiteUrl }); new cdk.CfnOutput(this, 'ObjectURL', { value: bucket.urlForObject('myfolder/myfile.txt') }); + new cdk.CfnOutput(this, 'S3ObjectURL', { value: bucket.s3UrlForObject('myfolder/myfile.txt') }); /// !hide } } diff --git a/packages/@aws-cdk/aws-s3/test/test.bucket.ts b/packages/@aws-cdk/aws-s3/test/test.bucket.ts index 31c5634f0060f..92440f7d05586 100644 --- a/packages/@aws-cdk/aws-s3/test/test.bucket.ts +++ b/packages/@aws-cdk/aws-s3/test/test.bucket.ts @@ -1053,6 +1053,50 @@ export = { test.done(); }, + 'grantDelete, with a KMS Key'(test: Test) { + // given + const stack = new cdk.Stack(); + const key = new kms.Key(stack, 'MyKey'); + const deleter = new iam.User(stack, 'Deleter'); + const bucket = new s3.Bucket(stack, 'MyBucket', { + bucketName: 'my-bucket-physical-name', + encryptionKey: key, + encryption: s3.BucketEncryption.KMS, + }); + + // when + bucket.grantDelete(deleter); + + // then + expect(stack).to(haveResourceLike('AWS::IAM::Policy', { + 'PolicyDocument': { + 'Statement': [ + { + 'Action': 's3:DeleteObject*', + 'Effect': 'Allow', + 'Resource': { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + 'MyBucketF68F3FF0', + 'Arn', + ], + }, + '/*', + ], + ], + }, + }, + ], + 'Version': '2012-10-17', + }, + })); + + test.done(); + }, + 'cross-stack permissions': { 'in the same account and region'(test: Test) { const app = new cdk.App(); @@ -1388,6 +1432,70 @@ export = { test.done(); }, + 's3UrlForObject returns a token with the S3 URL of the token'(test: Test) { + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'MyBucket'); + + new cdk.CfnOutput(stack, 'BucketS3URL', { value: bucket.s3UrlForObject() }); + new cdk.CfnOutput(stack, 'MyFileS3URL', { value: bucket.s3UrlForObject('my/file.txt') }); + new cdk.CfnOutput(stack, 'YourFileS3URL', { value: bucket.s3UrlForObject('/your/file.txt') }); // "/" is optional + + expect(stack).toMatch({ + 'Resources': { + 'MyBucketF68F3FF0': { + 'Type': 'AWS::S3::Bucket', + 'DeletionPolicy': 'Retain', + 'UpdateReplacePolicy': 'Retain', + }, + }, + 'Outputs': { + 'BucketS3URL': { + 'Value': { + 'Fn::Join': [ + '', + [ + 's3://', + { + 'Ref': 'MyBucketF68F3FF0', + }, + ], + ], + }, + }, + 'MyFileS3URL': { + 'Value': { + 'Fn::Join': [ + '', + [ + 's3://', + { + 'Ref': 'MyBucketF68F3FF0', + }, + '/my/file.txt', + ], + ], + }, + }, + 'YourFileS3URL': { + 'Value': { + 'Fn::Join': [ + '', + [ + 's3://', + { + 'Ref': 'MyBucketF68F3FF0', + }, + '/your/file.txt', + ], + ], + }, + }, + }, + }); + + test.done(); + }, + 'grantPublicAccess': { 'by default, grants s3:GetObject to all objects'(test: Test) { // GIVEN diff --git a/packages/@aws-cdk/aws-sam/package.json b/packages/@aws-cdk/aws-sam/package.json index a4970eae21ea1..3190eb0afba88 100644 --- a/packages/@aws-cdk/aws-sam/package.json +++ b/packages/@aws-cdk/aws-sam/package.json @@ -69,7 +69,7 @@ "cfn2ts": "0.0.0", "jest": "^25.5.4", "pkglint": "0.0.0", - "ts-jest": "^25.4.0" + "ts-jest": "^25.5.0" }, "dependencies": { "@aws-cdk/core": "0.0.0", diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index 6ae768c9311b8..f48235bfb0857 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -240,6 +240,12 @@ export class Secret extends SecretBase { }); this.encryptionKey = props.encryptionKey; + + // @see https://docs.aws.amazon.com/kms/latest/developerguide/services-secrets-manager.html#asm-authz + const principle = + new kms.ViaServicePrincipal(`secretsmanager.${Stack.of(this).region}.amazonaws.com`, new iam.AccountPrincipal(Stack.of(this).account)); + this.encryptionKey?.grantEncryptDecrypt(principle); + this.encryptionKey?.grant(principle, 'kms:CreateGrant', 'kms:DescribeKey'); } /** diff --git a/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts b/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts index 947d86df8281d..a8fe2c26e9a11 100644 --- a/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts @@ -129,6 +129,90 @@ export = { }, }, Resource: '*', + }, { + Effect: 'Allow', + Resource: '*', + Action: [ + 'kms:Decrypt', + 'kms:Encrypt', + 'kms:ReEncrypt*', + 'kms:GenerateDataKey*', + ], + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::', + { + Ref: 'AWS::AccountId', + }, + ':root', + ], + ], + }, + }, + Condition: { + StringEquals: { + 'kms:ViaService': { + 'Fn::Join': [ + '', + [ + 'secretsmanager.', + { + Ref: 'AWS::Region', + }, + '.amazonaws.com', + ], + ], + }, + }, + }, + }, { + Effect: 'Allow', + Resource: '*', + Action: [ + 'kms:CreateGrant', + 'kms:DescribeKey', + ], + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::', + { + Ref: 'AWS::AccountId', + }, + ':root', + ], + ], + }, + }, + Condition: { + StringEquals: { + 'kms:ViaService': { + 'Fn::Join': [ + '', + [ + 'secretsmanager.', + { + Ref: 'AWS::Region', + }, + '.amazonaws.com', + ], + ], + }, + }, + }, }, { Action: 'kms:Decrypt', Condition: { @@ -231,6 +315,90 @@ export = { }, }, Resource: '*', + }, { + Effect: 'Allow', + Resource: '*', + Action: [ + 'kms:Decrypt', + 'kms:Encrypt', + 'kms:ReEncrypt*', + 'kms:GenerateDataKey*', + ], + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::', + { + Ref: 'AWS::AccountId', + }, + ':root', + ], + ], + }, + }, + Condition: { + StringEquals: { + 'kms:ViaService': { + 'Fn::Join': [ + '', + [ + 'secretsmanager.', + { + Ref: 'AWS::Region', + }, + '.amazonaws.com', + ], + ], + }, + }, + }, + }, { + Effect: 'Allow', + Resource: '*', + Action: [ + 'kms:CreateGrant', + 'kms:DescribeKey', + ], + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::', + { + Ref: 'AWS::AccountId', + }, + ':root', + ], + ], + }, + }, + Condition: { + StringEquals: { + 'kms:ViaService': { + 'Fn::Join': [ + '', + [ + 'secretsmanager.', + { + Ref: 'AWS::Region', + }, + '.amazonaws.com', + ], + ], + }, + }, + }, }, { Action: 'kms:Decrypt', Condition: { diff --git a/packages/@aws-cdk/aws-sqs/lib/queue.ts b/packages/@aws-cdk/aws-sqs/lib/queue.ts index 9d8eab064f198..d335da2c9120f 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue.ts @@ -97,9 +97,8 @@ export interface QueueProps { * turn will be encrypted using this key, and reused for a maximum of * `dataKeyReuseSecs` seconds. * - * The 'encryption' property must be either not specified or set to "Kms". - * An error will be emitted if encryption is set to "Unencrypted" or - * "KmsManaged". + * If the 'encryptionMasterKey' property is set, 'encryption' type will be + * implicitly set to "KMS". * * @default If encryption is set to KMS and not specified, a key will be created. */ diff --git a/packages/@aws-cdk/aws-sqs/package.json b/packages/@aws-cdk/aws-sqs/package.json index c6ca2484781aa..7efc1e85684bd 100644 --- a/packages/@aws-cdk/aws-sqs/package.json +++ b/packages/@aws-cdk/aws-sqs/package.json @@ -65,7 +65,7 @@ "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-ssm/lib/parameter.ts b/packages/@aws-cdk/aws-ssm/lib/parameter.ts index 617375e314553..bc73278bfc267 100644 --- a/packages/@aws-cdk/aws-ssm/lib/parameter.ts +++ b/packages/@aws-cdk/aws-ssm/lib/parameter.ts @@ -1,10 +1,10 @@ import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { CfnDynamicReference, CfnDynamicReferenceService, CfnParameter, Construct, ContextProvider, Fn, IResource, Resource, Stack, Token, } from '@aws-cdk/core'; -import * as cxapi from '@aws-cdk/cx-api'; import * as ssm from './ssm.generated'; import { arnForParameterName, AUTOGEN_MARKER } from './util'; @@ -362,7 +362,7 @@ export class StringParameter extends ParameterBase implements IStringParameter { */ public static valueFromLookup(scope: Construct, parameterName: string): string { const value = ContextProvider.getValue(scope, { - provider: cxapi.SSM_PARAMETER_PROVIDER, + provider: cxschema.ContextProvider.SSM_PARAMETER_PROVIDER, props: { parameterName }, dummyValue: `dummy-value-for-${parameterName}`, }).value; diff --git a/packages/@aws-cdk/aws-ssm/package.json b/packages/@aws-cdk/aws-ssm/package.json index 4930d3e10e7e8..357aad127a955 100644 --- a/packages/@aws-cdk/aws-ssm/package.json +++ b/packages/@aws-cdk/aws-ssm/package.json @@ -74,7 +74,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/core": "0.0.0", - "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/cloud-assembly-schema": "0.0.0", "constructs": "^3.0.2" }, "homepage": "https://github.com/aws/aws-cdk", @@ -82,7 +82,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/core": "0.0.0", - "@aws-cdk/cx-api": "0.0.0", + "@aws-cdk/cloud-assembly-schema": "0.0.0", "constructs": "^3.0.2" }, "engines": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md index 5a26cb5f59a86..917e862f0bda7 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md @@ -22,6 +22,10 @@ This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aw ## Table Of Contents - [Task](#task) +- [Paths](#paths) + - [InputPath](#inputpath) + - [OutputPath](#outputpath) + - [ResultPath](#resultpath) - [Parameters](#task-parameters-from-the-state-json) - [Evaluate Expression](#evaluate-expression) - [Batch](#batch) @@ -61,6 +65,79 @@ actions, and coordinate executions directly from the Amazon States Language in Step Functions. You can directly call and pass parameters to the APIs of those services. +## Paths + +In the Amazon States Language, a [path](https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-paths.html) is a string beginning with `$` that you +can use to identify components within JSON text. + +Learn more about input and output processing in Step Functions [here](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html) + +### InputPath + +Both `InputPath` and `Parameters` fields provide a way to manipulate JSON as it +moves through your workflow. AWS Step Functions applies the `InputPath` field first, +and then the `Parameters` field. You can first filter your raw input to a selection +you want using InputPath, and then apply Parameters to manipulate that input +further, or add new values. If you don't specify an `InputPath`, a default value +of `$` will be used. + +The following example provides the field named `input` as the input to the `Task` +state that runs a Lambda function. + +```ts +const submitJob = new sfn.Task(stack, 'Invoke Handler', { + task: new tasks.RunLambdaTask(submitJobLambda), + inputPath: '$.input' +}); +``` + +### OutputPath + +Tasks also allow you to select a portion of the state output to pass to the next +state. This enables you to filter out unwanted information, and pass only the +portion of the JSON that you care about. If you don't specify an `OutputPath`, +a default value of `$` will be used. This passes the entire JSON node to the next +state. + +The [response](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseSyntax) from a Lambda function includes the response from the function +as well as other metadata. + +The following example assigns the output from the Task to a field named `result` + +```ts +const submitJob = new sfn.Task(stack, 'Invoke Handler', { + task: new tasks.RunLambdaTask(submitJobLambda), + outputPath: '$.Payload.result' +}); +``` + +### ResultPath + +The output of a state can be a copy of its input, the result it produces (for +example, output from a Task state’s Lambda function), or a combination of its +input and result. Use [`ResultPath`](https://docs.aws.amazon.com/step-functions/latest/dg/input-output-resultpath.html) to control which combination of these is +passed to the state output. If you don't specify an `ResultPath`, a default +value of `$` will be used. + +The following example adds the item from calling DynamoDB's `getItem` API to the state +input and passes it to the next state. + +```ts +new sfn.Task(this, 'PutItem', { + task: tasks.CallDynamoDB.getItem({ + item: { + MessageId: new tasks.DynamoAttributeValue().withS('12345'), + }, + tableName: 'my-table', + }), + resultPath: `$.Item` +}); +``` + +⚠️ The `OutputPath` is computed after applying `ResultPath`. All service integrations +return metadata as part of their response. When using `ResultPath`, it's not possible to +merge a subset of the task output to the input. + ## Task parameters from the state JSON Most tasks take parameters. Parameter values can either be static, supplied directly @@ -69,8 +146,19 @@ in the state machine's execution (either as its input or an output of a prior st Parameter values available at runtime can be specified via the `Data` class, using methods such as `Data.stringAt()`. -If so, the value is taken from the indicated location in the state JSON, -similar to (for example) `inputPath`. +The following example provides the field named `input` as the input to the Lambda function +and invokes it asynchronously. + +```ts +const submitJob = new sfn.Task(stack, 'Invoke Handler', { + task: new tasks.RunLambdaTask(submitJobLambda, { + payload: sfn.Data.StringAt('$.input'), + invocationType: tasks.InvocationType.EVENT, + }), +}); +``` + +Each service integration has its own set of parameters that can be supplied. ## Evaluate Expression diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/package.json b/packages/@aws-cdk/aws-stepfunctions-tasks/package.json index 5713556799b00..7e029a1e91df8 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/package.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/package.json @@ -66,11 +66,9 @@ "keywords": [ "aws", "cdk", - "cloudlib", - "aws-cloudlib", - "aws-clib", - "cloudwatch", - "events" + "constructs", + "stepfunctions", + "stepfunctions-tasks" ], "author": { "name": "Amazon Web Services", diff --git a/packages/@aws-cdk/aws-stepfunctions/README.md b/packages/@aws-cdk/aws-stepfunctions/README.md index 1d280b49fd2b9..028a7761d9e9c 100644 --- a/packages/@aws-cdk/aws-stepfunctions/README.md +++ b/packages/@aws-cdk/aws-stepfunctions/README.md @@ -26,16 +26,15 @@ example](https://docs.aws.amazon.com/step-functions/latest/dg/job-status-poller- ```ts import * as sfn from '@aws-cdk/aws-stepfunctions'; import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; +import * as lambda from '@aws-cdk/aws-lambda'; const submitLambda = new lambda.Function(this, 'SubmitLambda', { ... }); const getStatusLambda = new lambda.Function(this, 'CheckLambda', { ... }); const submitJob = new sfn.Task(this, 'Submit Job', { - task: new tasks.RunLambdaTask(submitLambda, { - integrationPattern: sfn.ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN, - }), - // Put Lambda's result here in the execution's state object - resultPath: '$.guid', + task: new tasks.RunLambdaTask(submitLambda), + // Lambda's result is in the attribute `Payload` + outputPath: '$.Payload', }); const waitX = new sfn.Wait(this, 'Wait X Seconds', { @@ -43,13 +42,11 @@ const waitX = new sfn.Wait(this, 'Wait X Seconds', { }); const getStatus = new sfn.Task(this, 'Get Job Status', { - task: new tasks.RunLambdaTask(getStatusLambda, { - integrationPattern: sfn.ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN, - }), + task: new tasks.RunLambdaTask(getStatusLambda), // Pass just the field named "guid" into the Lambda, put the - // Lambda's result in a field called "status" + // Lambda's result in a field called "status" in the response inputPath: '$.guid', - resultPath: '$.status', + outputPath: '$.Payload', }); const jobFailed = new sfn.Fail(this, 'Job Failed', { @@ -58,12 +55,10 @@ const jobFailed = new sfn.Fail(this, 'Job Failed', { }); const finalStatus = new sfn.Task(this, 'Get Final Job Status', { - task: new tasks.RunLambdaTask(getStatusLambda, { - integrationPattern: sfn.ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN, - }), - // Use "guid" field as input, output of the Lambda becomes the - // entire state machine output. + task: new tasks.RunLambdaTask(getStatusLambda), + // Use "guid" field as input inputPath: '$.guid', + outputPath: '$.Payload', }); const definition = submitJob @@ -81,6 +76,9 @@ new sfn.StateMachine(this, 'StateMachine', { }); ``` +You can find more sample snippets and learn more about the service integrations +in the `@aws-cdk/aws-stepfunctions-tasks` package. + ## State Machine A `stepfunctions.StateMachine` is a resource that takes a state machine @@ -115,6 +113,7 @@ are supported: * [`Succeed`](#succeed) * [`Fail`](#fail) * [`Map`](#map) +* [`Custom State`](#custom-state) An arbitrary JSON object (specified at execution start) is passed from state to state and transformed during the execution of the workflow. For more @@ -258,6 +257,76 @@ const map = new stepfunctions.Map(this, 'Map State', { map.iterator(new stepfunctions.Pass(this, 'Pass State')); ``` +### Custom State + +It's possible that the high-level constructs for the states or `stepfunctions-tasks` do not have +the states or service integrations you are looking for. The primary reasons for this lack of +functionality are: + +* A [service integration](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-service-integrations.html) is available through Amazon States Langauge, but not available as construct + classes in the CDK. +* The state or state properties are available through Step Functions, but are not configurable + through constructs + +If a feature is not available, a `CustomState` can be used to supply any Amazon States Language +JSON-based object as the state definition. + +[Code Snippets](https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1) are available and can be plugged in as the state definition. + +Custom states can be chained together with any of the other states to create your state machine +definition. You will also need to provide any permissions that are required to the `role` that +the State Machine uses. + +The following example uses the `DynamoDB` service integration to insert data into a DynamoDB table. + +```ts +import * as ddb from '@aws-cdk/aws-dynamodb'; +import * as cdk from '@aws-cdk/core'; +import * as sfn from '@aws-cdk/aws-stepfunctions'; + +// create a table +const table = new ddb.Table(this, 'montable', { + partitionKey: { + name: 'id', + type: ddb.AttributeType.STRING, + }, +}); + +const finalStatus = new sfn.Pass(stack, 'final step'); + +// States language JSON to put an item into DynamoDB +// snippet generated from https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1 +const stateJson = { + Type: 'Task', + Resource: 'arn:aws:states:::dynamodb:putItem', + Parameters: { + TableName: table.tableName, + Item: { + id: { + S: 'MyEntry', + }, + }, + }, + ResultPath: null, +}; + +// custom state which represents a task to insert data into DynamoDB +const custom = new sfn.CustomState(this, 'my custom task', { + stateJson, +}); + +const chain = sfn.Chain.start(custom) + .next(finalStatus); + +const sm = new sfn.StateMachine(this, 'StateMachine', { + definition: chain, + timeout: cdk.Duration.seconds(30), +}); + +// don't forget permissions. You need to assign them +table.grantWriteData(sm.role); +``` + ## Task Chaining To make defining work flows as convenient (and readable in a top-to-bottom way) diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/index.ts b/packages/@aws-cdk/aws-stepfunctions/lib/index.ts index 59f6e32b4a523..c1c6249753e83 100644 --- a/packages/@aws-cdk/aws-stepfunctions/lib/index.ts +++ b/packages/@aws-cdk/aws-stepfunctions/lib/index.ts @@ -19,6 +19,7 @@ export * from './states/succeed'; export * from './states/task'; export * from './states/wait'; export * from './states/map'; +export * from './states/custom-state'; // AWS::StepFunctions CloudFormation Resources: export * from './stepfunctions.generated'; diff --git a/packages/@aws-cdk/aws-stepfunctions/lib/states/custom-state.ts b/packages/@aws-cdk/aws-stepfunctions/lib/states/custom-state.ts new file mode 100644 index 0000000000000..005945a4ad20b --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/lib/states/custom-state.ts @@ -0,0 +1,55 @@ +import * as cdk from '@aws-cdk/core'; +import { Chain } from '..'; +import { IChainable, INextable } from '../types'; +import { State } from './state'; + +/** + * Properties for defining a custom state definition + */ +export interface CustomStateProps { + /** + * Amazon States Language (JSON-based) definition of the state + * + * @see https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html + */ + readonly stateJson: { [key: string]: any }; +} + +/** + * State defined by supplying Amazon States Language (ASL) in the state machine. + * + * @experimental + */ +export class CustomState extends State implements IChainable, INextable { + public readonly endStates: INextable[]; + + /** + * Amazon States Language (JSON-based) definition of the state + */ + private readonly stateJson: { [key: string]: any}; + + constructor(scope: cdk.Construct, id: string, props: CustomStateProps) { + super(scope, id, {}); + + this.endStates = [this]; + this.stateJson = props.stateJson; + } + + /** + * Continue normal execution with the given state + */ + public next(next: IChainable): Chain { + super.makeNext(next.startState); + return Chain.sequence(this, next); + } + + /** + * Returns the Amazon States Language object for this state + */ + public toStateJson(): object { + return { + ...this.renderNextEnd(), + ...this.stateJson, + }; + } +} diff --git a/packages/@aws-cdk/aws-stepfunctions/test/custom-state.test.ts b/packages/@aws-cdk/aws-stepfunctions/test/custom-state.test.ts new file mode 100644 index 0000000000000..723d917986899 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/custom-state.test.ts @@ -0,0 +1,34 @@ +import '@aws-cdk/assert/jest'; +import * as cdk from '@aws-cdk/core'; +import * as stepfunctions from '../lib'; + +describe('Custom State', () => { + test('maintains the state Json provided during construction', () => { + // GIVEN + const stack = new cdk.Stack(); + const stateJson = { + Type: 'Task', + Resource: 'arn:aws:states:::dynamodb:putItem', + Parameters: { + TableName: 'MyTable', + Item: { + id: { + S: 'MyEntry', + }, + }, + }, + ResultPath: null, + }; + + // WHEN + const customState = new stepfunctions.CustomState(stack, 'Custom', { + stateJson, + }); + + // THEN + expect(customState.toStateJson()).toStrictEqual({ + ...stateJson, + End: true, + }); + }); +}); diff --git a/packages/@aws-cdk/aws-stepfunctions/test/integ.custom-state.expected.json b/packages/@aws-cdk/aws-stepfunctions/test/integ.custom-state.expected.json new file mode 100644 index 0000000000000..311e28c953615 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/integ.custom-state.expected.json @@ -0,0 +1,54 @@ +{ + "Resources": { + "StateMachineRoleB840431D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "states.", + { + "Ref": "AWS::Region" + }, + ".amazonaws.com" + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "StateMachine2E01A3A5": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "DefinitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null},\"final step\":{\"Type\":\"Pass\",\"End\":true}},\"TimeoutSeconds\":30}", + "RoleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] + } + }, + "DependsOn": [ + "StateMachineRoleB840431D" + ] + } + }, + "Outputs": { + "StateMachineARN": { + "Value": { + "Ref": "StateMachine2E01A3A5" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions/test/integ.custom-state.ts b/packages/@aws-cdk/aws-stepfunctions/test/integ.custom-state.ts new file mode 100644 index 0000000000000..318f2cd98dd11 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/integ.custom-state.ts @@ -0,0 +1,43 @@ +import * as cdk from '@aws-cdk/core'; +import * as sfn from '../lib'; + +/* + * Stack verification steps: + * + * -- aws stepfunctions describe-state-machine --state-machine-arn has a status of `ACTIVE` + */ +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-stepfunctions-custom-state-integ'); + +const finalStatus = new sfn.Pass(stack, 'final step'); + +const stateJson = { + Type: 'Task', + Resource: 'arn:aws:states:::dynamodb:putItem', + Parameters: { + TableName: 'my-cool-table', + Item: { + id: { + S: 'my-entry', + }, + }, + }, + ResultPath: null, +}; + +const custom = new sfn.CustomState(stack, 'my custom task', { + stateJson, +}); + +const chain = sfn.Chain.start(custom).next(finalStatus); + +const sm = new sfn.StateMachine(stack, 'StateMachine', { + definition: chain, + timeout: cdk.Duration.seconds(30), +}); + +new cdk.CfnOutput(stack, 'StateMachineARN', { + value: sm.stateMachineArn, +}); + +app.synth(); diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index b9045ed4f0bf5..cfdb595fd50eb 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,41 @@ +# CloudFormation Resource Specification v14.1.0 + +## New Resource Types + +* AWS::EventSchemas::RegistryPolicy + +## Attribute Changes + +* AWS::Synthetics::Canary Name (__deleted__) + +## Property Changes + +* AWS::MediaStore::Container MetricPolicy (__added__) +* AWS::MediaStore::Container Tags (__added__) +* AWS::Synthetics::Canary Name (__added__) + +## Property Type Changes + +* AWS::IoTEvents::DetectorModel.AssetPropertyTimestamp (__added__) +* AWS::IoTEvents::DetectorModel.AssetPropertyValue (__added__) +* AWS::IoTEvents::DetectorModel.AssetPropertyVariant (__added__) +* AWS::IoTEvents::DetectorModel.DynamoDB (__added__) +* AWS::IoTEvents::DetectorModel.DynamoDBv2 (__added__) +* AWS::IoTEvents::DetectorModel.IotSiteWise (__added__) +* AWS::IoTEvents::DetectorModel.Payload (__added__) +* AWS::MediaStore::Container.MetricPolicy (__added__) +* AWS::MediaStore::Container.MetricPolicyRule (__added__) +* AWS::IoTEvents::DetectorModel.Action DynamoDB (__added__) +* AWS::IoTEvents::DetectorModel.Action DynamoDBv2 (__added__) +* AWS::IoTEvents::DetectorModel.Action IotSiteWise (__added__) +* AWS::IoTEvents::DetectorModel.Firehose Payload (__added__) +* AWS::IoTEvents::DetectorModel.IotEvents Payload (__added__) +* AWS::IoTEvents::DetectorModel.IotTopicPublish Payload (__added__) +* AWS::IoTEvents::DetectorModel.Lambda Payload (__added__) +* AWS::IoTEvents::DetectorModel.Sns Payload (__added__) +* AWS::IoTEvents::DetectorModel.Sqs Payload (__added__) + + # CloudFormation Resource Specification v14.0.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 4b964e965400d..7b3b6e02bb3e9 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -14.0.0 +14.1.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index f32467877fa9a..d7e1771ee6a67 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -20428,6 +20428,18 @@ "Type": "ClearTimer", "UpdateType": "Mutable" }, + "DynamoDB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html#cfn-iotevents-detectormodel-action-dynamodb", + "Required": false, + "Type": "DynamoDB", + "UpdateType": "Mutable" + }, + "DynamoDBv2": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html#cfn-iotevents-detectormodel-action-dynamodbv2", + "Required": false, + "Type": "DynamoDBv2", + "UpdateType": "Mutable" + }, "Firehose": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html#cfn-iotevents-detectormodel-action-firehose", "Required": false, @@ -20440,6 +20452,12 @@ "Type": "IotEvents", "UpdateType": "Mutable" }, + "IotSiteWise": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html#cfn-iotevents-detectormodel-action-iotsitewise", + "Required": false, + "Type": "IotSiteWise", + "UpdateType": "Mutable" + }, "IotTopicPublish": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html#cfn-iotevents-detectormodel-action-iottopicpublish", "Required": false, @@ -20484,6 +20502,75 @@ } } }, + "AWS::IoTEvents::DetectorModel.AssetPropertyTimestamp": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertytimestamp.html", + "Properties": { + "OffsetInNanos": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertytimestamp.html#cfn-iotevents-detectormodel-assetpropertytimestamp-offsetinnanos", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "TimeInSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertytimestamp.html#cfn-iotevents-detectormodel-assetpropertytimestamp-timeinseconds", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTEvents::DetectorModel.AssetPropertyValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvalue.html", + "Properties": { + "Quality": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvalue.html#cfn-iotevents-detectormodel-assetpropertyvalue-quality", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Timestamp": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvalue.html#cfn-iotevents-detectormodel-assetpropertyvalue-timestamp", + "Required": false, + "Type": "AssetPropertyTimestamp", + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvalue.html#cfn-iotevents-detectormodel-assetpropertyvalue-value", + "Required": false, + "Type": "AssetPropertyVariant", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTEvents::DetectorModel.AssetPropertyVariant": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvariant.html", + "Properties": { + "BooleanValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvariant.html#cfn-iotevents-detectormodel-assetpropertyvariant-booleanvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DoubleValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvariant.html#cfn-iotevents-detectormodel-assetpropertyvariant-doublevalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "IntegerValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvariant.html#cfn-iotevents-detectormodel-assetpropertyvariant-integervalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "StringValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-assetpropertyvariant.html#cfn-iotevents-detectormodel-assetpropertyvariant-stringvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::IoTEvents::DetectorModel.ClearTimer": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-cleartimer.html", "Properties": { @@ -20513,6 +20600,88 @@ } } }, + "AWS::IoTEvents::DetectorModel.DynamoDB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html", + "Properties": { + "HashKeyField": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-hashkeyfield", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "HashKeyType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-hashkeytype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "HashKeyValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-hashkeyvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Operation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-operation", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" + }, + "PayloadField": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-payloadfield", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RangeKeyField": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-rangekeyfield", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RangeKeyType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-rangekeytype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "RangeKeyValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-rangekeyvalue", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "TableName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodb.html#cfn-iotevents-detectormodel-dynamodb-tablename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTEvents::DetectorModel.DynamoDBv2": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodbv2.html", + "Properties": { + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodbv2.html#cfn-iotevents-detectormodel-dynamodbv2-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" + }, + "TableName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-dynamodbv2.html#cfn-iotevents-detectormodel-dynamodbv2-tablename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::IoTEvents::DetectorModel.Event": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-event.html", "Properties": { @@ -20546,6 +20715,12 @@ "Required": false, "UpdateType": "Mutable" }, + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-firehose.html#cfn-iotevents-detectormodel-firehose-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" + }, "Separator": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-firehose.html#cfn-iotevents-detectormodel-firehose-separator", "PrimitiveType": "String", @@ -20562,6 +20737,47 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotevents.html#cfn-iotevents-detectormodel-iotevents-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" + } + } + }, + "AWS::IoTEvents::DetectorModel.IotSiteWise": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotsitewise.html", + "Properties": { + "AssetId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotsitewise.html#cfn-iotevents-detectormodel-iotsitewise-assetid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "EntryId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotsitewise.html#cfn-iotevents-detectormodel-iotsitewise-entryid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PropertyAlias": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotsitewise.html#cfn-iotevents-detectormodel-iotsitewise-propertyalias", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PropertyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotsitewise.html#cfn-iotevents-detectormodel-iotsitewise-propertyid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "PropertyValue": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iotsitewise.html#cfn-iotevents-detectormodel-iotsitewise-propertyvalue", + "Required": false, + "Type": "AssetPropertyValue", + "UpdateType": "Mutable" } } }, @@ -20573,6 +20789,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-iottopicpublish.html#cfn-iotevents-detectormodel-iottopicpublish-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" } } }, @@ -20584,6 +20806,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-lambda.html#cfn-iotevents-detectormodel-lambda-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" } } }, @@ -20630,6 +20858,23 @@ } } }, + "AWS::IoTEvents::DetectorModel.Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-payload.html", + "Properties": { + "ContentExpression": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-payload.html#cfn-iotevents-detectormodel-payload-contentexpression", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-payload.html#cfn-iotevents-detectormodel-payload-type", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::IoTEvents::DetectorModel.ResetTimer": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-resettimer.html", "Properties": { @@ -20684,6 +20929,12 @@ "AWS::IoTEvents::DetectorModel.Sns": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-sns.html", "Properties": { + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-sns.html#cfn-iotevents-detectormodel-sns-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" + }, "TargetArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-sns.html#cfn-iotevents-detectormodel-sns-targetarn", "PrimitiveType": "String", @@ -20695,6 +20946,12 @@ "AWS::IoTEvents::DetectorModel.Sqs": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-sqs.html", "Properties": { + "Payload": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-sqs.html#cfn-iotevents-detectormodel-sqs-payload", + "Required": false, + "Type": "Payload", + "UpdateType": "Mutable" + }, "QueueUrl": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-sqs.html#cfn-iotevents-detectormodel-sqs-queueurl", "PrimitiveType": "String", @@ -24284,6 +24541,41 @@ } } }, + "AWS::MediaStore::Container.MetricPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-metricpolicy.html", + "Properties": { + "ContainerLevelMetrics": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-metricpolicy.html#cfn-mediastore-container-metricpolicy-containerlevelmetrics", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "MetricPolicyRules": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-metricpolicy.html#cfn-mediastore-container-metricpolicy-metricpolicyrules", + "ItemType": "MetricPolicyRule", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::MediaStore::Container.MetricPolicyRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-metricpolicyrule.html", + "Properties": { + "ObjectGroup": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-metricpolicyrule.html#cfn-mediastore-container-metricpolicyrule-objectgroup", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ObjectGroupName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-metricpolicyrule.html#cfn-mediastore-container-metricpolicyrule-objectgroupname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::NetworkManager::Device.Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-device-location.html", "Properties": { @@ -31310,7 +31602,7 @@ } } }, - "ResourceSpecificationVersion": "14.0.0", + "ResourceSpecificationVersion": "14.1.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -43767,6 +44059,34 @@ } } }, + "AWS::EventSchemas::RegistryPolicy": { + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eventschemas-registrypolicy.html", + "Properties": { + "Policy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eventschemas-registrypolicy.html#cfn-eventschemas-registrypolicy-policy", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "RegistryName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eventschemas-registrypolicy.html#cfn-eventschemas-registrypolicy-registryname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "RevisionId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eventschemas-registrypolicy.html#cfn-eventschemas-registrypolicy-revisionid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::EventSchemas::Schema": { "Attributes": { "SchemaArn": { @@ -48134,11 +48454,24 @@ "Required": false, "UpdateType": "Mutable" }, + "MetricPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-mediastore-container.html#cfn-mediastore-container-metricpolicy", + "Required": false, + "Type": "MetricPolicy", + "UpdateType": "Mutable" + }, "Policy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-mediastore-container.html#cfn-mediastore-container-policy", "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-mediastore-container.html#cfn-mediastore-container-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" } } }, @@ -54360,9 +54693,6 @@ "Id": { "PrimitiveType": "String" }, - "Name": { - "PrimitiveType": "String" - }, "State": { "PrimitiveType": "String" } @@ -54393,6 +54723,12 @@ "Required": false, "UpdateType": "Mutable" }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, "RunConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-runconfig", "Required": false, diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/context-queries.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/context-queries.ts new file mode 100644 index 0000000000000..88932e117ffa3 --- /dev/null +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/context-queries.ts @@ -0,0 +1,177 @@ + +/** + * Identifier for the context provider + */ +export enum ContextProvider { + /** + * AMI provider + */ + AMI_PROVIDER = 'ami', + + /** + * AZ provider + */ + AVAILABILITY_ZONE_PROVIDER = 'availability-zones', + + /** + * Route53 Hosted Zone provider + */ + HOSTED_ZONE_PROVIDER = 'hosted-zone', + + /** + * SSM Parameter Provider + */ + SSM_PARAMETER_PROVIDER = 'ssm', + + /** + * VPC Provider + */ + VPC_PROVIDER = 'vpc-provider', +} + +/** + * Query to AMI context provider + */ +export interface AmiContextQuery { + /** + * Account to query + */ + readonly account: string; + + /** + * Region to query + */ + readonly region: string; + + /** + * Owners to DescribeImages call + * + * @default - All owners + */ + readonly owners?: string[]; + + /** + * Filters to DescribeImages call + */ + readonly filters: {[key: string]: string[]}; +} + +/** + * Query to availability zone context provider + */ +export interface AvailabilityZonesContextQuery { + /** + * Query account + */ + readonly account: string; + + /** + * Query region + */ + readonly region: string; +} + +/** + * Query to hosted zone context provider + */ +export interface HostedZoneContextQuery { + /** + * Query account + */ + readonly account: string; + + /** + * Query region + */ + readonly region: string; + + /** + * The domain name e.g. example.com to lookup + */ + readonly domainName: string; + + /** + * True if the zone you want to find is a private hosted zone + * + * @default false + */ + readonly privateZone?: boolean; + + /** + * The VPC ID to that the private zone must be associated with + * + * If you provide VPC ID and privateZone is false, this will return no results + * and raise an error. + * + * @default - Required if privateZone=true + */ + readonly vpcId?: string; +} + +/** + * Query to SSM Parameter Context Provider + */ +export interface SSMParameterContextQuery { + /** + * Query account + */ + readonly account: string; + + /** + * Query region + */ + readonly region: string; + + /** + * Parameter name to query + */ + readonly parameterName: string; +} + +/** + * Query input for looking up a VPC + */ +export interface VpcContextQuery { + /** + * Query account + */ + readonly account: string; + + /** + * Query region + */ + readonly region: string; + + /** + * Filters to apply to the VPC + * + * Filter parameters are the same as passed to DescribeVpcs. + * + * @see https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html + */ + readonly filter: {[key: string]: string}; + + /** + * Whether to populate the subnetGroups field of the {@link VpcContextResponse}, + * which contains potentially asymmetric subnet groups. + * + * @default false + */ + readonly returnAsymmetricSubnets?: boolean; + + /** + * Optional tag for subnet group name. + * If not provided, we'll look at the aws-cdk:subnet-name tag. + * If the subnet does not have the specified tag, + * we'll use its type as the name. + * + * @default 'aws-cdk:subnet-name' + */ + readonly subnetGroupNameTag?: string; +} + +export type ContextQueryProperties = AmiContextQuery +| AvailabilityZonesContextQuery +| HostedZoneContextQuery +| SSMParameterContextQuery +| VpcContextQuery; diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/index.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/index.ts index f12754d9eecd4..746eaa2ffb2ce 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/lib/index.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/index.ts @@ -1,2 +1,3 @@ export * from './manifest'; export * from './schema'; +export * from './context-queries'; diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/schema.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/schema.ts index 7b27ed49e8a6f..3369c16e93b4c 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/lib/schema.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/schema.ts @@ -1,3 +1,5 @@ +import { ContextProvider, ContextQueryProperties } from './context-queries'; + /** * Common properties for asset metadata. */ @@ -256,16 +258,12 @@ export interface MissingContext { /** * The provider from which we expect this context key to be obtained. */ - readonly provider: string; + readonly provider: ContextProvider; /** * A set of provider-specific options. */ - readonly props: { - account?: string; - region?: string; - [key: string]: any; - }; + readonly props: ContextQueryProperties; } /** diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json index f6221fddb2c76..885af9359b4d4 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json @@ -152,7 +152,7 @@ "type": "string" }, "sourceHash": { - "description": "The hash of the source directory used to build the asset.", + "description": "The hash of the asset source.", "type": "string" }, "path": { @@ -213,7 +213,7 @@ "type": "string" }, "sourceHash": { - "description": "The hash of the source directory used to build the asset.", + "description": "The hash of the asset source.", "type": "string" }, "path": { @@ -255,21 +255,28 @@ "type": "string" }, "provider": { - "description": "The provider from which we expect this context key to be obtained.", - "type": "string" + "$ref": "#/definitions/ContextProvider", + "description": "The provider from which we expect this context key to be obtained." }, "props": { "description": "A set of provider-specific options.", - "type": "object", - "additionalProperties": {}, - "properties": { - "account": { - "type": "string" + "anyOf": [ + { + "$ref": "#/definitions/AmiContextQuery" }, - "region": { - "type": "string" + { + "$ref": "#/definitions/AvailabilityZonesContextQuery" + }, + { + "$ref": "#/definitions/HostedZoneContextQuery" + }, + { + "$ref": "#/definitions/SSMParameterContextQuery" + }, + { + "$ref": "#/definitions/VpcContextQuery" } - } + ] } }, "required": [ @@ -278,6 +285,161 @@ "provider" ] }, + "ContextProvider": { + "description": "Identifier for the context provider", + "enum": [ + "ami", + "availability-zones", + "hosted-zone", + "ssm", + "vpc-provider" + ], + "type": "string" + }, + "AmiContextQuery": { + "description": "Query to AMI context provider", + "type": "object", + "properties": { + "account": { + "description": "Account to query", + "type": "string" + }, + "region": { + "description": "Region to query", + "type": "string" + }, + "owners": { + "description": "Owners to DescribeImages call (Default - All owners)", + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "description": "Filters to DescribeImages call", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": [ + "account", + "filters", + "region" + ] + }, + "AvailabilityZonesContextQuery": { + "description": "Query to hosted zone context provider", + "type": "object", + "properties": { + "account": { + "description": "Query account", + "type": "string" + }, + "region": { + "description": "Query region", + "type": "string" + } + }, + "required": [ + "account", + "region" + ] + }, + "HostedZoneContextQuery": { + "description": "Query to hosted zone context provider", + "type": "object", + "properties": { + "account": { + "description": "Query account", + "type": "string" + }, + "region": { + "description": "Query region", + "type": "string" + }, + "domainName": { + "description": "The domain name e.g. example.com to lookup", + "type": "string" + }, + "privateZone": { + "description": "True if the zone you want to find is a private hosted zone", + "default": false, + "type": "boolean" + }, + "vpcId": { + "description": "The VPC ID to that the private zone must be associated with\n\nIf you provide VPC ID and privateZone is false, this will return no results\nand raise an error. (Default - Required if privateZone=true)", + "type": "string" + } + }, + "required": [ + "account", + "domainName", + "region" + ] + }, + "SSMParameterContextQuery": { + "description": "Query to hosted zone context provider", + "type": "object", + "properties": { + "account": { + "description": "Query account", + "type": "string" + }, + "region": { + "description": "Query region", + "type": "string" + }, + "parameterName": { + "description": "Parameter name to query", + "type": "string" + } + }, + "required": [ + "account", + "parameterName", + "region" + ] + }, + "VpcContextQuery": { + "description": "Query input for looking up a VPC", + "type": "object", + "properties": { + "account": { + "description": "Query account", + "type": "string" + }, + "region": { + "description": "Query region", + "type": "string" + }, + "filter": { + "description": "Filters to apply to the VPC\n\nFilter parameters are the same as passed to DescribeVpcs.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "returnAsymmetricSubnets": { + "description": "Whether to populate the subnetGroups field of the {@link VpcContextResponse},\nwhich contains potentially asymmetric subnet groups.", + "default": false, + "type": "boolean" + }, + "subnetGroupNameTag": { + "description": "Optional tag for subnet group name.\nIf not provided, we'll look at the aws-cdk:subnet-name tag.\nIf the subnet does not have the specified tag,\nwe'll use its type as the name. (Default 'aws-cdk:subnet-name')", + "type": "string" + } + }, + "required": [ + "account", + "filter", + "region" + ] + }, "RuntimeInfo": { "description": "Information about the application's runtime components.", "type": "object", diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json index 0e5bee35953f1..b0616139cced7 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json @@ -1 +1 @@ -{"version":"1.33.0"} \ No newline at end of file +{"version":"2.0.0"} diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index 1650ecdd55c0f..6b9c9cf2a39fe 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -45,7 +45,7 @@ "fast-check": "^1.24.2", "jest": "^25.5.4", "pkglint": "0.0.0", - "ts-jest": "^25.4.0" + "ts-jest": "^25.5.0" }, "repository": { "url": "https://github.com/aws/aws-cdk.git", diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md index 7b7a9e89216ff..db0bc2dd54a5d 100644 --- a/packages/@aws-cdk/core/README.md +++ b/packages/@aws-cdk/core/README.md @@ -185,7 +185,7 @@ resources in the scope of `constructB`. If you want a single object to represent a set of constructs that are not necessarily in the same scope, you can use a `ConcreteDependable`. The following creates a single object that represents a dependency on two -construts, `constructB` and `constructC`: +constructs, `constructB` and `constructC`: ```ts // Declare the dependable object @@ -246,24 +246,45 @@ new CustomResource(this, 'MyMagicalResource', { ### Custom Resource Providers Custom resources are backed by a **custom resource provider** which can be -implemented in one of the following ways (ordered from low-level to high-level): - -* `@aws-cdk/aws-sns.Topic` -* `@aws-cdk/aws-lambda.Function` -* `@aws-cdk/custom-resources.Provider` - -**NOTE**: when defining resources for a custom resource provider, you will -likely want to define them as a *stack singleton* so that only a single instance -of the provider is created in your stack and which is used by all custom -resources of that type. - -The following is a pattern for defining stack singletons in the CDK: +implemented in one of the following ways. The following table compares the +various provider types (ordered from low-level to high-level): + +| Provider | Compute Type | Error Handling | Submit to CloudFormation | Max Timeout | Language | Footprint | +|----------------------------------------------------------------------|:------------:|:--------------:|:------------------------:|:---------------:|:--------:|:---------:| +| [sns.Topic](#amazon-sns-topic) | Self-managed | Manual | Manual | Unlimited | Any | Depends | +| [lambda.Function](#aws-lambda-function) | AWS Lambda | Manual | Manual | 15min | Any | Small | +| [core.CustomResourceProvider](#the-corecustomresourceprovider-class) | Lambda | Auto | Auto | 15min | Node.js | Small | +| [custom-resources.Provider](#the-custom-resource-provider-framework) | Lambda | Auto | Auto | Unlimited Async | Any | Large | + +Legend: + +- **Compute type**: which type of compute can is used to execute the handler. +- **Error Handling**: whether errors thrown by handler code are automatically + trapped and a FAILED response is submitted to CloudFormation. If this is + "Manual", developers must take care of trapping errors. Otherwise, events + could cause stacks to hang. +- **Submit to CloudFormation**: whether the framework takes care of submitting + SUCCESS/FAILED responses to CloudFormation through the event's response URL. +- **Max Timeout**: maximum allows/possible timeout. +- **Language**: which programming languages can be used to implement handlers. +- **Footprint**: how many resources are used by the provider framework itself. + +**A NOTE ABOUT SINGLETONS** + +When defining resources for a custom resource provider, you will likely want to +define them as a *stack singleton* so that only a single instance of the +provider is created in your stack and which is used by all custom resources of +that type. + +Here is a basic pattern for defining stack singletons in the CDK. The following +examples ensures that only a single SNS topic is defined: ```ts -const stack = Stack.of(this); -const uniqueid = 'GloballyUniqueIdForSingleton'; -return stack.node.tryFindChild(uniqueid) as MySingleton - ?? new MySingleton(stack, uniqueid); +function getOrCreate(scope: Construct): sns.Topic { + const stack = Stack.of(this); + const uniqueid = 'GloballyUniqueIdForSingleton'; + return stack.node.tryFindChild(uniqueid) as sns.Topic ?? new sns.Topic(stack, uniqueid); +} ``` #### Amazon SNS Topic @@ -305,6 +326,132 @@ new CustomResource(this, 'MyResource', { }); ``` +#### The `core.CustomResourceProvider` class + +The class [`@aws-cdk/core.CustomResourceProvider`] offers a basic low-level +framework designed to implement simple and slim custom resource providers. It +currently only supports Node.js-based user handlers, and it does not have +support for asynchronous waiting (handler cannot exceed the 15min lambda +timeout). + +[`@aws-cdk/core.CustomResourceProvider`]: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.CustomResourceProvider.html + +The provider has a built-in singleton method which uses the resource type as a +stack-unique identifier and returns the service token: + +```ts +const serviceToken = CustomResourceProvider.getOrCreate(this, 'Custom::MyCustomResourceType', { + codeDirectory: `${__dirname}/my-handler`, + runtime: CustomResourceProviderRuntime.NODEJS_12, // currently the only supported runtime +}); + +new CustomResource(this, 'MyResource', { + resourceType: 'Custom::MyCustomResourceType', + serviceToken: serviceToken +}); +``` + +The directory (`my-handler` in the above example) must include an `index.js` file. It cannot import +external dependencies or files outside this directory. It must export an async +function named `handler`. This function accepts the CloudFormation resource +event object and returns an object with the following structure: + +```js +exports.handler = async function(event) { + const id = event.PhysicalResourceId; // only for "Update" and "Delete" + const props = event.ResourceProperties; + const oldProps = event.OldResourceProperties; // only for "Update"s + + switch (event.RequestType) { + case "Create": + // ... + + case "Update": + // ... + + // if an error is thrown, a FAILED response will be submitted to CFN + throw new Error('Failed!'); + + case "Delete": + // ... + } + + return { + // (optional) the value resolved from `resource.ref` + // defaults to "event.PhysicalResourceId" or "event.RequestId" + PhysicalResourceId: "REF", + + // (optional) calling `resource.getAtt("Att1")` on the custom resource in the CDK app + // will return the value "BAR". + Data: { + Att1: "BAR", + Att2: "BAZ" + }, + + // (optional) user-visible message + Reason: "User-visible message", + + // (optional) hides values from the console + NoEcho: true + }; +} +``` + +Here is an complete example of a custom resource that summarizes two numbers: + +`sum-handler/index.js`: + +```js +exports.handler = async e => { + return { + Data: { + Result: e.ResourceProperties.lhs + e.ResourceProperties.rhs + } + }; +}; +``` + +`sum.ts`: + +```ts +export interface SumProps { + readonly lhs: number; + readonly rhs: number; +} + +export class Sum extends Construct { + public readonly result: number; + + constructor(scope: Construct, id: string, props: SumProps) { + super(scope, id); + + const resourceType = 'Custom::Sum'; + const provider = CustomResourceProvider.getOrCreate(this, resourceType, { + codeDirectory: `${__dirname}/sum-handler`, + runtime: CustomResourceProviderRuntime.NODEJS_12, + }); + + const resource = new CustomResource(this, 'Resource', { + resourceType: resourceType, + serviceToken: provider.serviceToken, + properties: { + lhs: props.lhs, + rhs: props.rhs + } + }); + + this.result = Token.asNumber(resource.getAtt('Result')); + } +} +``` + +Usage will look like this: + +```ts +const sum = new Sum(this, 'MySum', { lhs: 40, rhs: 2 }); +new CfnOutput(this, 'Result', { value: sum.result }); +``` + #### The Custom Resource Provider Framework The [`@aws-cdk/custom-resource`] module includes an advanced framework for @@ -318,7 +465,7 @@ asynchronous mode, which means that users can provide an `isComplete` lambda function which is called periodically until the operation is complete. This allows implementing providers that can take up to two hours to stabilize. -Set `serviceToken` to `provider.serviceToken` to use this provider: +Set `serviceToken` to `provider.serviceToken` to use this type of provider: ```ts import { Provider } from 'custom-resources'; @@ -333,6 +480,8 @@ new CustomResource(this, 'MyResource', { }); ``` +See the [documentation](https://docs.aws.amazon.com/cdk/api/latest/docs/custom-resources-readme.html) for more details. + #### Amazon SNS Topic Every time a resource event occurs (CREATE/UPDATE/DELETE), an SNS notification diff --git a/packages/@aws-cdk/core/lib/context-provider.ts b/packages/@aws-cdk/core/lib/context-provider.ts index d2442f0bb025e..d5c7928649f37 100644 --- a/packages/@aws-cdk/core/lib/context-provider.ts +++ b/packages/@aws-cdk/core/lib/context-provider.ts @@ -1,3 +1,4 @@ +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from './construct-compat'; import { Stack } from './stack'; @@ -99,7 +100,11 @@ export class ContextProvider { // if context is missing or an error occurred during context retrieval, // report and return a dummy value. if (value === undefined || providerError !== undefined) { - stack.reportMissingContext({ key, props, provider: options.provider }); + stack.reportMissingContext({ + key, + provider: options.provider as cxschema.ContextProvider, + props: props as cxschema.ContextQueryProperties, + }); if (providerError !== undefined) { scope.node.addError(providerError); diff --git a/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts b/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts new file mode 100644 index 0000000000000..8b24d068235f9 --- /dev/null +++ b/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts @@ -0,0 +1,183 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { AssetStaging } from '../asset-staging'; +import { FileAssetPackaging } from '../assets'; +import { CfnResource } from '../cfn-resource'; +import { Construct } from '../construct-compat'; +import { Duration } from '../duration'; +import { Size } from '../size'; +import { Stack } from '../stack'; +import { Token } from '../token'; + +const ENTRYPOINT_FILENAME = '__entrypoint__'; +const ENTRYPOINT_NODEJS_SOURCE = path.join(__dirname, 'nodejs-entrypoint.js'); + +/** + * Initialization properties for `CustomResourceProvider`. + * + * @experimental + */ +export interface CustomResourceProviderProps { + /** + * A local file system directory with the provider's code. The code will be + * bundled into a zip asset and wired to the provider's AWS Lambda function. + */ + readonly codeDirectory: string; + + /** + * The AWS Lambda runtime and version to use for the provider. + */ + readonly runtime: CustomResourceProviderRuntime; + + /** + * A set of IAM policy statements to include in the inline policy of the + * provider's lambda function. + * + * @default - no additional inline policy + * + * @example + * + * policyStatements: [ { Effect: 'Allow', Action: 's3:PutObject*', Resource: '*' } ] + * + */ + readonly policyStatements?: any[]; + + /** + * AWS Lambda timeout for the provider. + * + * @default Duration.minutes(15) + */ + readonly timeout?: Duration; + + /** + * The amount of memory that your function has access to. Increasing the + * function's memory also increases its CPU allocation. + * + * @default Size.mebibytes(128) + */ + readonly memorySize?: Size; +} + +/** + * The lambda runtime to use for the resource provider. This also indicates + * which language is used for the handler. + * @experimental + */ +export enum CustomResourceProviderRuntime { + /** + * Node.js 12.x + */ + NODEJS_12 = 'nodejs12' +} + +/** + * An AWS-Lambda backed custom resource provider. + * + * @experimental + */ +export class CustomResourceProvider extends Construct { + /** + * Returns a stack-level singleton ARN (service token) for the custom resource + * provider. + * + * @param scope Construct scope + * @param uniqueid A globally unique id that will be used for the stack-level + * construct. + * @param props Provider properties which will only be applied when the + * provider is first created. + * @returns the service token of the custom resource provider, which should be + * used when defining a `CustomResource`. + */ + public static getOrCreate(scope: Construct, uniqueid: string, props: CustomResourceProviderProps) { + const id = `${uniqueid}CustomResourceProvider`; + const stack = Stack.of(scope); + const provider = stack.node.tryFindChild(id) as CustomResourceProvider + ?? new CustomResourceProvider(stack, id, props); + + return provider.serviceToken; + } + + /** + * The ARN of the provider's AWS Lambda function which should be used as the + * `serviceToken` when defining a custom resource. + * + * @example + * + * new CustomResource(this, 'MyCustomResource', { + * // ... + * serviceToken: provider.serviceToken // <--- here + * }) + * + */ + public readonly serviceToken: string; + + protected constructor(scope: Construct, id: string, props: CustomResourceProviderProps) { + super(scope, id); + + const stack = Stack.of(scope); + + // copy the entry point to the code directory + fs.copyFileSync(ENTRYPOINT_NODEJS_SOURCE, path.join(props.codeDirectory, `${ENTRYPOINT_FILENAME}.js`)); + + // verify we have an index file there + if (!fs.existsSync(path.join(props.codeDirectory, 'index.js'))) { + throw new Error(`cannot find ${props.codeDirectory}/index.js`); + } + + const staging = new AssetStaging(this, 'Staging', { + sourcePath: props.codeDirectory, + }); + + const asset = stack.addFileAsset({ + fileName: staging.stagedPath, + sourceHash: staging.sourceHash, + packaging: FileAssetPackaging.ZIP_DIRECTORY, + }); + + const policies = !props.policyStatements ? undefined : [ + { + PolicyName: 'Inline', + PolicyDocument: { + Version: '2012-10-17', + Statement: props.policyStatements, + }, + }, + ]; + + const role = new CfnResource(this, 'Role', { + type: 'AWS::IAM::Role', + properties: { + AssumeRolePolicyDocument: { + Version: '2012-10-17', + Statement: [ { Action: 'sts:AssumeRole', Effect: 'Allow', Principal: { Service: 'lambda.amazonaws.com' } } ], + }, + ManagedPolicyArns: [ + { 'Fn::Sub': 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' }, + ], + Policies: policies, + }, + }); + + const timeout = props.timeout ?? Duration.minutes(15); + const memory = props.memorySize ?? Size.mebibytes(128); + + const handler = new CfnResource(this, 'Handler', { + type: 'AWS::Lambda::Function', + properties: { + Code: { + S3Bucket: asset.bucketName, + S3Key: asset.objectKey, + }, + Timeout: timeout.toSeconds(), + MemorySize: memory.toMebibytes(), + Handler: `${ENTRYPOINT_FILENAME}.handler`, + Role: role.getAtt('Arn'), + Runtime: 'nodejs12.x', + }, + }); + + handler.addDependsOn(role); + + this.serviceToken = Token.asString(handler.getAtt('Arn')); + } +} diff --git a/packages/@aws-cdk/core/lib/custom-resource-provider/index.ts b/packages/@aws-cdk/core/lib/custom-resource-provider/index.ts new file mode 100644 index 0000000000000..9ff36ec201b71 --- /dev/null +++ b/packages/@aws-cdk/core/lib/custom-resource-provider/index.ts @@ -0,0 +1 @@ +export * from './custom-resource-provider'; \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/custom-resource-provider/nodejs-entrypoint.ts b/packages/@aws-cdk/core/lib/custom-resource-provider/nodejs-entrypoint.ts new file mode 100644 index 0000000000000..c90bf96e684cf --- /dev/null +++ b/packages/@aws-cdk/core/lib/custom-resource-provider/nodejs-entrypoint.ts @@ -0,0 +1,139 @@ +import * as https from 'https'; +import * as url from 'url'; + +// for unit tests +export const external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; + +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; + +export type Response = AWSLambda.CloudFormationCustomResourceEvent & HandlerResponse; +export type Handler = (event: AWSLambda.CloudFormationCustomResourceEvent) => Promise; +export type HandlerResponse = undefined | { + Data?: any; + PhysicalResourceId?: string; + Reason?: string; + NoEcho?: boolean; +}; + +export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { + external.log(JSON.stringify(event, undefined, 2)); + + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler: Handler = require(external.userHandlerIndex).handler; + const result = await userHandler(event); + + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } catch (e) { + const resp: Response = { + ...event, + Reason: external.includeStackTraces ? e.stack : e.message, + }; + + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} + +function renderResponse( + cfnRequest: AWSLambda.CloudFormationCustomResourceEvent & { PhysicalResourceId?: string }, + handlerResponse: void | HandlerResponse = { }): Response { + + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} + +async function submitResponse(status: 'SUCCESS' | 'FAILED', event: Response) { + const json: AWSLambda.CloudFormationCustomResourceResponse = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + + external.log('submit response to cloudformation', json); + + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { 'content-type': '', 'content-length': responseBody.length }, + }; + + await external.sendHttpRequest(req, responseBody); +} + +async function defaultSendHttpRequest(options: https.RequestOptions, responseBody: string): Promise { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } catch (e) { + reject(e); + } + }); +} + +function defaultLog(fmt: string, ...params: any[]) { + // tslint:disable-next-line:no-console + console.log(fmt, ...params); +} diff --git a/packages/@aws-cdk/core/lib/fs/fingerprint.ts b/packages/@aws-cdk/core/lib/fs/fingerprint.ts index dcac8f5ba5fce..80f133d4b5f51 100644 --- a/packages/@aws-cdk/core/lib/fs/fingerprint.ts +++ b/packages/@aws-cdk/core/lib/fs/fingerprint.ts @@ -33,12 +33,13 @@ export function fingerprint(fileOrDirectory: string, options: FingerprintOptions if (exclude.length) { _hashField(hash, 'options.exclude', JSON.stringify(exclude)); } - _processFileOrDirectory(fileOrDirectory); + const isDir = fs.statSync(fileOrDirectory).isDirectory(); + _processFileOrDirectory(fileOrDirectory, isDir); return hash.digest('hex'); - function _processFileOrDirectory(symbolicPath: string, realPath = symbolicPath) { - if (shouldExclude(exclude, symbolicPath)) { + function _processFileOrDirectory(symbolicPath: string, isRootDir: boolean = false, realPath = symbolicPath) { + if (!isRootDir && shouldExclude(exclude, symbolicPath)) { return; } @@ -49,7 +50,7 @@ export function fingerprint(fileOrDirectory: string, options: FingerprintOptions const linkTarget = fs.readlinkSync(realPath); const resolvedLinkTarget = path.resolve(path.dirname(realPath), linkTarget); if (shouldFollow(follow, rootDirectory, resolvedLinkTarget)) { - _processFileOrDirectory(symbolicPath, resolvedLinkTarget); + _processFileOrDirectory(symbolicPath, false, resolvedLinkTarget); } else { _hashField(hash, `link:${relativePath}`, linkTarget); } @@ -57,7 +58,7 @@ export function fingerprint(fileOrDirectory: string, options: FingerprintOptions _hashField(hash, `file:${relativePath}`, _contentFingerprint(realPath, stat)); } else if (stat.isDirectory()) { for (const item of fs.readdirSync(realPath).sort()) { - _processFileOrDirectory(path.join(symbolicPath, item), path.join(realPath, item)); + _processFileOrDirectory(path.join(symbolicPath, item), false, path.join(realPath, item)); } } else { throw new Error(`Unable to hash ${symbolicPath}: it is neither a file nor a directory`); diff --git a/packages/@aws-cdk/core/lib/index.ts b/packages/@aws-cdk/core/lib/index.ts index 890b0fc215327..201de0947af84 100644 --- a/packages/@aws-cdk/core/lib/index.ts +++ b/packages/@aws-cdk/core/lib/index.ts @@ -48,6 +48,7 @@ export * from './fs'; export * from './custom-resource'; export * from './nested-stack'; +export * from './custom-resource-provider'; export * from './cfn-capabilities'; export * from './cloudformation.generated'; diff --git a/packages/@aws-cdk/core/lib/stack.ts b/packages/@aws-cdk/core/lib/stack.ts index f9340e314dd9a..cda56f53de5e8 100644 --- a/packages/@aws-cdk/core/lib/stack.ts +++ b/packages/@aws-cdk/core/lib/stack.ts @@ -324,14 +324,17 @@ export class Stack extends Construct implements ITaggable { * @param report The set of parameters needed to obtain the context */ public reportMissingContext(report: cxapi.MissingContext) { - this._missingContext.push(report); + if (!Object.values(cxschema.ContextProvider).includes(report.provider as cxschema.ContextProvider)) { + throw new Error(`Unknown context provider requested in: ${JSON.stringify(report)}`); + } + this._missingContext.push(report as cxschema.MissingContext); } /** * Rename a generated logical identities * * To modify the naming scheme strategy, extend the `Stack` class and - * override the `createNamingScheme` method. + * override the `allocateLogicalId` method. */ public renameLogicalId(oldId: string, newId: string) { this._logicalIds.addRename(oldId, newId); @@ -520,12 +523,12 @@ export class Stack extends Construct implements ITaggable { } const value = ContextProvider.getValue(this, { - provider: cxapi.AVAILABILITY_ZONE_PROVIDER, + provider: cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER, dummyValue: ['dummy1a', 'dummy1b', 'dummy1c'], }).value; if (!Array.isArray(value)) { - throw new Error(`Provider ${cxapi.AVAILABILITY_ZONE_PROVIDER} expects a list`); + throw new Error(`Provider ${cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER} expects a list`); } return value; diff --git a/packages/@aws-cdk/core/test/custom-resource-provider/mock-provider/index.ts b/packages/@aws-cdk/core/test/custom-resource-provider/mock-provider/index.ts new file mode 100644 index 0000000000000..5a372f057593e --- /dev/null +++ b/packages/@aws-cdk/core/test/custom-resource-provider/mock-provider/index.ts @@ -0,0 +1,10 @@ +// tslint:disable: no-console + +export function handler(event: any) { + console.log('I am a custom resource'); + console.log(event); + return { + PhysicalResourceId: event.ResourceProperties.physicalResourceId, + Data: event.ResourceProperties.attributes, + }; +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/test/custom-resource-provider/test.custom-resource-provider.ts b/packages/@aws-cdk/core/test/custom-resource-provider/test.custom-resource-provider.ts new file mode 100644 index 0000000000000..99c8fb12d4e70 --- /dev/null +++ b/packages/@aws-cdk/core/test/custom-resource-provider/test.custom-resource-provider.ts @@ -0,0 +1,168 @@ +import * as fs from 'fs'; +import { Test } from 'nodeunit'; +import * as path from 'path'; +import { CustomResourceProvider, CustomResourceProviderRuntime, Duration, Size, Stack } from '../../lib'; +import { toCloudFormation } from '../util'; + +const TEST_HANDLER = `${__dirname}/mock-provider`; + +export = { + 'minimal configuration'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + CustomResourceProvider.getOrCreate(stack, 'Custom:MyResourceType', { + codeDirectory: TEST_HANDLER, + runtime: CustomResourceProviderRuntime.NODEJS_12, + }); + + // THEN + test.ok(fs.existsSync(path.join(TEST_HANDLER, '__entrypoint__.js')), 'expecting entrypoint to be copied to the handler directory'); + const cfn = toCloudFormation(stack); + test.deepEqual(cfn, { + Resources: { + CustomMyResourceTypeCustomResourceProviderRoleBD5E655F: { + Type: 'AWS::IAM::Role', + Properties: { + AssumeRolePolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'lambda.amazonaws.com', + }, + }, + ], + }, + ManagedPolicyArns: [ + { + 'Fn::Sub': 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', + }, + ], + }, + }, + CustomMyResourceTypeCustomResourceProviderHandler29FBDD2A: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + S3Bucket: { + Ref: 'AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3Bucket1D703CB8', + }, + S3Key: { + 'Fn::Join': [ + '', + [ + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { + Ref: 'AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3VersionKey01A97AE3', + }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { + Ref: 'AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3VersionKey01A97AE3', + }, + ], + }, + ], + }, + ], + ], + }, + }, + Timeout: 900, + MemorySize: 128, + Handler: '__entrypoint__.handler', + Role: { + 'Fn::GetAtt': [ + 'CustomMyResourceTypeCustomResourceProviderRoleBD5E655F', + 'Arn', + ], + }, + Runtime: 'nodejs12.x', + }, + DependsOn: [ + 'CustomMyResourceTypeCustomResourceProviderRoleBD5E655F', + ], + }, + }, + Parameters: { + AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3Bucket1D703CB8: { + Type: 'String', + Description: 'S3 bucket for asset "d46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7a"', + }, + AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aS3VersionKey01A97AE3: { + Type: 'String', + Description: 'S3 key for asset version "d46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7a"', + }, + AssetParametersd46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7aArtifactHash16A571C9: { + Type: 'String', + Description: 'Artifact hash for asset "d46d1ebe2c1958c6352664721f77acb9c78131013956eb82d3d36cf503098e7a"', + }, + }, + }); + test.done(); + }, + + 'policyStatements can be used to add statements to the inline policy'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + CustomResourceProvider.getOrCreate(stack, 'Custom:MyResourceType', { + codeDirectory: TEST_HANDLER, + runtime: CustomResourceProviderRuntime.NODEJS_12, + policyStatements: [ + { statement1: 123 }, + { statement2: { foo: 111 } }, + ], + }); + + // THEN + const template = toCloudFormation(stack); + const role = template.Resources.CustomMyResourceTypeCustomResourceProviderRoleBD5E655F; + test.deepEqual(role.Properties.Policies, [{ + PolicyName: 'Inline', + PolicyDocument: { + Version: '2012-10-17', + Statement: [{ statement1: 123 }, { statement2: { foo: 111 } }], + }, + }]); + test.done(); + }, + + 'memorySize and timeout'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + CustomResourceProvider.getOrCreate(stack, 'Custom:MyResourceType', { + codeDirectory: TEST_HANDLER, + runtime: CustomResourceProviderRuntime.NODEJS_12, + memorySize: Size.gibibytes(2), + timeout: Duration.minutes(5), + }); + + // THEN + const template = toCloudFormation(stack); + const lambda = template.Resources.CustomMyResourceTypeCustomResourceProviderHandler29FBDD2A; + test.deepEqual(lambda.Properties.MemorySize, 2048); + test.deepEqual(lambda.Properties.Timeout, 300); + test.done(); + }, +}; diff --git a/packages/@aws-cdk/core/test/custom-resource-provider/test.nodejs-entrypoint.ts b/packages/@aws-cdk/core/test/custom-resource-provider/test.nodejs-entrypoint.ts new file mode 100644 index 0000000000000..87935b7d93599 --- /dev/null +++ b/packages/@aws-cdk/core/test/custom-resource-provider/test.nodejs-entrypoint.ts @@ -0,0 +1,198 @@ +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as https from 'https'; +import { Test } from 'nodeunit'; +import * as os from 'os'; +import * as path from 'path'; +import * as url from 'url'; +import * as entrypoint from '../../lib/custom-resource-provider/nodejs-entrypoint'; + +export = { + 'handler return value is sent back to cloudformation as a success response': { + + async 'physical resource id (ref)'(test: Test) { + // GIVEN + const createEvent = makeEvent({ RequestType: 'Create' }); + + // WHEN + const response = await invokeHandler(createEvent, async _ => ({ PhysicalResourceId: 'returned-from-handler' })); + + // THEN + test.deepEqual(response.Status, 'SUCCESS'); + test.deepEqual(response.PhysicalResourceId, 'returned-from-handler'); + test.done(); + }, + + async 'data (attributes)'(test: Test) { + // GIVEN + const createEvent = makeEvent({ RequestType: 'Create' }); + + // WHEN + const response = await invokeHandler(createEvent, async _ => { + return { + Data: { + Attribute1: 'hello', + Attribute2: { + Foo: 1111, + }, + }, + }; + }); + + // THEN + test.deepEqual(response.Status, 'SUCCESS'); + test.deepEqual(response.PhysicalResourceId, '', 'physical id defaults to request id'); + test.deepEqual(response.Data, { + Attribute1: 'hello', + Attribute2: { + Foo: 1111, + }, + }); + test.done(); + }, + + async 'no echo'(test: Test) { + // GIVEN + const createEvent = makeEvent({ RequestType: 'Create' }); + + // WHEN + const response = await invokeHandler(createEvent, async _ => ({ NoEcho: true })); + + // THEN + test.deepEqual(response.Status, 'SUCCESS'); + test.deepEqual(response.NoEcho, true); + test.done(); + }, + + async 'reason'(test: Test) { + // GIVEN + const createEvent = makeEvent({ RequestType: 'Create' }); + + // WHEN + const response = await invokeHandler(createEvent, async _ => ({ Reason: 'hello, reason' })); + + // THEN + test.deepEqual(response.Status, 'SUCCESS'); + test.deepEqual(response.Reason, 'hello, reason'); + test.done(); + }, + }, + + async 'an error thrown by the handler is sent as a failure response to cloudformation'(test: Test) { + // GIVEN + const createEvent = makeEvent({ RequestType: 'Create' }); + + // WHEN + const response = await invokeHandler(createEvent, async _ => { + throw new Error('this is an error'); + }); + + // THEN + test.deepEqual(response, { + Status: 'FAILED', + Reason: 'this is an error', + StackId: '', + RequestId: '', + PhysicalResourceId: 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED', + LogicalResourceId: '', + }); + + test.done(); + }, + + async 'physical resource id cannot be changed in DELETE'(test: Test) { + // GIVEN + const event = makeEvent({ RequestType: 'Delete' }); + + // WHEN + const response = await invokeHandler(event, async _ => ({ + PhysicalResourceId: 'Changed', + })); + + // THEN + test.deepEqual(response, { + Status: 'FAILED', + Reason: 'DELETE: cannot change the physical resource ID from "undefined" to "Changed" during deletion', + StackId: '', + RequestId: '', + PhysicalResourceId: 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID', + LogicalResourceId: '', + }); + + test.done(); + }, + + async 'DELETE after CREATE is ignored with success'(test: Test) { + // GIVEN + const event = makeEvent({ + RequestType: 'Delete', + PhysicalResourceId: 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED', + }); + + // WHEN + const response = await invokeHandler(event, async _ => { + test.ok(false, 'handler should not be called'); + }); + + // THEN + test.deepEqual(response, { + Status: 'SUCCESS', + Reason: 'SUCCESS', + StackId: '', + RequestId: '', + PhysicalResourceId: 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED', + LogicalResourceId: '', + }); + + test.done(); + + }, +}; + +function makeEvent(req: Partial): AWSLambda.CloudFormationCustomResourceEvent { + return { + LogicalResourceId: '', + RequestId: '', + ResourceType: '', + ResponseURL: '', + ServiceToken: '', + StackId: '', + ResourceProperties: { + ServiceToken: '', + ...req.ResourceProperties, + }, + ...req, + } as any; +} + +async function invokeHandler(req: AWSLambda.CloudFormationCustomResourceEvent, userHandler: entrypoint.Handler) { + const parsedResponseUrl = url.parse(req.ResponseURL); + + // stage entry point and user handler. + const workdir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-custom-resource-provider-handler-test-')); + entrypoint.external.userHandlerIndex = path.join(workdir, 'index.js'); + fs.writeFileSync(entrypoint.external.userHandlerIndex, `exports.handler = ${userHandler.toString()};`); + + // do not include stack traces in failure responses so we can assert against them. + entrypoint.external.includeStackTraces = false; + + // disable logging + entrypoint.external.log = () => { + return; + }; + + let actualResponse; + entrypoint.external.sendHttpRequest = async (options: https.RequestOptions, responseBody: string): Promise => { + assert(options.hostname === parsedResponseUrl.hostname, 'request hostname expected to be based on response URL'); + assert(options.path === parsedResponseUrl.path, 'request path expected to be based on response URL'); + assert(options.method === 'PUT', 'request method is expected to be PUT'); + actualResponse = responseBody; + }; + + await entrypoint.handler(req); + if (!actualResponse) { + throw new Error('no response sent to cloudformation'); + } + + return JSON.parse(actualResponse) as AWSLambda.CloudFormationCustomResourceResponse; +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/test/fs/test.fs-fingerprint.ts b/packages/@aws-cdk/core/test/fs/test.fs-fingerprint.ts index 7be40d4b31ad4..414386a649523 100644 --- a/packages/@aws-cdk/core/test/fs/test.fs-fingerprint.ts +++ b/packages/@aws-cdk/core/test/fs/test.fs-fingerprint.ts @@ -166,6 +166,20 @@ export = { const f1 = FileSystem.fingerprint(dir, options1); const f2 = FileSystem.fingerprint(dir, options2); + // THEN + test.notDeepEqual(f1, f2); + test.done(); + }, + 'considers negated exclude patterns for fingerprint'(test: Test) { + // GIVEN + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'fingerprint-tests')); + const options = {path: dir, exclude: ['**', '!file.txt'], sourcePath: dir}; + + // WHEN + const f1 = FileSystem.fingerprint(dir, options); + fs.writeFileSync(path.join(dir, 'file.txt'), 'data'); + const f2 = FileSystem.fingerprint(dir, options); + // THEN test.notDeepEqual(f1, f2); test.done(); diff --git a/packages/@aws-cdk/core/test/integration.custom-resources.readme b/packages/@aws-cdk/core/test/integration.custom-resources.readme new file mode 100644 index 0000000000000..bc1e807e01237 --- /dev/null +++ b/packages/@aws-cdk/core/test/integration.custom-resources.readme @@ -0,0 +1,5 @@ ++--------------------------------------------------------------------------+ +| Since cdk-integ depends on cdk which depends on @aws-cdk/core (as a "dev | +| dependency"), this integration test has been added to the package | +| @aws-cdk/aws-cloudformation under `test/integ.core-custom-resources.ts` | ++--------------------------------------------------------------------------+ diff --git a/packages/@aws-cdk/core/test/test.app.ts b/packages/@aws-cdk/core/test/test.app.ts index 7812c01c67e55..04ea5b47492c3 100644 --- a/packages/@aws-cdk/core/test/test.app.ts +++ b/packages/@aws-cdk/core/test/test.app.ts @@ -1,3 +1,4 @@ +import { ContextProvider } from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { Test } from 'nodeunit'; import { CfnResource, Construct, Stack, StackProps } from '../lib'; @@ -189,7 +190,7 @@ export = { this.reportMissingContext({ key: 'missing-context-key', - provider: 'fake', + provider: ContextProvider.AVAILABILITY_ZONE_PROVIDER, props: { account: '12345689012', region: 'ab-north-1', @@ -199,9 +200,8 @@ export = { this.reportMissingContext({ key: 'missing-context-key-2', - provider: 'fake2', + provider: ContextProvider.AVAILABILITY_ZONE_PROVIDER, props: { - foo: 'bar', account: '12345689012', region: 'ab-south-1', }, @@ -217,7 +217,7 @@ export = { test.deepEqual(assembly.manifest.missing, [ { key: 'missing-context-key', - provider: 'fake', + provider: ContextProvider.AVAILABILITY_ZONE_PROVIDER, props: { account: '12345689012', region: 'ab-north-1', @@ -225,11 +225,10 @@ export = { }, { key: 'missing-context-key-2', - provider: 'fake2', + provider: ContextProvider.AVAILABILITY_ZONE_PROVIDER, props: { account: '12345689012', region: 'ab-south-1', - foo: 'bar', }, }, ]); diff --git a/packages/@aws-cdk/core/test/test.context.ts b/packages/@aws-cdk/core/test/test.context.ts index 47561ff5a48c2..d83f41ba9feaf 100644 --- a/packages/@aws-cdk/core/test/test.context.ts +++ b/packages/@aws-cdk/core/test/test.context.ts @@ -140,8 +140,8 @@ export = { }, 'context provider errors are attached to tree'(test: Test) { - const contextProps = { provider: 'bloop' }; - const contextKey = 'bloop:account=12345:region=us-east-1'; // Depends on the mangling algo + const contextProps = { provider: 'availability-zones' }; + const contextKey = 'availability-zones:account=12345:region=us-east-1'; // Depends on the mangling algo // GIVEN const stack = new Stack(undefined, 'TestStack', { env: { account: '12345', region: 'us-east-1' } }); diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 8a3e812e6a868..785cf8831bb91 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -73,7 +73,7 @@ "@types/aws-lambda": "^8.10.39", "@types/fs-extra": "^8.1.0", "@types/sinon": "^9.0.0", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts b/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts index 30e86fb567d9b..0cf2e3d2ea9e0 100644 --- a/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts +++ b/packages/@aws-cdk/cx-api/lib/cloud-assembly.ts @@ -285,8 +285,27 @@ export interface MetadataEntry extends cxschema.MetadataEntry { * @deprecated moved to package 'cloud-assembly-schema' * @see core.Stack.reportMissingContext */ -export interface MissingContext extends cxschema.MissingContext { +export interface MissingContext { + /** + * The missing context key. + */ + readonly key: string; + /** + * The provider from which we expect this context key to be obtained. + * + * (This is the old untyped definition, which is necessary for backwards compatibility. + * See cxschema for a type definition.) + */ + readonly provider: string; + + /** + * A set of provider-specific options. + * + * (This is the old untyped definition, which is necessary for backwards compatibility. + * See cxschema for a type definition.) + */ + readonly props: Record; } export interface AssemblyBuildOptions { diff --git a/packages/@aws-cdk/cx-api/lib/context/ami.ts b/packages/@aws-cdk/cx-api/lib/context/ami.ts index c9fa8accbcd43..00908a5e4798c 100644 --- a/packages/@aws-cdk/cx-api/lib/context/ami.ts +++ b/packages/@aws-cdk/cx-api/lib/context/ami.ts @@ -1,23 +1,4 @@ -export const AMI_PROVIDER = 'ami'; - -/** - * Query to AMI context provider - */ -export interface AmiContextQuery { - /** - * Owners to DescribeImages call - * - * @default - All owners - */ - readonly owners?: string[]; - - /** - * Filters to DescribeImages call - */ - readonly filters: {[key: string]: string[]}; -} - /** * Returns just an AMI ID */ -export type AmiContextResponse = string; \ No newline at end of file +export type AmiContextResponse = string; diff --git a/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts b/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts index 9fa2a2f9601d2..fe1f484ba8b6f 100644 --- a/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts +++ b/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts @@ -1,25 +1,3 @@ -export const AVAILABILITY_ZONE_PROVIDER = 'availability-zones'; - -/** - * Query to hosted zone context provider - */ -export interface AvailabilityZonesContextQuery { - /** - * Query account - */ - readonly account?: string; - - /** - * Query region - */ - readonly region?: string; -} - -/** - * Response of the AZ provider looks like this - */ -export type AvailabilityZonesContextResponse = string[]; - /** * This context key is used to determine the value of `stack.availabilityZones` * when a stack is not associated with a specific account/region (env-agnostic). @@ -27,4 +5,9 @@ export type AvailabilityZonesContextResponse = string[]; * If this key is passed in the context, the values will be used. Otherwise, a * system-fallback which uses `Fn::GetAZs` will be used. */ -export const AVAILABILITY_ZONE_FALLBACK_CONTEXT_KEY = 'aws:cdk:availability-zones:fallback'; \ No newline at end of file +export const AVAILABILITY_ZONE_FALLBACK_CONTEXT_KEY = 'aws:cdk:availability-zones:fallback'; + +/** + * Response of the AZ provider looks like this + */ +export type AvailabilityZonesContextResponse = string[]; \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts b/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts deleted file mode 100644 index c2dad65d924f7..0000000000000 --- a/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts +++ /dev/null @@ -1,57 +0,0 @@ -export const HOSTED_ZONE_PROVIDER = 'hosted-zone'; - -/** - * Query to hosted zone context provider - */ -export interface HostedZoneContextQuery { - /** - * Query account - */ - readonly account?: string; - - /** - * Query region - */ - readonly region?: string; - - /** - * The domain name e.g. example.com to lookup - */ - readonly domainName: string; - - /** - * True if the zone you want to find is a private hosted zone - */ - readonly privateZone?: boolean; - - /** - * The VPC ID to that the private zone must be associated with - * - * If you provide VPC ID and privateZone is false, this will return no results - * and raise an error. - */ - readonly vpcId?: string; -} - -/** - * Hosted zone context - * - * This definition is for human reference. It is not machine-checked as the - * naming conventions used in it are not JSII compatible, and changing those - * introduces a backwards incompatibility. - */ -// export interface HostedZoneContextResponse { -// /** -// * The ID that Amazon Route 53 assigned to the hosted zone when you created -// * it. -// */ -// Id: string; - -// /** -// * The name of the domain. For public hosted zones, this is the name that you -// * have registered with your DNS registrar. For information about how to -// * specify characters other than a-z, 0-9, and - (hyphen) and how to specify -// * internationalized domain names, see CreateHostedZone. -// */ -// Name: string; -// } \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts b/packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts deleted file mode 100644 index c0b27a46db796..0000000000000 --- a/packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts +++ /dev/null @@ -1,23 +0,0 @@ -export const SSM_PARAMETER_PROVIDER = 'ssm'; - -/** - * Query to hosted zone context provider - */ -export interface SSMParameterContextQuery { - /** - * Query account - */ - readonly account?: string; - - /** - * Query region - */ - readonly region?: string; - - /** - * Parameter name to query - */ - readonly parameterName?: string; -} - -// Response is a string \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/context/vpc.ts b/packages/@aws-cdk/cx-api/lib/context/vpc.ts index 245ea842f735a..8d7bbf34f28ea 100644 --- a/packages/@aws-cdk/cx-api/lib/context/vpc.ts +++ b/packages/@aws-cdk/cx-api/lib/context/vpc.ts @@ -1,47 +1,3 @@ -export const VPC_PROVIDER = 'vpc-provider'; - -/** - * Query input for looking up a VPC - */ -export interface VpcContextQuery { - /** - * Query account - */ - readonly account?: string; - - /** - * Query region - */ - readonly region?: string; - - /** - * Filters to apply to the VPC - * - * Filter parameters are the same as passed to DescribeVpcs. - * - * @see https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html - */ - readonly filter: {[key: string]: string}; - - /** - * Whether to populate the subnetGroups field of the {@link VpcContextResponse}, - * which contains potentially asymmetric subnet groups. - * - * @default false - */ - readonly returnAsymmetricSubnets?: boolean; - - /** - * Optional tag for subnet group name. - * If not provided, we'll look at the aws-cdk:subnet-name tag. - * If the subnet does not have the specified tag, - * we'll use its type as the name. - * - * @default 'aws-cdk:subnet-name' - */ - readonly subnetGroupNameTag?: string; -} - /** * The type of subnet group. * Same as SubnetType in the @aws-cdk/aws-ec2 package, diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index 38629ffd7a17f..cb4079a02d6a6 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -1,7 +1,5 @@ export * from './cxapi'; -export * from './context/hosted-zone'; export * from './context/vpc'; -export * from './context/ssm-parameter'; export * from './context/ami'; export * from './context/availability-zones'; export * from './cloud-artifact'; diff --git a/packages/@aws-cdk/cx-api/test/__snapshots__/cloud-assembly.test.js.snap b/packages/@aws-cdk/cx-api/test/__snapshots__/cloud-assembly.test.js.snap index aa6c729905fe5..6aa2a5490d445 100644 --- a/packages/@aws-cdk/cx-api/test/__snapshots__/cloud-assembly.test.js.snap +++ b/packages/@aws-cdk/cx-api/test/__snapshots__/cloud-assembly.test.js.snap @@ -24,9 +24,13 @@ Array [ Object { "key": "missing:context:key", "props": Object { - "foo": 123, + "account": "1234", + "filter": Object { + "foo": 123, + }, + "region": "us-east-1", }, - "provider": "context-provider", + "provider": "vpc-provider", }, ] `; diff --git a/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts b/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts index dbdc57a7466fd..bc348d9442188 100644 --- a/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts +++ b/packages/@aws-cdk/cx-api/test/cloud-assembly-builder.test.ts @@ -36,10 +36,13 @@ test('cloud assembly builder', () => { session.addMissing({ key: 'foo', - provider: 'context-provider', + provider: cxschema.ContextProvider.VPC_PROVIDER, props: { - a: 'A', - b: 2, + account: '1234', + region: 'us-east-1', + filter: { + a: 'a', + }, }, }); @@ -67,7 +70,17 @@ test('cloud assembly builder', () => { expect(manifest).toStrictEqual({ version: cxschema.Manifest.version(), missing: [ - { key: 'foo', provider: 'context-provider', props: { a: 'A', b: 2 } }, + { + key: 'foo', + provider: 'vpc-provider', + props: { + account: '1234', + region: 'us-east-1', + filter: { + a: 'a', + }, + }, + }, ], artifacts: { 'tree-artifact': { @@ -115,8 +128,14 @@ test('duplicate missing values with the same key are only reported once', () => const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloud-assembly-builder-tests')); const session = new CloudAssemblyBuilder(outdir); - session.addMissing({ key: 'foo', provider: 'context-provider', props: { } }); - session.addMissing({ key: 'foo', provider: 'context-provider', props: { } }); + const props: cxschema.ContextQueryProperties = { + account: '1234', + region: 'asdf', + filter: { a: 'a' }, + }; + + session.addMissing({ key: 'foo', provider: cxschema.ContextProvider.VPC_PROVIDER, props }); + session.addMissing({ key: 'foo', provider: cxschema.ContextProvider.VPC_PROVIDER, props }); const assembly = session.buildAssembly(); diff --git a/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json index 1ff5e00933bb0..72bc48f404e6e 100644 --- a/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json +++ b/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json @@ -2,8 +2,14 @@ "version": "0.0.0", "missing": [{ "key": "missing:context:key", - "provider": "context-provider", - "props": { "foo": 123 } + "provider": "vpc-provider", + "props": { + "account": "1234", + "region": "us-east-1", + "filter": { + "foo": 123 + } + } }], "artifacts": { "MyStackName": { diff --git a/packages/@aws-cdk/example-construct-library/.eslintrc.js b/packages/@aws-cdk/example-construct-library/.eslintrc.js new file mode 100644 index 0000000000000..1b28bad193ceb --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/.eslintrc.js @@ -0,0 +1,2 @@ +const baseConfig = require('../../../tools/cdk-build-tools/config/eslintrc'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/example-construct-library/.gitignore b/packages/@aws-cdk/example-construct-library/.gitignore new file mode 100644 index 0000000000000..0bd6133da4d09 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/.gitignore @@ -0,0 +1,16 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js diff --git a/packages/@aws-cdk/example-construct-library/.npmignore b/packages/@aws-cdk/example-construct-library/.npmignore new file mode 100644 index 0000000000000..174864d493a79 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/.npmignore @@ -0,0 +1,21 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json +.eslintrc.js diff --git a/packages/@aws-cdk/example-construct-library/LICENSE b/packages/@aws-cdk/example-construct-library/LICENSE new file mode 100644 index 0000000000000..b71ec1688783a --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/example-construct-library/NOTICE b/packages/@aws-cdk/example-construct-library/NOTICE new file mode 100644 index 0000000000000..bfccac9a7f69c --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/example-construct-library/README.md b/packages/@aws-cdk/example-construct-library/README.md new file mode 100644 index 0000000000000..74a34f0a2c484 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/README.md @@ -0,0 +1,90 @@ +## An example Construct Library module + + +--- + +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. They are subject to non-backward compatible changes or removal in any future version. These are not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be announced in the release notes. This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package. + +--- + + +This package contains an example CDK construct library +for an imaginary resource called ExampleResource. +Its target audience are construct library authors - +both when contributing to the core CDK codebase, +or when writing your own construct library. + +Even though different construct libraries model vastly different services, +a large percentage of the structure of the construct libraries +(what we often call Layer 2 constructs, or L2s for short) +is actually strikingly similar between all of them. +This module hopes to present a skeleton of that structure, +that you can literally copy&paste to your own construct library, +and then edit to suit your needs. +It also attempts to explain the elements of that skeleton as best as it can, +through inline comments on the code itself. + +## Using when contributing to the CDK codebase + +If you're creating a completely new module, +feel free to copy&paste this entire directory, +and then edit the `package.json` and `README.md` +files as necessary (see the "Package structure" section below). +Make sure to remove the `"private": true` line from `package.json` +after copying, as otherwise your package will not be published! + +If you're contributing a new resource to an existing package, +feel free to copy&paste the following files, +instead of the entire package: + +* [`lib/example-resource.ts`](lib/example-resource.ts) +* [`lib/private/example-resource-common.ts`](lib/private/example-resource-common.ts) +* [`test/example-resource.test.ts`](test/example-resource.test.ts) +* [`test/integ.example-resource.ts`](test/integ.example-resource.ts) +* [`test/integ.example-resource.expected.json`](test/integ.example-resource.expected.json) + +And proceed to edit and rename them from there. + +## Using for your own construct libraries + +Feel free to use this package as the basis of your own construct library; +note, however, that you will have to change a few things in `package.json` to get it to build: + +* Remove the `"private": true` flag if you intend to publish your package to npmjs.org + (see https://docs.npmjs.com/files/package.json#private for details). +* Remove the `devDependencies` on `cdk-build-tools`, `cdk-integ-tools` and `pkglint`. +* Remove the `lint`, `integ`, `pkglint`, `package`, `build+test+package`, `awslint`, and `compat` entries in the `scripts` section. +* The `build` script should be just `tsc`, `watch` just `tsc -w`, and `test` just `jest`. +* Finally, the `awscdkio` key should be completely removed. + +You will also have to get rid of the integration test files, +[`test/integ.example-resource.ts`](test/integ.example-resource.ts) and +[`test/integ.example-resource.expected.json`](test/integ.example-resource.expected.json), +as those styles of integration tests are not available outside the CDK main repo. + +## Code structure + +The code structure is explained through inline comments in the files themselves. +Probably [`lib/example-resource.ts`](lib/example-resource.ts) is a good place to start reading. + +### Tests + +The package contains examples of unit tests in the [`test/example-resource.test.ts`](test/example-resource.test.ts) +file. + +It also contains an example integration test in [`test/integ.example-resource.ts`](test/integ.example-resource.ts). +For more information on CDK integ tests, see the +[main `Contributing.md` file](../../../CONTRIBUTING.md#integration-tests). + +## Package structure + +The package uses the standard build and test tools available in the CDK repo. +Even though it's not published, +it also uses [JSII](https://github.com/aws/jsii), +the technology that allows CDK logic to be written once, +but used from multiple programming languages. +Its configuration lives the `jsii` key in `package.json`. +It's mainly used as a validation tool in this package, +as JSII places some constraints on the TypeScript code that you can write. diff --git a/packages/@aws-cdk/example-construct-library/lib/example-resource.ts b/packages/@aws-cdk/example-construct-library/lib/example-resource.ts new file mode 100644 index 0000000000000..f2ad8ea9e2807 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/lib/example-resource.ts @@ -0,0 +1,510 @@ +/* + * We always import other construct libraries entirely with a prefix - + * we never import individual classes from them without a qualifier + * (the prefix makes it more obvious where a given dependency comes from, + * and prevents conflicting names causing issues). + * Our linter also enforces ES6-style imports - + * we don't use TypeScript's import a = require('a') imports. + */ +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as events from '@aws-cdk/aws-events'; +import * as iam from '@aws-cdk/aws-iam'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as core from '@aws-cdk/core'; +// for files that are part of this package, we do import individual classes or functions +import { exampleResourceArnComponents } from './private/example-resource-common'; + +/** + * The interface that represents the ExampleResource resource. + * We always use an interface, because each L2 resource type in the CDK can occur in two aspects: + * + * 1. It can be a resource that's created and managed by the CDK. + * Those resources are represented by the class with the name identical to the resource - + * {@link ExampleResource} in our case, which implements {@link IExampleResource}. + * 2. It can be a resource that exists already, and is not managed by the CDK code, + * but needs to be referenced in your infrastructure definition code. + * Those kinds of instances are returned from static `fromXyz(Name/Arn/Attributes)` methods - + * in our case, the {@link ExampleResource.fromExampleResourceName} method. + * In general, those kinds of resources do not allow any sort of mutating operations to be performed on them + * (the exception is when they can be changed by creating a different resource - + * IAM Roles, which you can attach multiple IAM Policies to, + * are the canonical example of this sort of resource), + * as they are not part of the CloudFormation stack that is created by the CDK. + * + * So, an interface like {@link IExampleResource} represents a resource that *might* be mutable, + * while the {@link ExampleResource} class represents a resource that definitely is mutable. + * Whenever a type that represents this resource needs to referenced in other code, + * you want to use {@link IExampleResource} as the type, not {@link ExampleResource}. + * + * The interface for the resource should have at least 2 (readonly) properties + * that represent the ARN and the physical name of the resource - + * in our example, those are {@link exampleResourceArn} and {@link exampleResourceName}. + * + * The interface defines the behaviors the resource exhibits. + * Common behaviors are: + * - {@link addToRolePolicy} for resources that are tied to an IAM Role + * - grantXyz() methods (represented by {@link grantRead} in this example) + * - onXyz() CloudWatch Events methods (represented by {@link onEvent} in this example) + * - metricXyz() CloudWatch Metric methods (represented by {@link metricCount} in this example) + * + * Of course, other behaviors are possible - + * it all depends on the capabilities of the underlying resource that is being modeled. + * + * This interface must always extend the IResource interface from the core module. + * It can also extend some other common interfaces that add various default behaviors - + * some examples are shown below. + */ +export interface IExampleResource extends + // all L2 interfaces need to extend IResource + core.IResource, + + // Only for resources that have an associated IAM Role. + // Allows this resource to be the target in calls like bucket.grantRead(exampleResource). + iam.IGrantable, + + // only for resources that are in a VPC and have SecurityGroups controlling their traffic + ec2.IConnectable { + + /** + * The ARN of example resource. + * Equivalent to doing `{ 'Fn::GetAtt': ['LogicalId', 'Arn' ]}` + * in CloudFormation if the underlying CloudFormation resource + * surfaces the ARN as a return value - + * if not, we usually construct the ARN "by hand" in the construct, + * using the Fn::Join function. + * + * It needs to be annotated with '@attribute' if the underlying CloudFormation resource + * surfaces the ARN as a return value. + * + * @attribute + */ + readonly exampleResourceArn: string; + + /** + * The physical name of the example resource. + * Often, equivalent to doing `{ 'Ref': 'LogicalId' }` + * (but not always - depends on the particular resource modeled) + * in CloudFormation. + * Also needs to be annotated with '@attribute'. + * + * @attribute + */ + readonly exampleResourceName: string; + + /** + * For resources that have an associated IAM Role, + * surface that Role as a property, + * so that other classes can add permissions to it. + * Make it optional, + * as resources imported with {@link ExampleResource.fromExampleResourceName} + * will not have this set. + */ + readonly role?: iam.IRole; + + /** + * For resources that have an associated IAM Role, + * surface a method that allows you to conditionally + * add a statement to that Role if it's known. + * This is just a convenience, + * so that clients of your interface don't have to check {@link role} for null. + * Many such methods in the CDK return void; + * you can also return a boolean indicating whether the permissions were in fact added + * (so, when {@link role} is not null). + */ + addToRolePolicy(policyStatement: iam.PolicyStatement): boolean; + + /** + * An example of a method that grants the given IAM identity + * permissions to this resource + * (in this case - read permissions). + */ + grantRead(identity: iam.IGrantable): iam.Grant; + + /** + * Add a CloudWatch rule that will use this resource as the source of events. + * Resources that emit events have a bunch of methods like these, + * that allow different resources to be triggered on various events happening to this resource + * (like item added, item updated, item deleted, ect.) - + * exactly which methods you need depends on the resource you're modeling. + */ + onEvent(id: string, options?: events.OnEventOptions): events.Rule; + + /** + * Standard method that allows you to capture metrics emitted by this resource, + * and use them in dashboards and alarms. + * The details of which metric methods you should have of course depends on the + * resource that is being modeled. + */ + metricCount(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric; +} + +/** + * A common abstract superclass that implements the {@link IExampleResource} interface. + * We often have these classes to share code between the {@link ExampleResource} + * class and the {@link IExampleResource} instances returned from methods like + * {@link ExampleResource.fromExampleResourceName}. + * It has to extend the Resource class from the core module. + * + * Notice that the class is not exported - it's not part of the public API of this module! + */ +abstract class ExampleResourceBase extends core.Resource implements IExampleResource { + // these stay abstract at this level + public abstract readonly exampleResourceArn: string; + public abstract readonly exampleResourceName: string; + public abstract readonly role?: iam.IRole; + // this property is needed for the iam.IGrantable interface + public abstract readonly grantPrincipal: iam.IPrincipal; + // This is needed for the ec2.IConnectable interface. + // Allow subclasses to write this field. + // JSII requires all member starting with an underscore to be annotated with '@internal'. + /** @internal */ + protected _connections: ec2.Connections | undefined; + + /** Implement the ec2.IConnectable interface, using the _connections field. */ + public get connections(): ec2.Connections { + if (!this._connections) { + throw new Error('An imported ExampleResource cannot manage its security groups'); + } + return this._connections; + } + + /** Implement the convenience {@link IExampleResource.addToRolePolicy} method. */ + public addToRolePolicy(policyStatement: iam.PolicyStatement): boolean { + if (this.role) { + this.role.addToPolicy(policyStatement); + return true; + } else { + return false; + } + } + + /** Implement the {@link IExampleResource.grantRead} method. */ + public grantRead(identity: iam.IGrantable): iam.Grant { + // usually, we would grant some service-specific permissions here, + // but since this is just an example, let's use S3 + return iam.Grant.addToPrincipal({ + grantee: identity, + actions: ['s3:Get*'], // as many actions as you need + resourceArns: [this.exampleResourceArn], + }); + } + + /** + * Implement the {@link IExampleResource.onEvent} method. + * Notice that we change 'options' from an optional argument to an argument with a default value - + * that's a common trick in the CDK + * (you're not allowed to have default values for arguments in interface methods in TypeScript), + * as it simplifies the implementation code (less branching). + */ + public onEvent(id: string, options: events.OnEventOptions = {}): events.Rule { + const rule = new events.Rule(this, id, options); + rule.addTarget(options.target); + rule.addEventPattern({ + // obviously, you would put your resource-specific values here + source: ['aws.cloudformation'], + detail: { + 'example-resource-name': [this.exampleResourceName], + }, + }); + return rule; + } + + /** Implement the {@link IExampleResource.metricCount} method. */ + public metricCount(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric { + return new cloudwatch.Metric({ + // of course, you would put your resource-specific values here + namespace: 'AWS/ExampleResource', + dimensions: { ExampleResource: this.exampleResourceName }, + metricName, + ...props, + }).attachTo(this); + } +} + +/** + * Construction properties for {@link ExampleResource}. + * All constructs have the same construction pattern: + * you provide a scope of type Construct, + * a string identifier, and a third argument, + * representing the properties specific to that resource. + * That third type is represented in the CDK by an interface + * with only readonly simple properties (no methods), + * sometimes called, in JSII terminology, a 'struct'. + * This is this struct for the {@link ExampleResource} class. + * + * This interface is always called 'Props'. + */ +export interface ExampleResourceProps { + /** + * The physical name of the resource. + * If you don't provide one, CloudFormation will generate one for you. + * Almost all resources, with only a few exceptions, + * allow setting their physical name. + * The name is a little silly, + * because of the @resource annotation on the {@link ExampleResource} class + * (CDK linters make sure those two names are aligned). + * + * @default - CloudFormation-generated name + */ + readonly waitConditionHandleName?: string; + + /** + * Many resources require an IAM Role to function. + * While a customer can provide one, + * the CDK will always create a new one + * (with the correct assumeRole service principal) if it wasn't provided. + * + * @default - a new Role will be created + */ + readonly role?: iam.IRole; + + /** + * Many resources allow passing in an optional S3 Bucket. + * Buckets can also have KMS Keys associated with them, + * so any encryption settings in your resource should check + * for the presence of that property on the passed Bucket. + * + * @default - no Bucket will be used + */ + readonly bucket?: s3.IBucket; + + /** + * Many resources can be attached to a VPC. + * If your resource cannot function without a VPC, + * make this property required - + * do NOT make it optional, and then create a VPC implicitly! + * This is different than what we do for IAM Roles, for example. + * + * @default - no VPC will be used + */ + readonly vpc?: ec2.IVpc; + + /** + * Whenever you have IVpc as a property, + * like we have in {@link vpc}, + * you need to provide an optional property of type ec2.SubnetSelection, + * which can be used to specify which subnets of the VPC should the resource use. + * The default is usually all private subnets, + * however you can change that default in your resource if it makes sense + * (for example, to all public subnets). + * + * @default - default subnet selection strategy, see the EC2 module for details + */ + readonly vpcSubnets?: ec2.SubnetSelection; + + /** + * If your resource interface extends ec2.IConnectable, + * that means it needs security groups to control traffic coming to and from it. + * Allow the customer to specify these security groups. + * If none were specified, we will create a new one implicitly, + * similarly like we do for IAM Roles. + * + * **Note**: a few resources in the CDK only allow you to provide a single SecurityGroup. + * This is generally considered a historical mistake, + * and all new code should allow an array of security groups to be passed. + * + * @default - a new security group will be created + */ + readonly securityGroups?: ec2.ISecurityGroup[]; + + /** + * What to do when this resource is deleted from a stack. + * Some stateful resources cannot be deleted if they have any contents + * (S3 Buckets are the canonical example), + * so we set their deletion policy to RETAIN by default. + * If your resource also behaves like that, + * you need to allow your customers to override this behavior if they need to. + * + * @default RemovalPolicy.RETAIN + */ + readonly removalPolicy?: core.RemovalPolicy; +} + +/** + * The actual L2 class for the ExampleResource. + * Extends ExampleResourceBase. + * Represents a resource completely managed by the CDK, and thus mutable. + * You can add additional methods to the public API of this class not present in {@link IExampleResource}, + * although you should strive to minimize that as much as possible, + * and have the entire API available in {@link IExampleResource} + * (but perhaps some of it not having any effect, + * like {@link IExampleResource.addToRolePolicy}). + * + * Usually, the CDK is able to figure out what's the equivalent CloudFormation resource for this L2, + * but sometimes (like in this example), we need to specify it explicitly. + * You do it with the '@resource' annotation: + * + * @resource AWS::CloudFormation::WaitConditionHandle + */ +export class ExampleResource extends ExampleResourceBase { + /** + * Reference an existing ExampleResource, + * defined outside of the CDK code, by name. + * + * The class might contain more methods for referencing an existing resource, + * like fromExampleResourceArn, + * or fromExampleResourceAttributes + * (the last one if you want the importing behavior to be more customizable). + */ + public static fromExampleResourceName(scope: core.Construct, id: string, exampleResourceName: string): IExampleResource { + // Imports are almost always implemented as a module-private + // inline class in the method itself. + // We extend ExampleResourceBase to reuse all of the logic inside it. + class Import extends ExampleResourceBase { + // we don't have an associated Role in this case + public readonly role = undefined; + // for imported resources, you always use the UnknownPrincipal, + // which ignores all modifications + public readonly grantPrincipal = new iam.UnknownPrincipal({ resource: this }); + + public readonly exampleResourceName = exampleResourceName; + // Since we have the name, we have to generate the ARN, + // using the Stack.formatArn helper method from the core library. + // We have to know the ARN components of ExampleResource in a few places, so, + // to avoid duplication, extract that into a module-private function + public readonly exampleResourceArn = core.Stack.of(scope) + .formatArn(exampleResourceArnComponents(exampleResourceName)); + } + + return new Import(scope, id); + } + + // implement all fields that are abstract in ExampleResourceBase + public readonly exampleResourceArn: string; + public readonly exampleResourceName: string; + // while we know 'role' will actually never be undefined in this class, + // JSII does not allow changing the optionality of a field + // when overriding it, so it has to be 'role?' + public readonly role?: iam.IRole; + public readonly grantPrincipal: iam.IPrincipal; + + /** + * The constructor of a construct has always 3 arguments: + * the parent Construct, the string identifier, + * locally unique within the scope of the parent, + * and a properties struct. + * + * If the props only have optional properties, like in our case, + * make sure to add a default value of an empty object to the props argument. + */ + constructor(scope: core.Construct, id: string, props: ExampleResourceProps = {}) { + // Call the constructor from Resource superclass, + // which attaches this construct to the construct tree. + super(scope, id, { + // You need to let the Resource superclass know which of your properties + // signifies the resource's physical name. + // If your resource doesn't have a physical name, + // don't set this property. + // For more information on what exactly is a physical name, + // see the CDK guide: https://docs.aws.amazon.com/cdk/latest/guide/resources.html#resources_physical_names + physicalName: props.waitConditionHandleName, + }); + + // We often add validations for properties, + // so that customers receive feedback about incorrect properties + // sooner than a CloudFormation deployment. + // However, when validating string (and number!) properties, + // it's important to remember that the value can be a CFN function + // (think a { Ref: ParameterName } expression in CloudFormation), + // and that sort of value would be also encoded as a string; + // so, we need to use the Token.isUnresolved() method from the core library + // to skip validation in that case. + if (props.waitConditionHandleName !== undefined && + !core.Token.isUnresolved(props.waitConditionHandleName) && + !/^[_a-zA-Z]+$/.test(props.waitConditionHandleName)) { + throw new Error('waitConditionHandleName must be non-empty and contain only letters and underscores, ' + + `got: '${props.waitConditionHandleName}'`); + } + + // Inside the implementation of the L2, + // we very often use L1 classes (those whose names begin with 'Cfn'). + // However, it's important we don't 'leak' that fact to the API of the L2 class - + // so, we should never take L1 types as inputs in our props, + // and we should not surface any L1 classes in public fields or methods of the class. + // The 'Cfn*' class is purely an implementation detail. + + // If this was a real resource, we would use a specific L1 for that resource + // (like a CfnBucket inside the Bucket class), + // but since this is just an example, + // we'll use CloudFormation wait conditions. + + // Remember to always, always, pass 'this' as the first argument + // when creating any constructs inside your L2s! + // This guarantees that they get scoped correctly, + // and the CDK will make sure their locally-unique identifiers + // are globally unique, which makes your L2 compose. + const waitConditionHandle = new core.CfnWaitConditionHandle(this, 'WaitConditionHandle'); + + // The 'main' L1 you create should always have the logical ID 'Resource'. + // This is important, so that the ConstructNode.defaultChild method works correctly. + // The local variable representing the L1 is often called 'resource' as well. + const resource = new core.CfnWaitCondition(this, 'Resource', { + count: 0, + handle: waitConditionHandle.ref, + timeout: '10', + }); + + // The resource's physical name and ARN are set using + // some protected methods from the Resource superclass + // that correctly resolve when your L2 is used in another resource + // that is in a different AWS region or account than this one. + this.exampleResourceName = this.getResourceNameAttribute( + // A lot of the CloudFormation resources return their physical name + // when the Ref function is used on them. + // If your resource is like that, simply pass 'resource.ref' here. + // However, if Ref for your resource returns something else, + // it's often still possible to use CloudFormation functions to get out the physical name; + // for example, if Ref for your resource returns the ARN, + // and the ARN for your resource is of the form 'arn:aws::::resource/physical-name', + // which is quite common, + // you can use Fn::Select and Fn::Split to take out the part after the '/' from the ARN: + core.Fn.select(1, core.Fn.split('/', resource.ref)), + ); + this.exampleResourceArn = this.getResourceArnAttribute( + // A lot of the L1 classes have an 'attrArn' property - + // if yours does, use it here. + // However, if it doesn't, + // you can often formulate the ARN yourself, + // using the Stack.formatArn helper function. + // Here, we assume resource.ref returns the physical name of the resource. + core.Stack.of(this).formatArn(exampleResourceArnComponents(resource.ref)), + // always use the protected physicalName property for this second argument + exampleResourceArnComponents(this.physicalName)); + + // if a role wasn't passed, create one + const role = props.role || new iam.Role(this, 'Role', { + // of course, fill your correct service principal here + assumedBy: new iam.ServicePrincipal('cloudformation.amazonaws.com'), + }); + this.role = role; + // we need this to correctly implement the iam.IGrantable interface + this.grantPrincipal = role; + + // implement the ec2.IConnectable interface, + // by writing to the _connections field in ExampleResourceBase, + // if a VPC was passed in props + if (props.vpc) { + const securityGroups = (props.securityGroups ?? []).length === 0 + // no security groups were provided - create one + ? [new ec2.SecurityGroup(this, 'SecurityGroup', { + vpc: props.vpc, + })] + : props.securityGroups; + this._connections = new ec2.Connections({ securityGroups }); + + // this is how you would use the VPC inputs to fill a subnetIds property of an L1: + new ec2.CfnVPCEndpoint(this, 'VpcEndpoint', { + vpcId: props.vpc.vpcId, + serviceName: 'ServiceName', + subnetIds: props.vpc.selectSubnets(props.vpcSubnets).subnetIds, + }); + } + + // this is how you apply the removal policy + resource.applyRemovalPolicy(props.removalPolicy, { + // this is the default to apply if props.removalPolicy is undefined + default: core.RemovalPolicy.RETAIN, + }); + } +} diff --git a/packages/@aws-cdk/example-construct-library/lib/index.ts b/packages/@aws-cdk/example-construct-library/lib/index.ts new file mode 100644 index 0000000000000..7ab8c455fa2e9 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/lib/index.ts @@ -0,0 +1,9 @@ +// The index.ts files contains a list of files we want to +// include as part of the public API of this module. +// In general, all files including L2 classes will be listed here, +// while all files including only utility functions will be omitted from here. + +// obviously, the ExampleResource L2 should be exported +export * from './example-resource'; + +// notice that private/example-resource-common.ts is not exported! diff --git a/packages/@aws-cdk/example-construct-library/lib/private/example-resource-common.ts b/packages/@aws-cdk/example-construct-library/lib/private/example-resource-common.ts new file mode 100644 index 0000000000000..ec95e51fa4825 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/lib/private/example-resource-common.ts @@ -0,0 +1,18 @@ +import * as cdk from '@aws-cdk/core'; + +// This file contains utility functions used in the implementation of ExampleResource +// which we don't want to make part of the public API of this module +// (in fact, we can't, as JSII does not work for standalone functions!). +// So, while the functions are exported from this file, +// this file is not listed in index.ts, +// and so these functions are effectively 'module-private'. +// To make it clear that this file should not be exported, +// we place it in a subdirectory of lib called 'private'. + +export function exampleResourceArnComponents(exampleResourceName: string): cdk.ArnComponents { + return { + service: 'cloudformation', + resource: 'wait-condition', + resourceName: exampleResourceName, + }; +} diff --git a/packages/@aws-cdk/example-construct-library/package.json b/packages/@aws-cdk/example-construct-library/package.json new file mode 100644 index 0000000000000..31dd2522ddc41 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/package.json @@ -0,0 +1,97 @@ +{ + "name": "@aws-cdk/example-construct-library", + "private": true, + "version": "0.0.0", + "description": "An example CDK Construct Library that can serve as a template for creating new libraries", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.example.construct.library", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "cdk-example-construct-library" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.Example.Construct.Library", + "packageId": "Amazon.CDK.Example.Construct.Library", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.example-construct-library", + "module": "aws_cdk.example_construct_library" + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/example-construct-library" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "build+test": "npm run build && npm test", + "build+test+package": "npm run build+test && npm run package", + "compat": "cdk-compat" + }, + "keywords": [ + "aws", + "cdk", + "example", + "construct", + "library" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assert": "0.0.0", + "cdk-build-tools": "0.0.0", + "cdk-integ-tools": "0.0.0", + "jest": "^25.5.3", + "pkglint": "0.0.0" + }, + "dependencies": { + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-events": "0.0.0", + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.0.2" + }, + "homepage": "https://github.com/aws/aws-cdk", + "peerDependencies": { + "@aws-cdk/aws-cloudwatch": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-events": "0.0.0", + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.0.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "jest": {}, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + } +} diff --git a/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts b/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts new file mode 100644 index 0000000000000..5dcab5f1a8288 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/test/example-resource.test.ts @@ -0,0 +1,204 @@ +/* + * We write unit tests using the Jest framework + * (some modules might still use NodeUnit, + * but it's considered legacy, and we want to migrate to Jest). + */ + +// import the various CDK assertion helpers +import { ABSENT, ResourcePart } from '@aws-cdk/assert'; +// always import our Jest-specific helpers +import '@aws-cdk/assert/jest'; + +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as iam from '@aws-cdk/aws-iam'; +import * as core from '@aws-cdk/core'; +// Always import the module you're testing qualified - +// don't import individual classes from it! +// Importing it qualified tests whether everything that needs to be exported +// from the module is. +import * as er from '../lib'; + +/* We allow quotes in the object keys used for CloudFormation template assertions */ +// tslint:disable:object-literal-key-quotes + +describe('Example Resource', () => { + let stack: core.Stack; + + beforeEach(() => { + // try to factor out as much boilerplate test setup to before methods - + // makes the tests much more readable + stack = new core.Stack(); + }); + + describe('created with default properties', () => { + let exampleResource: er.IExampleResource; + + beforeEach(() => { + exampleResource = new er.ExampleResource(stack, 'ExampleResource'); + }); + + test('creates a CFN WaitConditionHandle resource', () => { + // you can simply assert that a resource of a given type + // was generated in the resulting template + expect(stack).toHaveResource('AWS::CloudFormation::WaitConditionHandle'); + }); + + describe('creates a CFN WaitCondition resource', () => { + test('with count = 0 and timeout = 10', () => { + // you can also assert the properties of the resulting resource + expect(stack).toHaveResource('AWS::CloudFormation::WaitCondition', { + 'Count': 0, + 'Timeout': '10', + 'Handle': { + // Don't be afraid of using the generated logical IDs in your tests! + // While they look random, they are actually only dependent on the + // path constructs have in the tree. + // Since changing logical IDs as the library changes actually causes + // problems for their customers (their CloudFormation resources will be replaced), + // it's good for the unit tests to verify that the logical IDs are stable. + 'Ref': 'ExampleResourceWaitConditionHandle9C53A8D3', + }, + // this is how you can check a given property is _not_ set + 'RandomProperty': ABSENT, + }); + }); + + test('with retention policy = Retain', () => { + // haveResource asserts _all_ properties of a resource, + // while haveResourceLike only those that you provide + expect(stack).toHaveResourceLike('AWS::CloudFormation::WaitCondition', { + 'DeletionPolicy': 'Retain', + 'UpdateReplacePolicy': 'Retain', + // by default, haveResource and haveResourceLike only assert the properties of a resource - + // here's how you make them look at the entire resource definition + }, ResourcePart.CompleteDefinition); + }); + }); + + test('returns true from addToResourcePolicy', () => { + const result = exampleResource.addToRolePolicy(new iam.PolicyStatement({ + actions: ['kms:*'], + resources: ['*'], + })); + + expect(result).toBe(true); + }); + + test('correctly adds s3:Get* permissions when grantRead() is called', () => { + const role = new iam.Role(stack, 'Role', { + assumedBy: new iam.AnyPrincipal(), + }); + + exampleResource.grantRead(role); + + expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + 'PolicyDocument': { + 'Statement': [ + { + 'Action': 's3:Get*', + 'Resource': { + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':cloudformation:', + { 'Ref': 'AWS::Region' }, + ':', + { 'Ref': 'AWS::AccountId' }, + ':wait-condition/', + { 'Ref': 'ExampleResourceAC53F4AE' }, + ]], + }, + }, + ], + }, + }); + }); + }); + + describe('created with a VPC', () => { + let exampleResource: er.IExampleResource; + let vpc: ec2.IVpc; + + beforeEach(() => { + vpc = new ec2.Vpc(stack, 'Vpc'); + exampleResource = new er.ExampleResource(stack, 'ExampleResource', { + vpc, + }); + }); + + test('allows manipulating its connections object', () => { + exampleResource.connections.allowToAnyIpv4(ec2.Port.allTcp()); + }); + + test('correctly fills out the subnetIds property of the created VPC endpoint', () => { + expect(stack).toHaveResourceLike('AWS::EC2::VPCEndpoint', { + 'SubnetIds': [ + { 'Ref': 'VpcPrivateSubnet1Subnet536B997A' }, + { 'Ref': 'VpcPrivateSubnet2Subnet3788AAA1' }, + ], + }); + }); + }); + + describe('imported by name', () => { + let exampleResource: er.IExampleResource; + + beforeEach(() => { + exampleResource = er.ExampleResource.fromExampleResourceName(stack, 'ExampleResource', + 'my-example-resource-name'); + }); + + test('has the same name as it was imported with', () => { + expect(exampleResource.exampleResourceName).toEqual('my-example-resource-name'); + }); + + test('renders the correct ARN for Example Resource', () => { + // We can't simply compare the value we get from exampleResource.exampleResourceArn, + // as it will contain unresolved late-bound values + // (what we in the CDK call Tokens). + // So, use a utility method on Stack that allows you to resolve those Tokens + // into their correct values. + const arn = stack.resolve(exampleResource.exampleResourceArn); + expect(arn).toEqual({ + 'Fn::Join': ['', [ + 'arn:', + { 'Ref': 'AWS::Partition' }, + ':cloudformation:', + { 'Ref': 'AWS::Region' }, + ':', + { 'Ref': 'AWS::AccountId' }, + ':wait-condition/my-example-resource-name', + ]], + }); + }); + + test('returns false from addToResourcePolicy', () => { + const result = exampleResource.addToRolePolicy(new iam.PolicyStatement({ + actions: ['kms:*'], + resources: ['*'], + })); + + expect(result).toEqual(false); + }); + }); + + test('cannot be created with a physical name containing illegal characters', () => { + // this is how we write tests that expect an exception to be thrown + expect(() => { + new er.ExampleResource(stack, 'ExampleResource', { + waitConditionHandleName: 'a-1234', + }); + // it's not enough to know an exception was thrown - + // we have to verify that its message is what we expected + }).toThrow(/waitConditionHandleName must be non-empty and contain only letters and underscores, got: 'a-1234'/); + }); + + test('does not fail validation if the physical name is a late-bound value', () => { + const parameter = new core.CfnParameter(stack, 'Parameter'); + + // no assertion necessary - the lack of an exception being thrown is all we need in this case + new er.ExampleResource(stack, 'ExampleResource', { + waitConditionHandleName: parameter.valueAsString, + }); + }); +}); diff --git a/packages/@aws-cdk/example-construct-library/test/integ.example-resource.expected.json b/packages/@aws-cdk/example-construct-library/test/integ.example-resource.expected.json new file mode 100644 index 0000000000000..c9e2f4bc4db5a --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/test/integ.example-resource.expected.json @@ -0,0 +1,36 @@ +{ + "Resources": { + "ExampleResourceWaitConditionHandle9C53A8D3": { + "Type": "AWS::CloudFormation::WaitConditionHandle" + }, + "ExampleResourceAC53F4AE": { + "Type": "AWS::CloudFormation::WaitCondition", + "Properties": { + "Count": 0, + "Handle": { + "Ref": "ExampleResourceWaitConditionHandle9C53A8D3" + }, + "Timeout": "10" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ExampleResourceRole0533653E": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "cloudformation.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/example-construct-library/test/integ.example-resource.ts b/packages/@aws-cdk/example-construct-library/test/integ.example-resource.ts new file mode 100644 index 0000000000000..93d082da24989 --- /dev/null +++ b/packages/@aws-cdk/example-construct-library/test/integ.example-resource.ts @@ -0,0 +1,25 @@ +/* + * Our integration tests act as snapshot tests to make sure the rendered template is stable. + * If any changes to the result are required, + * you need to perform an actual CloudFormation deployment of this application, + * and, if it is successful, a new snapshot will be written out. + * + * For more information on CDK integ tests, + * see the main CONTRIBUTING.md file. + */ + +import * as core from '@aws-cdk/core'; +// as in unit tests, we use a qualified import, +// not bring in individual classes +import * as er from '../lib'; + +const app = new core.App(); + +const stack = new core.Stack(app, 'ExampleResourceIntegTestStack'); + +new er.ExampleResource(stack, 'ExampleResource', { + // we don't want to leave trash in the account after running the deployment of this + removalPolicy: core.RemovalPolicy.DESTROY, +}); + +app.synth(); diff --git a/packages/@monocdk-experiment/assert/package.json b/packages/@monocdk-experiment/assert/package.json index 582adaaf07524..7b4ef8901ac8e 100644 --- a/packages/@monocdk-experiment/assert/package.json +++ b/packages/@monocdk-experiment/assert/package.json @@ -47,7 +47,7 @@ "cdk-build-tools": "0.0.0", "jest": "^25.5.4", "pkglint": "0.0.0", - "ts-jest": "^25.4.0", + "ts-jest": "^25.5.0", "@monocdk-experiment/rewrite-imports": "0.0.0", "monocdk-experiment": "0.0.0", "constructs": "^3.0.2" diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index 14ab1a2d04b98..0d3ffa82ba9ea 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -69,7 +69,8 @@ async function parseCommandLineArguments() { .option('execute', { type: 'boolean', desc: 'Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet)', default: true }) .option('force', { alias: 'f', type: 'boolean', desc: 'Always deploy stack even if templates are identical', default: false }) .option('parameters', { type: 'array', desc: 'Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE)', nargs: 1, requiresArg: true, default: {} }) - .option('outputs-file', { type: 'string', alias: 'O', desc: 'Path to file where stack outputs will be written as JSON', requiresArg: true }), + .option('outputs-file', { type: 'string', alias: 'O', desc: 'Path to file where stack outputs will be written as JSON', requiresArg: true }) + .option('previous-parameters', { type: 'boolean', default: true, desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)' }), ) .command('destroy [STACKS..]', 'Destroy the stack(s) named STACKS', yargs => yargs .option('exclusively', { type: 'boolean', alias: 'e', desc: 'Only destroy requested stacks, don\'t include dependees' }) @@ -243,6 +244,7 @@ async function initCommandLine() { execute: args.execute, force: args.force, parameters: parameterMap, + usePreviousParameters: args['previous-parameters'], outputsFile: args.outputsFile, }); diff --git a/packages/aws-cdk/lib/api/cloudformation-deployments.ts b/packages/aws-cdk/lib/api/cloudformation-deployments.ts index 65dc93616b4d6..d41e128793f97 100644 --- a/packages/aws-cdk/lib/api/cloudformation-deployments.ts +++ b/packages/aws-cdk/lib/api/cloudformation-deployments.ts @@ -77,6 +77,15 @@ export interface DeployStackOptions { * @default - no additional parameters will be passed to the template */ parameters?: { [name: string]: string | undefined }; + + /** + * Use previous values for unspecified parameters + * + * If not set, all parameters must be specified for every deployment. + * + * @default true + */ + usePreviousParameters?: boolean; } export interface DestroyStackOptions { @@ -138,6 +147,7 @@ export class CloudFormationDeployments { execute: options.execute, force: options.force, parameters: options.parameters, + usePreviousParameters: options.usePreviousParameters, }); } diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index e8d0a9ec09361..98f950bbd19bd 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -130,6 +130,15 @@ export interface DeployStackOptions { */ parameters?: { [name: string]: string | undefined }; + /** + * Use previous values for unspecified parameters + * + * If not set, all parameters must be specified for every deployment. + * + * @default true + */ + usePreviousParameters?: boolean; + /** * Deploy even if the deployed template is identical to the one we are about to deploy. * @default false @@ -170,7 +179,7 @@ export async function deployStack(options: DeployStackOptions): Promise { + public async getValue(args: cxschema.HostedZoneContextQuery): Promise { const account = args.account; const region = args.region; if (!this.isHostedZoneQuery(args)) { @@ -35,7 +36,7 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { private async filterZones( r53: AWS.Route53, zones: AWS.Route53.HostedZone[], - props: cxapi.HostedZoneContextQuery): Promise { + props: cxschema.HostedZoneContextQuery): Promise { let candidates: AWS.Route53.HostedZone[] = []; const domainName = props.domainName.endsWith('.') ? props.domainName : `${props.domainName}.`; @@ -64,7 +65,7 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { return candidates; } - private isHostedZoneQuery(props: cxapi.HostedZoneContextQuery | any): props is cxapi.HostedZoneContextQuery { - return (props as cxapi.HostedZoneContextQuery).domainName !== undefined; + private isHostedZoneQuery(props: cxschema.HostedZoneContextQuery | any): props is cxschema.HostedZoneContextQuery { + return (props as cxschema.HostedZoneContextQuery).domainName !== undefined; } } diff --git a/packages/aws-cdk/lib/context-providers/index.ts b/packages/aws-cdk/lib/context-providers/index.ts index b582c5789939e..4e5b4063b826e 100644 --- a/packages/aws-cdk/lib/context-providers/index.ts +++ b/packages/aws-cdk/lib/context-providers/index.ts @@ -54,9 +54,9 @@ export function registerContextProvider(name: string, provider: ProviderConstruc } const availableContextProviders: ProviderMap = { - [cxapi.AVAILABILITY_ZONE_PROVIDER]: AZContextProviderPlugin, - [cxapi.SSM_PARAMETER_PROVIDER]: SSMContextProviderPlugin, - [cxapi.HOSTED_ZONE_PROVIDER]: HostedZoneContextProviderPlugin, - [cxapi.VPC_PROVIDER]: VpcNetworkContextProviderPlugin, - [cxapi.AMI_PROVIDER]: AmiContextProviderPlugin, + [cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER]: AZContextProviderPlugin, + [cxschema.ContextProvider.SSM_PARAMETER_PROVIDER]: SSMContextProviderPlugin, + [cxschema.ContextProvider.HOSTED_ZONE_PROVIDER]: HostedZoneContextProviderPlugin, + [cxschema.ContextProvider.VPC_PROVIDER]: VpcNetworkContextProviderPlugin, + [cxschema.ContextProvider.AMI_PROVIDER]: AmiContextProviderPlugin, }; diff --git a/packages/aws-cdk/lib/context-providers/ssm-parameters.ts b/packages/aws-cdk/lib/context-providers/ssm-parameters.ts index 25fb21215e1fb..79558a89ff4bf 100644 --- a/packages/aws-cdk/lib/context-providers/ssm-parameters.ts +++ b/packages/aws-cdk/lib/context-providers/ssm-parameters.ts @@ -1,3 +1,4 @@ +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import * as AWS from 'aws-sdk'; import { Mode, SdkProvider } from '../api'; @@ -11,7 +12,7 @@ export class SSMContextProviderPlugin implements ContextProviderPlugin { constructor(private readonly aws: SdkProvider) { } - public async getValue(args: {[key: string]: any}) { + public async getValue(args: cxschema.SSMParameterContextQuery) { const region = args.region; const account = args.account; if (!('parameterName' in args)) { diff --git a/packages/aws-cdk/lib/context-providers/vpcs.ts b/packages/aws-cdk/lib/context-providers/vpcs.ts index 058e81b6c8b18..a2b3dec92eedf 100644 --- a/packages/aws-cdk/lib/context-providers/vpcs.ts +++ b/packages/aws-cdk/lib/context-providers/vpcs.ts @@ -1,3 +1,4 @@ +import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import * as AWS from 'aws-sdk'; import { Mode, SdkProvider } from '../api'; @@ -9,7 +10,7 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { constructor(private readonly aws: SdkProvider) { } - public async getValue(args: cxapi.VpcContextQuery) { + public async getValue(args: cxschema.VpcContextQuery) { const account: string = args.account!; const region: string = args.region!; @@ -20,7 +21,7 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { return await this.readVpcProps(ec2, vpcId, args); } - private async findVpc(ec2: AWS.EC2, args: cxapi.VpcContextQuery): Promise { + private async findVpc(ec2: AWS.EC2, args: cxschema.VpcContextQuery): Promise { // Build request filter (map { Name -> Value } to list of [{ Name, Values }]) const filters: AWS.EC2.Filter[] = Object.entries(args.filter).map(([tag, value]) => ({ Name: tag, Values: [value] })); @@ -38,7 +39,7 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { return vpcs[0]; } - private async readVpcProps(ec2: AWS.EC2, vpc: AWS.EC2.Vpc, args: cxapi.VpcContextQuery): Promise { + private async readVpcProps(ec2: AWS.EC2, vpc: AWS.EC2.Vpc, args: cxschema.VpcContextQuery): Promise { const vpcId = vpc.VpcId!; debug(`Describing VPC ${vpcId}`); diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index 534bafb6de5ad..d614cbda6f6a9 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -17,9 +17,11 @@ "package": "cdk-package", "build+test+package": "npm run build+test && npm run package", "build+test": "npm run build && npm test", - "integ-cli": "scripts/integ-cli.sh", - "integ-cli-regression": "scripts/integ-cli-regression.sh", - "integ-cli-no-regression": "scripts/integ-cli-no-regression.sh", + "integ-cli": "npm run integ-cli-regression && npm run integ-cli-no-regression", + "integ-cli-regression": "npm run integ-cli-regression-latest-release && npm run integ-cli-regression-latest-code", + "integ-cli-regression-latest-release": "test/integ/run-against-repo test/integ/test-cli-regression-against-latest-release.sh", + "integ-cli-regression-latest-code": "test/integ/run-against-repo test/integ/test-cli-regression-against-current-code.sh", + "integ-cli-no-regression": "test/integ/run-against-repo test/integ/cli/test.sh", "integ-init": "test/integ/run-against-dist test/integ/init/test-all.sh" }, "cdk-build": { @@ -58,7 +60,7 @@ "mockery": "^2.1.0", "pkglint": "0.0.0", "sinon": "^9.0.2", - "ts-jest": "^25.4.0", + "ts-jest": "^25.5.0", "ts-mock-imports": "^1.2.6" }, "dependencies": { @@ -68,7 +70,7 @@ "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/region-info": "0.0.0", "archiver": "^4.0.1", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "camelcase": "^6.0.0", "cdk-assets": "0.0.0", "colors": "^1.4.0", diff --git a/packages/aws-cdk/scripts/integ-cli-no-regression.sh b/packages/aws-cdk/scripts/integ-cli-no-regression.sh deleted file mode 100755 index f8ffea80888f7..0000000000000 --- a/packages/aws-cdk/scripts/integ-cli-no-regression.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -# -# Run only local integration tests. -# -set -eu - -scriptdir=$(cd $(dirname $0) && pwd) - -echo "Running local integration tests" -./test/integ/run-against-repo test/integ/cli/test.sh diff --git a/packages/aws-cdk/scripts/integ-cli-regression.sh b/packages/aws-cdk/scripts/integ-cli-regression.sh deleted file mode 100755 index 7b281264a637f..0000000000000 --- a/packages/aws-cdk/scripts/integ-cli-regression.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# -# Run only local integration tests. -# -set -eu - -scriptdir=$(cd $(dirname $0) && pwd) -repo_root=$(realpath ${scriptdir}/..) - -echo "Running regression tests against local code" -${repo_root}/test/integ/run-against-repo ${repo_root}/test/integ/test-cli-regression-against-current-code.sh - -echo "Running regression tests against local CLI and published framework" -${repo_root}/test/integ/run-against-repo ${repo_root}/test/integ/test-cli-regression-against-latest-release.sh \ No newline at end of file diff --git a/packages/aws-cdk/scripts/integ-cli.sh b/packages/aws-cdk/scripts/integ-cli.sh deleted file mode 100755 index 5307cf15336b7..0000000000000 --- a/packages/aws-cdk/scripts/integ-cli.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -# -# Run both local integration tests and regression tests. -# -set -eu - -scriptdir=$(cd $(dirname $0) && pwd) - -${scriptdir}/integ-cli-no-regression.sh -${scriptdir}/integ-cli-regression.sh diff --git a/packages/aws-cdk/test/api/cloud-executable.test.ts b/packages/aws-cdk/test/api/cloud-executable.test.ts index b60d712401f45..3e9dc83948c23 100644 --- a/packages/aws-cdk/test/api/cloud-executable.test.ts +++ b/packages/aws-cdk/test/api/cloud-executable.test.ts @@ -49,7 +49,7 @@ describe('AWS::CDK::Metadata', () => { }); test('stop executing if context providers are not making progress', async () => { - registerContextProvider('testprovider', class { + registerContextProvider(cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER, class { public async getValue(_: { [key: string]: any }): Promise { return 'foo'; } @@ -62,7 +62,7 @@ test('stop executing if context providers are not making progress', async () => }], // Always return the same missing keys, synthesis should still finish. missing: [ - { key: 'abcdef', props: {}, provider: 'testprovider' }, + { key: 'abcdef', props: { account: '1324', region: 'us-east-1' }, provider: cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER }, ], }); const cxasm = await cloudExecutable.synthesize(); diff --git a/packages/aws-cdk/test/api/deploy-stack.test.ts b/packages/aws-cdk/test/api/deploy-stack.test.ts index cb88c38def3a0..913394ea72d5b 100644 --- a/packages/aws-cdk/test/api/deploy-stack.test.ts +++ b/packages/aws-cdk/test/api/deploy-stack.test.ts @@ -9,6 +9,17 @@ const FAKE_STACK = testStack({ template: FAKE_TEMPLATE, }); +const FAKE_STACK_WITH_PARAMETERS = testStack({ + stackName: 'withparameters', + template: { + Parameters: { + HasValue: { Type: 'String' }, + HasDefault: { Type: 'String', Default: 'TheDefault' }, + OtherParameter: { Type: 'String' }, + }, + }, +}); + const FAKE_STACK_TERMINATION_PROTECTION = testStack({ stackName: 'termination-protection', template: FAKE_TEMPLATE, @@ -84,6 +95,88 @@ test('correctly passes CFN parameters, ignoring ones with empty values', async ( })); }); +test('reuse previous parameters if requested', async () => { + // GIVEN + givenStackExists({ + Parameters: [ + { ParameterKey: 'HasValue', ParameterValue: 'TheValue' }, + { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' }, + ], + }); + + // WHEN + await deployStack({ + stack: FAKE_STACK_WITH_PARAMETERS, + sdk, + sdkProvider, + resolvedEnvironment: mockResolvedEnvironment(), + parameters: { + OtherParameter: 'SomeValue', + }, + usePreviousParameters: true, + }); + + // THEN + expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ + Parameters: [ + { ParameterKey: 'HasValue', UsePreviousValue: true }, + { ParameterKey: 'HasDefault', UsePreviousValue: true }, + { ParameterKey: 'OtherParameter', ParameterValue: 'SomeValue' }, + ], + })); +}); + +test('do not reuse previous parameters if not requested', async () => { + // GIVEN + givenStackExists({ + Parameters: [ + { ParameterKey: 'HasValue', ParameterValue: 'TheValue' }, + { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' }, + ], + }); + + // WHEN + await deployStack({ + stack: FAKE_STACK_WITH_PARAMETERS, + sdk, + sdkProvider, + resolvedEnvironment: mockResolvedEnvironment(), + parameters: { + HasValue: 'SomeValue', + OtherParameter: 'SomeValue', + }, + }); + + // THEN + expect(cfnMocks.createChangeSet).toHaveBeenCalledWith(expect.objectContaining({ + Parameters: [ + { ParameterKey: 'HasValue', ParameterValue: 'SomeValue' }, + { ParameterKey: 'OtherParameter', ParameterValue: 'SomeValue' }, + ], + })); +}); + +test('throw exception if not enough parameters supplied', async () => { + // GIVEN + givenStackExists({ + Parameters: [ + { ParameterKey: 'HasValue', ParameterValue: 'TheValue' }, + { ParameterKey: 'HasDefault', ParameterValue: 'TheOldValue' }, + ], + }); + + // WHEN + await expect(deployStack({ + stack: FAKE_STACK_WITH_PARAMETERS, + sdk, + sdkProvider, + resolvedEnvironment: mockResolvedEnvironment(), + parameters: { + OtherParameter: 'SomeValue', + }, + })).rejects.toThrow(/CloudFormation Parameters are missing a value/); +}); + test('deploy is skipped if template did not change', async () => { // GIVEN givenStackExists(); diff --git a/packages/aws-cdk/test/context-providers/asymmetric-vpcs.test.ts b/packages/aws-cdk/test/context-providers/asymmetric-vpcs.test.ts index 8b5534c2c4710..36c451269adbb 100644 --- a/packages/aws-cdk/test/context-providers/asymmetric-vpcs.test.ts +++ b/packages/aws-cdk/test/context-providers/asymmetric-vpcs.test.ts @@ -29,6 +29,8 @@ test('looks up the requested (symmetric) VPC', async () => { }); const result = await new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, }); @@ -83,6 +85,8 @@ test('throws when no such VPC is found', async () => { }); await expect(new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, })).rejects.toThrow(/Could not find any VPCs matching/); @@ -97,6 +101,8 @@ test('throws when multiple VPCs are found', async () => { // WHEN await expect(new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, })).rejects.toThrow(/Found 2 VPCs matching/); @@ -116,6 +122,8 @@ test('uses the VPC main route table when a subnet has no specific association', }); const result = await new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, }); @@ -199,6 +207,8 @@ test('Recognize public subnet by route table', async () => { // WHEN const result = await new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, }); @@ -251,6 +261,8 @@ test('works for asymmetric subnets (not spanning the same Availability Zones)', // WHEN const result = await new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, }); @@ -338,6 +350,8 @@ test('allows specifying the subnet group name tag', async () => { }); const result = await new VpcNetworkContextProviderPlugin(mockSDK).getValue({ + account: '1234', + region: 'us-east-1', filter: { foo: 'bar' }, returnAsymmetricSubnets: true, subnetGroupNameTag: 'Tier', diff --git a/packages/aws-cdk/test/context-providers/generic.test.ts b/packages/aws-cdk/test/context-providers/generic.test.ts index 70d09e4a8e4e5..35f8c85da83e6 100644 --- a/packages/aws-cdk/test/context-providers/generic.test.ts +++ b/packages/aws-cdk/test/context-providers/generic.test.ts @@ -4,9 +4,11 @@ import { MockSdkProvider } from '../util/mock-sdk'; const mockSDK = new MockSdkProvider(); +const TEST_PROVIDER: any = 'testprovider'; + test('errors are reported into the context value', async () => { // GIVEN - contextproviders.registerContextProvider('testprovider', class { + contextproviders.registerContextProvider(TEST_PROVIDER, class { public async getValue(_: {[key: string]: any}): Promise { throw new Error('Something went wrong'); } @@ -15,7 +17,7 @@ test('errors are reported into the context value', async () => { // WHEN await contextproviders.provideContextValues([ - { key: 'asdf', props: {}, provider: 'testprovider' }, + { key: 'asdf', props: { account: '1234', region: 'us-east-1' }, provider: TEST_PROVIDER }, ], context, mockSDK); // THEN - error is now in context @@ -27,7 +29,7 @@ test('errors are reported into the context value', async () => { test('errors are marked transient', async () => { // GIVEN - contextproviders.registerContextProvider('testprovider', class { + contextproviders.registerContextProvider(TEST_PROVIDER, class { public async getValue(_: {[key: string]: any}): Promise { throw new Error('Something went wrong'); } @@ -36,7 +38,7 @@ test('errors are marked transient', async () => { // WHEN await contextproviders.provideContextValues([ - { key: 'asdf', props: {}, provider: 'testprovider' }, + { key: 'asdf', props: { account: '1234', region: 'us-east-1' }, provider: TEST_PROVIDER }, ], context, mockSDK); // THEN - error is marked transient diff --git a/packages/aws-cdk/test/context-providers/vpcs.test.ts b/packages/aws-cdk/test/context-providers/vpcs.test.ts index 3dbef6494845f..f9159b1bc89f0 100644 --- a/packages/aws-cdk/test/context-providers/vpcs.test.ts +++ b/packages/aws-cdk/test/context-providers/vpcs.test.ts @@ -33,7 +33,11 @@ test('looks up the requested VPC', async () => { }); // WHEN - const result = await provider.getValue({ filter }); + const result = await provider.getValue({ + account: '1234', + region: 'us-east-1', + filter, + }); // THEN expect(result).toEqual({ @@ -65,7 +69,11 @@ test('throws when no such VPC is found', async () => { }); // WHEN - await expect(provider.getValue({ filter })).rejects.toThrow(/Could not find any VPCs matching/); + await expect(provider.getValue({ + account: '1234', + region: 'us-east-1', + filter, + })).rejects.toThrow(/Could not find any VPCs matching/); }); test('throws when multiple VPCs are found', async () => { @@ -79,7 +87,11 @@ test('throws when multiple VPCs are found', async () => { }); // WHEN - await expect(provider.getValue({ filter })).rejects.toThrow(/Found 2 VPCs matching/); + await expect(provider.getValue({ + account: '1234', + region: 'us-east-1', + filter, + })).rejects.toThrow(/Found 2 VPCs matching/); }); test('uses the VPC main route table when a subnet has no specific association', async () => { @@ -100,7 +112,11 @@ test('uses the VPC main route table when a subnet has no specific association', }); // WHEN - const result = await provider.getValue({ filter }); + const result = await provider.getValue({ + account: '1234', + region: 'us-east-1', + filter, + }); // THEN expect(result).toEqual({ @@ -159,7 +175,11 @@ test('Recognize public subnet by route table', async () => { }); // WHEN - const result = await provider.getValue({ filter }); + const result = await provider.getValue({ + account: '1234', + region: 'us-east-1', + filter, + }); // THEN expect(result).toEqual({ diff --git a/packages/aws-cdk/test/integ/cli.exclusions.js b/packages/aws-cdk/test/integ/cli.exclusions.js index 6c9d25a778e4c..4204b62bd527c 100644 --- a/packages/aws-cdk/test/integ/cli.exclusions.js +++ b/packages/aws-cdk/test/integ/cli.exclusions.js @@ -16,20 +16,20 @@ For example: */ const exclusions = [ { - "test": "test-cdk-deploy-with-parameters.sh", - "version": "v1.31.0", - "justification": "This test doesn't use a unique sns topic name and it collides with our regular integ suite" + "test": "test-cdk-deploy-nested-stack-with-parameters.sh", + "version": "v1.37.0", + "justification": "This test doesn't use a unique sns topic name for the topic in the nested stack and it collides with our regular integ suite" }, { - "test": "test-cdk-deploy-wildcard-with-parameters.sh", - "version": "v1.31.0", + "test": "test-cdk-deploy-wildcard-with-outputs.sh", + "version": "v1.37.0", "justification": "This test doesn't use a unique sns topic name and it collides with our regular integ suite" }, { - "test": "test-cdk-deploy-nested-stack-with-parameters.sh", - "version": "v1.31.0", + "test": "test-cdk-deploy-with-outputs.sh", + "version": "v1.37.0", "justification": "This test doesn't use a unique sns topic name and it collides with our regular integ suite" - } + } ] function getExclusion(test, version) { diff --git a/packages/aws-cdk/test/integ/cli/app/app.js b/packages/aws-cdk/test/integ/cli/app/app.js index 0344c834d0a1c..33e2802ad2ac7 100644 --- a/packages/aws-cdk/test/integ/cli/app/app.js +++ b/packages/aws-cdk/test/integ/cli/app/app.js @@ -46,7 +46,7 @@ class ParameterStack extends cdk.Stack { super(parent, id, props); new sns.Topic(this, 'TopicParameter', { - topicName: new cdk.CfnParameter(this, 'TopicNameParam') + topicName: new cdk.CfnParameter(this, 'TopicNameParam').valueAsString }); } } @@ -56,7 +56,7 @@ class OtherParameterStack extends cdk.Stack { super(parent, id, props); new sns.Topic(this, 'TopicParameter', { - topicName: new cdk.CfnParameter(this, 'OtherTopicNameParam') + topicName: new cdk.CfnParameter(this, 'OtherTopicNameParam').valueAsString }); } } @@ -66,10 +66,10 @@ class MultiParameterStack extends cdk.Stack { super(parent, id, props); new sns.Topic(this, 'TopicParameter', { - displayName: new cdk.CfnParameter(this, 'DisplayNameParam') + displayName: new cdk.CfnParameter(this, 'DisplayNameParam').valueAsString }); new sns.Topic(this, 'OtherTopicParameter', { - displayName: new cdk.CfnParameter(this, 'OtherDisplayNameParam') + displayName: new cdk.CfnParameter(this, 'OtherDisplayNameParam').valueAsString }); } } @@ -79,7 +79,7 @@ class OutputsStack extends cdk.Stack { super(parent, id, props); const topic = new sns.Topic(this, 'MyOutput', { - topicName: 'MyTopic' + topicName: `${cdk.Stack.of(this).stackName}MyTopic` }); new cdk.CfnOutput(this, 'TopicName', { @@ -93,7 +93,7 @@ class AnotherOutputsStack extends cdk.Stack { super(parent, id, props); const topic = new sns.Topic(this, 'MyOtherOutput', { - topicName: 'MyOtherTopic' + topicName: `${cdk.Stack.of(this).stackName}MyOtherTopic` }); new cdk.CfnOutput(this, 'TopicName', { diff --git a/packages/aws-cdk/test/integ/cli/app/nested-stack.js b/packages/aws-cdk/test/integ/cli/app/nested-stack.js index 98202ee4520e5..3b3125963679b 100644 --- a/packages/aws-cdk/test/integ/cli/app/nested-stack.js +++ b/packages/aws-cdk/test/integ/cli/app/nested-stack.js @@ -20,9 +20,9 @@ class MyNestedStack extends cfn.NestedStack { class StackWithNestedStackUsingParameters extends Stack { constructor(scope, id) { super(scope, id); - new CfnParameter(this, 'MyTopicParam'); + const topicNameParam = new CfnParameter(this, 'MyTopicParam'); new MyNestedStackUsingParameters(this, 'MyNested', { - parameters: {'MyTopicParam': 'ThereIsASpoon'} + parameters: {'MyTopicParam': topicNameParam.valueAsString} }); } } diff --git a/packages/aws-cdk/test/integ/cli/cdk-deploy-wildcard-with-outputs-expected.template b/packages/aws-cdk/test/integ/cli/cdk-deploy-wildcard-with-outputs-expected.template index 6097801be8035..6e682e2a96d4c 100644 --- a/packages/aws-cdk/test/integ/cli/cdk-deploy-wildcard-with-outputs-expected.template +++ b/packages/aws-cdk/test/integ/cli/cdk-deploy-wildcard-with-outputs-expected.template @@ -1,8 +1,8 @@ { "%STACK_NAME_PREFIX%-outputs-test-1": { - "TopicName": "MyTopic" + "TopicName": "%STACK_NAME_PREFIX%-outputs-test-1MyTopic" }, "%STACK_NAME_PREFIX%-outputs-test-2": { - "TopicName": "MyOtherTopic" + "TopicName": "%STACK_NAME_PREFIX%-outputs-test-2MyOtherTopic" } } \ No newline at end of file diff --git a/packages/aws-cdk/test/integ/cli/cdk-deploy-with-outputs-expected.template b/packages/aws-cdk/test/integ/cli/cdk-deploy-with-outputs-expected.template index 972c4eaa725ff..47b2f6e574e17 100644 --- a/packages/aws-cdk/test/integ/cli/cdk-deploy-with-outputs-expected.template +++ b/packages/aws-cdk/test/integ/cli/cdk-deploy-with-outputs-expected.template @@ -1,5 +1,5 @@ { "%STACK_NAME_PREFIX%-outputs-test-1": { - "TopicName": "MyTopic" + "TopicName": "%STACK_NAME_PREFIX%-outputs-test-1MyTopic" } } diff --git a/packages/aws-cdk/test/integ/run-against-dist b/packages/aws-cdk/test/integ/run-against-dist index eebf758ec2823..3b314abc0e2c4 100755 --- a/packages/aws-cdk/test/integ/run-against-dist +++ b/packages/aws-cdk/test/integ/run-against-dist @@ -23,15 +23,9 @@ if [[ ! -f $dist_root/build.json ]]; then exit 1 fi -local_cli_version="$(node -e "console.log(require('${dist_root}/build.json').version)")" serve_npm_packages -# Install the CLI and put it on the path -(cd $npmws && npm install aws-cdk@${local_cli_version}) -export PATH=$npmws/node_modules/.bin:$PATH - -verify_installed_cli_version ${local_cli_version} prepare_java_packages prepare_nuget_packages prepare_python_packages diff --git a/packages/aws-cdk/test/integ/run-against-dist.bash b/packages/aws-cdk/test/integ/run-against-dist.bash index f20c3d65a8676..a082de222af29 100644 --- a/packages/aws-cdk/test/integ/run-against-dist.bash +++ b/packages/aws-cdk/test/integ/run-against-dist.bash @@ -21,61 +21,43 @@ function serve_npm_packages() { return 1 fi - if [ ! -z "${USE_PUBLISHED_FRAMEWORK_VERSION:-}" ]; then - - echo "Testing against latest published versions of the framework" + local_cli_version="$(node -e "console.log(require('${dist_root}/build.json').version)")" - # when using latest published framework, only - # install the cli and its dependencies. + tarballs_glob="$dist_root/js/*.tgz" - cli_root=./package - - version=$(node -p "require('${cli_root}/package.json').version") + if [ ! -z "${USE_PUBLISHED_FRAMEWORK_VERSION:-}" ]; then - # good lord - echo "Fetching @aws-cdk CLI dependencies from package.json" - cli_deps=$(node -p "Object.entries(require('${cli_root}/package.json').dependencies).filter(x => x[0].includes('@aws-cdk')).map(x => x[0].replace('@aws-cdk/', '')).join(' ')") + echo "Testing against latest published versions of the framework" - # tarballs_glob is going to look like "{file,file,...}" - tarballs_glob="{$dist_root/js/aws-cdk-${version}.tgz" + header "Installing aws-cdk from local tarballs..." + (cd ${npmws} && npx serve-npm-tarballs --glob "${tarballs_glob}" -- npm install aws-cdk@${local_cli_version}) + export PATH=$npmws/node_modules/.bin:$PATH - for dep in ${cli_deps}; do - tarball=$dist_root/js/${dep}@${version}.jsii.tgz - if [ ! -f ${tarball} ]; then - # not a jsii dependency, the tarball is different... - tarball=$dist_root/js/aws-cdk-${dep}-${version}.tgz - fi + else - tarballs_glob="${tarballs_glob},${tarball}" - done + echo "Testing against local versions of the framework" - # manually add cdk-assets since its not prefixed with @aws-cdk and - # hence isn't picked up from package.json - echo "Adding cdk-assets to CLI dependencies" - tarballs_glob="${tarballs_glob},$dist_root/js/cdk-assets-${version}.tgz" + #------------------------------------------------------------------------------ + # Start a mock npm repository from the given tarballs + #------------------------------------------------------------------------------ + header "Starting local NPM Repository" - # manually add @aws-cdk/cfnspec since its a transitive dependency via @aws-cdk/cloudformation-diff - # hence isn't picked up from package.json - echo "Adding @aws-cdk/cfnspec to CLI dependencies" - tarballs_glob="${tarballs_glob},$dist_root/js/aws-cdk-cfnspec-${version}.tgz" + # When using '--daemon', 'npm install' first so the files are permanent, or + # 'npx' will remove them too soon. + npm install serve-npm-tarballs + eval $(npx serve-npm-tarballs --glob "${tarballs_glob}" --daemon) + trap "kill $SERVE_NPM_TARBALLS_PID" EXIT - tarballs_glob="${tarballs_glob}}" - else + header "Installing aws-cdk from local tarballs..." + (cd ${npmws} && npm install aws-cdk@${local_cli_version}) + export PATH=$npmws/node_modules/.bin:$PATH - echo "Testing against local versions of the framework" - tarballs_glob="$dist_root/js/*.tgz" fi - #------------------------------------------------------------------------------ - # Start a mock npm repository from the given tarballs - #------------------------------------------------------------------------------ - header "Starting local NPM Repository" + # a bit silly, but it verifies the PATH exports and just makes sure + # that we run 'cdk' commands we use the version we just installed. + verify_installed_cli_version ${local_cli_version} - # When using '--daemon', 'npm install' first so the files are permanent, or - # 'npx' will remove them too soon. - npm install serve-npm-tarballs - eval $(npx serve-npm-tarballs --glob "${tarballs_glob}" --daemon) - trap "kill $SERVE_NPM_TARBALLS_PID" EXIT } # Make sure that installed CLI matches the build version diff --git a/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh b/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh index 11ca5469d98a0..8ac522c91f48e 100755 --- a/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh +++ b/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh @@ -10,9 +10,6 @@ set -euo pipefail integdir=$(cd $(dirname $0) && pwd) -echo "Regression tests are currently disabled. We will re-enable after investigation" -exit 0 - temp_dir=$(mktemp -d) function cleanup { diff --git a/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh b/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh index 8e877a808b3df..fc3e4e3b9a859 100755 --- a/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh +++ b/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh @@ -2,9 +2,6 @@ set -euo pipefail integdir=$(cd $(dirname $0) && pwd) -echo "Regression tests are currently disabled. We will re-enable after investigation" -exit 0 - # run the regular regression test but pass the env variable that will # eventually instruct our runners and wrappers to install the framework # from npmjs.org rather then using the local code. diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index 61f45483f8e18..43fb3d0e0e2ad 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -44,7 +44,7 @@ "dependencies": { "@aws-cdk/cdk-assets-schema": "0.0.0", "archiver": "^4.0.1", - "aws-sdk": "^2.668.0", + "aws-sdk": "^2.672.0", "glob": "^7.1.6", "yargs": "^15.3.1" }, diff --git a/packages/cdk-dasm/package.json b/packages/cdk-dasm/package.json index b160665d17dd6..00c350f4f8fea 100644 --- a/packages/cdk-dasm/package.json +++ b/packages/cdk-dasm/package.json @@ -26,7 +26,7 @@ }, "license": "Apache-2.0", "dependencies": { - "codemaker": "^1.4.1", + "codemaker": "^1.5.0", "yaml": "1.9.2" }, "devDependencies": { diff --git a/packages/decdk/deps.js b/packages/decdk/deps.js index 3435c5e6a0acf..e6087c7163690 100644 --- a/packages/decdk/deps.js +++ b/packages/decdk/deps.js @@ -31,6 +31,10 @@ for (const dir of modules) { delete deps[meta.name]; continue; } + // skip private packages + if (meta.private) { + continue; + } if (!exists) { console.error(`missing dependency: ${meta.name}`); diff --git a/packages/decdk/package.json b/packages/decdk/package.json index fc79842e10f48..88ffd01bf5e80 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -175,7 +175,7 @@ "@aws-cdk/region-info": "0.0.0", "constructs": "^3.0.2", "fs-extra": "^8.1.0", - "jsii-reflect": "^1.4.1", + "jsii-reflect": "^1.5.0", "jsonschema": "^1.2.6", "yaml": "1.9.2", "yargs": "^15.3.1" @@ -186,7 +186,7 @@ "@types/yaml": "1.9.7", "@types/yargs": "^15.0.4", "jest": "^25.5.4", - "jsii": "^1.4.1" + "jsii": "^1.5.0" }, "keywords": [ "aws", diff --git a/packages/decdk/test/__snapshots__/synth.test.js.snap b/packages/decdk/test/__snapshots__/synth.test.js.snap index c181ff0751808..e625105f784f6 100644 --- a/packages/decdk/test/__snapshots__/synth.test.js.snap +++ b/packages/decdk/test/__snapshots__/synth.test.js.snap @@ -1744,6 +1744,39 @@ Object { }, ], }, + Object { + "Action": Array [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + ], + "Effect": "Allow", + "Resource": Object { + "Fn::Join": Array [ + "", + Array [ + "arn:", + Object { + "Ref": "AWS::Partition", + }, + ":codebuild:", + Object { + "Ref": "AWS::Region", + }, + ":", + Object { + "Ref": "AWS::AccountId", + }, + ":report-group/", + Object { + "Ref": "BuildProject097C5DB7", + }, + "-*", + ], + ], + }, + }, Object { "Action": Array [ "kms:Decrypt", diff --git a/packages/monocdk-experiment/deps.js b/packages/monocdk-experiment/deps.js index 034bcc33944c3..61215dd7c84fa 100644 --- a/packages/monocdk-experiment/deps.js +++ b/packages/monocdk-experiment/deps.js @@ -30,6 +30,10 @@ for (const dir of modules) { delete pkgDevDeps[meta.name]; continue; } + // skip private packages + if (meta.private) { + continue; + } if (!exists) { console.error(`missing dependency: ${meta.name}`); diff --git a/packages/monocdk-experiment/package.json b/packages/monocdk-experiment/package.json index e16764d2a7d28..ad79692e340a3 100644 --- a/packages/monocdk-experiment/package.json +++ b/packages/monocdk-experiment/package.json @@ -45,7 +45,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "jsii": "^1.4.1", + "jsii": "^1.5.0", "constructs": "^3.0.2", "@aws-cdk/alexa-ask": "0.0.0", "@aws-cdk/app-delivery": "0.0.0", diff --git a/tools/awslint/package.json b/tools/awslint/package.json index 1eae776b70974..35ee0ce7d9e68 100644 --- a/tools/awslint/package.json +++ b/tools/awslint/package.json @@ -16,11 +16,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "^1.4.1", + "@jsii/spec": "^1.5.0", "camelcase": "^6.0.0", "colors": "^1.4.0", "fs-extra": "^8.1.0", - "jsii-reflect": "^1.4.1", + "jsii-reflect": "^1.5.0", "yargs": "^15.3.1" }, "devDependencies": { diff --git a/tools/cdk-build-tools/package.json b/tools/cdk-build-tools/package.json index c145b5447fc06..6cb490e10ca70 100644 --- a/tools/cdk-build-tools/package.json +++ b/tools/cdk-build-tools/package.json @@ -49,11 +49,11 @@ "eslint-plugin-import": "^2.20.2", "fs-extra": "^8.1.0", "jest": "^25.5.4", - "jsii": "^1.4.1", - "jsii-pacmak": "^1.4.1", + "jsii": "^1.5.0", + "jsii-pacmak": "^1.5.0", "nodeunit": "^0.11.3", "nyc": "^15.0.1", - "ts-jest": "^25.4.0", + "ts-jest": "^25.5.0", "tslint": "^5.20.1", "typescript": "~3.8.3", "yargs": "^15.3.1", diff --git a/tools/cfn2ts/package.json b/tools/cfn2ts/package.json index 50ab6101e8802..63c4043f8c525 100644 --- a/tools/cfn2ts/package.json +++ b/tools/cfn2ts/package.json @@ -30,7 +30,7 @@ "license": "Apache-2.0", "dependencies": { "@aws-cdk/cfnspec": "0.0.0", - "codemaker": "^1.4.1", + "codemaker": "^1.5.0", "fast-json-patch": "^3.0.0-1", "fs-extra": "^8.1.0", "yargs": "^15.3.1" diff --git a/yarn.lock b/yarn.lock index 66c763dd7cefd..d178b94631757 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,16 +9,7 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" - integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== - dependencies: - browserslist "^4.9.1" - invariant "^2.2.4" - semver "^5.5.0" - -"@babel/core@^7.1.0", "@babel/core@^7.4.4", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.7.5": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== @@ -40,7 +31,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.4.4", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": +"@babel/generator@^7.4.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== @@ -50,76 +41,7 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" - integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-builder-react-jsx-experimental@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.5.tgz#0b4b3e04e6123f03b404ca4dfd6528fe6bb92fe3" - integrity sha512-HAagjAC93tk748jcXpZ7oYRZH485RCq/+yEv9SIWezHRPv9moZArTnkUNciUNzvwHUABmiWKlcxJvMcu59UwTg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-module-imports" "^7.8.3" - "@babel/types" "^7.9.5" - -"@babel/helper-builder-react-jsx@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz#16bf391990b57732700a3278d4d9a81231ea8d32" - integrity sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/types" "^7.9.0" - -"@babel/helper-compilation-targets@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" - integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== - dependencies: - "@babel/compat-data" "^7.8.6" - browserslist "^4.9.1" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" - integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - regexpu-core "^4.7.0" - -"@babel/helper-define-map@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" - integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== - dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": +"@babel/helper-function-name@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== @@ -135,13 +57,6 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== - dependencies: - "@babel/types" "^7.8.3" - "@babel/helper-member-expression-to-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" @@ -181,25 +96,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== -"@babel/helper-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" - integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": +"@babel/helper-replace-supers@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== @@ -229,16 +126,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - "@babel/helpers@^7.9.0": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" @@ -257,86 +144,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.7.5", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.5", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - -"@babel/plugin-proposal-object-rest-spread@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" - integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.9.5" - -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": +"@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== @@ -357,34 +170,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-dynamic-import@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-flow@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz#f2c883bd61a6316f2c89380ae5122f923ba4527f" - integrity sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": +"@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" - integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz#3995d7d7ffff432f6ddc742b47e730c054599897" @@ -392,395 +184,49 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": +"@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" - -"@babel/plugin-transform-classes@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" - integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-destructuring@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" - integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-flow-strip-types@^7.4.4": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz#8a3538aa40434e000b8f44a3c5c9ac7229bd2392" - integrity sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-flow" "^7.8.3" - -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-modules-amd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" - integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.4.4", "@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" - integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" - integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== - dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" - -"@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-react-jsx@^7.0.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz#86f576c8540bd06d0e95e0b61ea76d55f6cbd03f" - integrity sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw== - dependencies: - "@babel/helper-builder-react-jsx" "^7.9.0" - "@babel/helper-builder-react-jsx-experimental" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" - -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/preset-env@^7.4.4": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" - integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ== - dependencies: - "@babel/compat-data" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.5" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.0" - "@babel/plugin-transform-modules-commonjs" "^7.9.0" - "@babel/plugin-transform-modules-systemjs" "^7.9.0" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.5" - browserslist "^4.9.1" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/runtime@^7.4.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.9.2": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.3.3", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": +"@babel/template@^7.3.3", "@babel/template@^7.4.0", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== @@ -789,7 +235,7 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== @@ -804,7 +250,7 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== @@ -900,11 +346,6 @@ unique-filename "^1.1.1" which "^1.3.1" -"@iarna/toml@^2.2.0": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" - integrity sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg== - "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" @@ -1098,10 +539,10 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jsii/spec@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.4.1.tgz#35893433c7144bc56efcf3528bc9e21c638ea405" - integrity sha512-iARdSgmuq2+9BCS9fd2RD+KN7FCPwXCW8pIJkAaTWDJolS9cmVaNp7WWZKLhdo7UkPDUpYzLUW3nCc5dimo3iw== +"@jsii/spec@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jsii/spec/-/spec-1.5.0.tgz#55a6d7395862c287cff18cf6cf8d166b715d1e49" + integrity sha512-gmqCGiAuXd8XFwy2uqqwoA0VBhADbrPuuowK7Qfy44ZIzv2gm0txlSkKA5elwRFdqlYHCAl6GYcimZemm6x/rQ== dependencies: jsonschema "^1.2.6" @@ -1905,47 +1346,6 @@ dependencies: "@types/node" ">= 8" -"@parcel/fs@^1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-1.11.0.tgz#fb8a2be038c454ad46a50dc0554c1805f13535cd" - integrity sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA== - dependencies: - "@parcel/utils" "^1.11.0" - mkdirp "^0.5.1" - rimraf "^2.6.2" - -"@parcel/logger@^1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-1.11.1.tgz#c55b0744bcbe84ebc291155627f0ec406a23e2e6" - integrity sha512-9NF3M6UVeP2udOBDILuoEHd8VrF4vQqoWHEafymO1pfSoOMfxrSJZw1MfyAAIUN/IFp9qjcpDCUbDZB+ioVevA== - dependencies: - "@parcel/workers" "^1.11.0" - chalk "^2.1.0" - grapheme-breaker "^0.3.2" - ora "^2.1.0" - strip-ansi "^4.0.0" - -"@parcel/utils@^1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-1.11.0.tgz#539e08fff8af3b26eca11302be80b522674b51ea" - integrity sha512-cA3p4jTlaMeOtAKR/6AadanOPvKeg8VwgnHhOyfi0yClD0TZS/hi9xu12w4EzA/8NtHu0g6o4RDfcNjqN8l1AQ== - -"@parcel/watcher@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-1.12.1.tgz#b98b3df309fcab93451b5583fc38e40826696dad" - integrity sha512-od+uCtCxC/KoNQAIE1vWx1YTyKYY+7CTrxBJPRh3cDWw/C0tCtlBMVlrbplscGoEpt6B27KhJDCv82PBxOERNA== - dependencies: - "@parcel/utils" "^1.11.0" - chokidar "^2.1.5" - -"@parcel/workers@^1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-1.11.0.tgz#7b8dcf992806f4ad2b6cecf629839c41c2336c59" - integrity sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ== - dependencies: - "@parcel/utils" "^1.11.0" - physical-cpu-count "^2.0.0" - "@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.7.2": version "1.7.2" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2" @@ -2181,11 +1581,6 @@ resolved "https://registry.yarnpkg.com/@types/proxyquire/-/proxyquire-1.3.28.tgz#05a647bb0d8fe48fc8edcc193e43cc79310faa7d" integrity sha512-SQaNzWQ2YZSr7FqAyPPiA3FYpux2Lqh3HWMZQk47x3xbMCqgC/w0dY3dw9rGqlweDDkrySQBcaScXWeR+Yb11Q== -"@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== - "@types/semver@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408" @@ -2349,7 +1744,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -acorn-globals@^4.3.0, acorn-globals@^4.3.2: +acorn-globals@^4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== @@ -2367,7 +1762,7 @@ acorn-walk@^6.0.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== -acorn@^6.0.1, acorn@^6.0.4: +acorn@^6.0.1: version "6.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== @@ -2421,11 +1816,6 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -alphanum-sort@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -2458,11 +1848,6 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -2478,13 +1863,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" -ansi-to-html@^0.6.4: - version "0.6.14" - resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.14.tgz#65fe6d08bba5dd9db33f44a20aec331e0010dad8" - integrity sha512-7ZslfB1+EnFSDO5Ju+ue5Y6It19DRnZXWv8jrGHgIlPna5Mh4jz7BV5jCbQneXNFurQcKoolaaAjHtgSBfOIuA== - dependencies: - entities "^1.1.2" - any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -2668,15 +2046,6 @@ asap@^2.0.0: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -2689,14 +2058,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2712,16 +2073,6 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - async@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -2765,10 +2116,10 @@ aws-sdk-mock@^5.1.0: sinon "^9.0.1" traverse "^0.6.6" -aws-sdk@^2.637.0, aws-sdk@^2.668.0: - version "2.668.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.668.0.tgz#18b3e64a47f86c109586422596e53dc733117696" - integrity sha512-mmZJmeenNM9hRR4k+JAStBhYFym2+VCPTRWv0Vn2oqqXIaIaNVdNf9xag/WMG8b8M80R3XXfVHKmDPST0/EfHA== +aws-sdk@^2.637.0, aws-sdk@^2.672.0: + version "2.672.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.672.0.tgz#1aa321f40be878efec225f83184a15be6ab753a4" + integrity sha512-ANxBUPTx5KvNX4OJhIkGT6IoNhBPuh63YvAGuf6tV55MsXNNpZXWuPtvIHxst+M5GrQFA2qDpfcuENzC3OzumQ== dependencies: buffer "4.9.1" events "1.1.1" @@ -2811,13 +2162,6 @@ babel-jest@^25.5.1: graceful-fs "^4.2.4" slash "^3.0.0" -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - babel-plugin-istanbul@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" @@ -2862,33 +2206,6 @@ babel-preset-jest@^25.5.0: babel-plugin-jest-hoist "^25.5.0" babel-preset-current-node-syntax "^0.1.2" -babel-runtime@^6.11.6, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-types@^6.15.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon-walk@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" - integrity sha1-OxWl3btIKni0zpwByLoYFwLZ1s4= - dependencies: - babel-runtime "^6.11.6" - babel-types "^6.15.0" - lodash.clone "^4.5.0" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -2924,23 +2241,11 @@ before-after-hook@^2.0.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - bind-obj-methods@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bind-obj-methods/-/bind-obj-methods-2.0.0.tgz#0178140dbe7b7bb67dc74892ace59bc0247f06f0" integrity sha512-3/qRXczDi2Cdbz6jE+W3IflJOutRVica8frpBn14de1mBOkzDo+6tY33kNhvkw54Kn3PzRRD2VnGbGPcTAk4sw== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bl@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a" @@ -2955,16 +2260,6 @@ bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2973,7 +2268,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -2996,21 +2291,6 @@ braces@^3.0.1: dependencies: fill-range "^7.0.1" -brfs@^1.2.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" - integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== - dependencies: - quote-stream "^1.0.1" - resolve "^1.1.5" - static-module "^2.2.0" - through2 "^2.0.0" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - browser-process-hrtime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" @@ -3023,75 +2303,6 @@ browser-resolve@^1.11.3: dependencies: resolve "1.1.7" -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" - integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g== - dependencies: - caniuse-lite "^1.0.30001038" - electron-to-chromium "^1.3.390" - node-releases "^1.1.53" - pkg-up "^2.0.0" - bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -3116,21 +2327,11 @@ buffer-crc32@^0.2.1, buffer-crc32@^0.2.13: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= -buffer-equal@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" - integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= - buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - buffer@4.9.1: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" @@ -3140,15 +2341,6 @@ buffer@4.9.1: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - buffer@^5.1.0, buffer@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" @@ -3162,11 +2354,6 @@ builtin-modules@^1.1.1: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" @@ -3314,21 +2501,6 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001038: - version "1.0.30001043" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001043.tgz#1b561de27aefbe6ff99e41866b8d7d87840c513b" - integrity sha512-MrBDRPJPDBYwACtSQvxg9+fkna5jPXhJlKmuxenl/ml9uf8LHKlDmLpElu+zTW/bEz7lC1m0wTDD7jiIB+hgFg== - capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -3351,7 +2523,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3360,17 +2532,6 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3. escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - 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" - chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -3389,25 +2550,6 @@ charenc@~0.0.1: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -chokidar@^2.1.5: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - chownr@^1.1.1, chownr@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -3418,14 +2560,6 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -3467,11 +2601,6 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" - integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== - cli-width@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" @@ -3518,7 +2647,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clone@^2.1.1, clone@^2.1.2: +clone@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -3528,24 +2657,15 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codemaker@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/codemaker/-/codemaker-1.4.1.tgz#fc87559a99fa751add5ea53380c41cf12afad128" - integrity sha512-UCyJxq94GNli8wxPQc4lItDOdoK6XCjevgcS7GKix8lTLgR4IFhbd9Y/ZcV6n04r2PEKT44yErSLvCsJ31nQ3g== +codemaker@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/codemaker/-/codemaker-1.5.0.tgz#f0bf606e96dac89c8cf6d7641d344b3c46f11bc7" + integrity sha512-M3vtGs1koOa8OjpjaFX1T92LkcuXAWHAgArwYanAN7Ptu2mmbOJCtznubIr0GnXzetukpCFnRaf777CDgfUFIg== dependencies: camelcase "^6.0.0" decamelize "^1.2.0" @@ -3564,7 +2684,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0, color-convert@^1.9.1: +color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -3583,32 +2703,16 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0, color-name@~1.1.4: +color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - color-support@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -color@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -3629,12 +2733,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -command-exists@^1.2.6: - version "1.2.9" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" - integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== - -commander@^2.11.0, commander@^2.12.1, commander@^2.19.0, commander@^2.20.0, commander@~2.20.3: +commander@^2.12.1, commander@~2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -3682,7 +2781,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@~1.6.0: +concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -3710,21 +2809,11 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - constructs@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/constructs/-/constructs-3.0.2.tgz#49432ba2ef765445bddd5fcc5b3948903ec5210b" @@ -3801,7 +2890,7 @@ conventional-changelog-core@^3.1.6: read-pkg-up "^3.0.0" through2 "^3.0.0" -conventional-changelog-core@^4.1.1, conventional-changelog-core@^4.1.4: +conventional-changelog-core@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.1.4.tgz#39be27fca6ef20a0f998d7a3a1e97cfa8a055cb6" integrity sha512-LO58ZbEpp1Ul+y/vOI8rJRsWkovsYkCFbOCVgi6UnVfU8WC0F8K8VQQwaBZWWUpb6JvEiN4GBR5baRP2txZ+Vg== @@ -3869,33 +2958,16 @@ conventional-changelog-writer@^4.0.11, conventional-changelog-writer@^4.0.6: dependencies: compare-func "^1.3.1" conventional-commits-filter "^2.0.2" - dateformat "^3.0.0" - handlebars "^4.4.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.15" - meow "^5.0.0" - semver "^6.0.0" - split "^1.0.0" - through2 "^3.0.0" - -conventional-changelog@3.1.15: - version "3.1.15" - resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.15.tgz#103d0b550436cf83e8a59ba88be82ece2613cd9f" - integrity sha512-CoWM+Z9bYyF00QzNpTnxkCLiuLAeRocJz3C/foFjvhsdltdtkJgMChp7GytQNjm4pT7JFBVJTpqLHTpxNtOzaA== - dependencies: - conventional-changelog-angular "^5.0.6" - conventional-changelog-atom "^2.0.3" - conventional-changelog-codemirror "^2.0.3" - conventional-changelog-conventionalcommits "^4.2.3" - conventional-changelog-core "^4.1.1" - conventional-changelog-ember "^2.0.4" - conventional-changelog-eslint "^3.0.4" - conventional-changelog-express "^2.0.1" - conventional-changelog-jquery "^3.0.6" - conventional-changelog-jshint "^2.0.3" - conventional-changelog-preset-loader "^2.3.0" + dateformat "^3.0.0" + handlebars "^4.4.0" + json-stringify-safe "^5.0.1" + lodash "^4.17.15" + meow "^5.0.0" + semver "^6.0.0" + split "^1.0.0" + through2 "^3.0.0" -conventional-changelog@^3.1.18: +conventional-changelog@3.1.18, conventional-changelog@^3.1.18: version "3.1.18" resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.18.tgz#7da0a5ab34a604b920b8bf71c6cf5d952f0e805e" integrity sha512-aN6a3rjgV8qwAJj3sC/Lme2kvswWO7fFSGQc32gREcwIOsaiqBaO6f2p0NomFaPDnTqZ+mMZFLL3hlzvEnZ0mQ== @@ -3961,7 +3033,7 @@ conventional-recommended-bump@^5.0.0: meow "^4.0.0" q "^1.5.1" -convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -3985,25 +3057,12 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== - dependencies: - browserslist "^4.8.5" - semver "7.0.0" - -core-js@^2.4.0, core-js@^2.6.5: - version "2.6.11" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0, cosmiconfig@^5.1.0: +cosmiconfig@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -4050,37 +3109,6 @@ crc@^3.4.4: dependencies: buffer "^5.1.0" -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - cross-spawn@^4: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -4089,7 +3117,7 @@ cross-spawn@^4: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^6.0.0, cross-spawn@^6.0.4, cross-spawn@^6.0.5: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -4114,189 +3142,15 @@ crypt@~0.0.1: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" - -css-modules-loader-core@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16" - integrity sha1-WQhmgpShvs0mGuCkziGwtVHyHRY= - dependencies: - icss-replace-symbols "1.1.0" - postcss "6.0.1" - postcss-modules-extract-imports "1.1.0" - postcss-modules-local-by-default "1.2.0" - postcss-modules-scope "1.1.0" - postcss-modules-values "1.3.0" - -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-selector-tokenizer@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.2.tgz#11e5e27c9a48d90284f22d45061c303d7a25ad87" - integrity sha512-yj856NGuAymN6r8bn8/Jl46pR+OC3eEvAhfGYDUe7YPtTPAYrSSw4oAniZ9Y8T5B92hjhwTBLUen0/vKPxf6pw== - dependencies: - cssesc "^3.0.0" - fastparse "^1.1.2" - regexpu-core "^4.6.0" - -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== - dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" - -css-tree@1.0.0-alpha.39: - version "1.0.0-alpha.39" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" - integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== - dependencies: - mdn-data "2.0.6" - source-map "^0.6.1" - -css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.2" - postcss-unique-selectors "^4.0.1" - -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= - -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== - dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.0.0, cssnano@^4.1.10: - version "4.1.10" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.7" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" - integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== - dependencies: - css-tree "1.0.0-alpha.39" - -cssom@0.3.x, cssom@^0.3.4, cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - cssom@^0.4.1: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== -cssstyle@^1.1.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" - integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== - dependencies: - cssom "0.3.x" +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== cssstyle@^2.0.0: version "2.2.0" @@ -4360,15 +3214,7 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -deasync@^0.1.14: - version "0.1.19" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" - integrity sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg== - dependencies: - bindings "^1.5.0" - node-addon-api "^1.7.1" - -debug@2, debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -4429,10 +3275,10 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-equal@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.2.tgz#e68291e245493ae908ca7190c1deea57a01ed82b" - integrity sha512-kX0bjV7tdMuhrhzKPEnVwqfQCuf+IEfN+4Xqv4eKd75xGRyn8yzdQ9ujPY6a221rgJKyQC4KBu1PibDTpa6m9w== +deep-equal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0" + integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA== dependencies: es-abstract "^1.17.5" es-get-iterator "^1.1.0" @@ -4440,13 +3286,14 @@ deep-equal@^2.0.2: is-date-object "^1.0.2" is-regex "^1.0.5" isarray "^2.0.5" - object-is "^1.0.2" + object-is "^1.1.2" object-keys "^1.1.1" + object.assign "^4.1.0" regexp.prototype.flags "^1.3.0" side-channel "^1.0.2" which-boxed-primitive "^1.0.1" which-collection "^1.0.1" - which-typed-array "^1.1.1" + which-typed-array "^1.1.2" deep-is@~0.1.3: version "0.1.3" @@ -4537,19 +3384,6 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - detect-indent@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" @@ -4583,25 +3417,11 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== -diff@^1.3.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" - integrity sha1-fyjS657nsVqX79ic5j3P2qPMur8= - diff@^4.0.1, diff@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - difflib@~0.2.1: version "0.2.4" resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" @@ -4631,29 +3451,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -domain-browser@^1.1.1, domain-browser@^1.2.0: +domain-browser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== - domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -4661,21 +3463,6 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@^1.5.1, domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - dot-prop@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" @@ -4690,23 +3477,6 @@ dot-prop@^4.2.0: dependencies: is-obj "^1.0.0" -dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== - dependencies: - is-obj "^2.0.0" - -dotenv-expand@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" - integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== - -dotenv@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" - integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow== - dotgitignore@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" @@ -4722,13 +3492,6 @@ dreamopt@~0.6.0: dependencies: wordwrap ">=0.0.2" -duplexer2@~0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= - dependencies: - readable-stream "^2.0.2" - duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" @@ -4752,34 +3515,11 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - ejs@^2.5.2: version "2.7.4" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.390: - version "1.3.413" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.413.tgz#9c457a4165c7b42e59d66dff841063eb9bfe5614" - integrity sha512-Jm1Rrd3siqYHO3jftZwDljL2LYQafj3Kki5r+udqE58d0i91SkjItVJ5RwlJn9yko8i7MOcoidVKjQlgSdd1hg== - -elliptic@^6.0.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" - integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4790,11 +3530,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" @@ -4809,16 +3544,11 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -entities@^1.1.1, entities@^1.1.2, entities@~1.1.1: +entities@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== - env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" @@ -4841,7 +3571,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.4, es-abstract@^1.17.5: version "1.17.5" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== @@ -4902,22 +3632,22 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escape-string-regexp@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-3.0.0.tgz#1dad9cc28aed682be0de197280f79911a5fccd61" - integrity sha512-11dXIUC3umvzEViLP117d0KN6LJzZxh5+9F4E/7WLAAw7GrHk8NpUR+g9iJi/pe9C0py4F8rs0hreyRCwlAuZg== +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escodegen@1.x.x, escodegen@^1.11.0, escodegen@^1.11.1: +escodegen@1.x.x, escodegen@^1.11.1: version "1.14.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457" integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ== @@ -4929,18 +3659,6 @@ escodegen@1.x.x, escodegen@^1.11.0, escodegen@^1.11.1: optionalDependencies: source-map "~0.6.1" -escodegen@~1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" - integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" @@ -5070,7 +3788,7 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -esprima@3.x.x, esprima@^3.1.3: +esprima@3.x.x: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= @@ -5109,11 +3827,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -5129,19 +3842,6 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= -events@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" - integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - exec-sh@^0.3.2: version "0.3.4" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" @@ -5259,16 +3959,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -falafel@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.2.4.tgz#b5d86c060c2412a43166243cb1bce44d1abd2819" - integrity sha512-0HXjo8XASWRmsS0X1EkhwEMZaD3Qvp7FfURwjLKjG1ghfRm/MGZl2r4cWUTv41KdNghTw4OUMmVtdGQp3+H+uQ== - dependencies: - acorn "^7.1.1" - foreach "^2.0.5" - isarray "^2.0.1" - object-keys "^1.0.6" - fast-check@^1.24.2: version "1.24.2" resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-1.24.2.tgz#1f5e4a3c20530c3a85a861e60f680c32229d4fcb" @@ -5287,7 +3977,7 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== -fast-glob@^2.2.2, fast-glob@^2.2.6: +fast-glob@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== @@ -5321,11 +4011,6 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fastparse@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" - integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== - fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -5366,16 +4051,11 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-uri-to-path@1, file-uri-to-path@1.0.0: +file-uri-to-path@1: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -filesize@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - fill-keys@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" @@ -5525,11 +4205,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -5601,14 +4276,6 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.12" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c" - integrity sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - fsevents@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" @@ -5682,11 +4349,6 @@ get-pkg-repo@^1.0.0: parse-github-repo-url "^1.3.0" through2 "^2.0.0" -get-port@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= - get-port@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" @@ -5880,14 +4542,6 @@ graceful-fs@^4.2.4: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -grapheme-breaker@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" - integrity sha1-W55reMODJFLSuiuxy4MPlidkEKw= - dependencies: - brfs "^1.2.0" - unicode-trie "^0.3.1" - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -5918,18 +4572,6 @@ har-validator@~5.1.3: ajv "^6.5.5" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -5981,29 +4623,13 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.1, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - hasha@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39" @@ -6024,40 +4650,11 @@ hasha@^5.0.0: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - html-encoding-sniffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" @@ -6070,43 +4667,12 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-tags@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98" - integrity sha1-x43mW1Zjqll5id0rerSSANfk25g= - -htmlnano@^0.2.2: - version "0.2.5" - resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.2.5.tgz#134fd9548c7cbe51c8508ce434a3f9488cff1b0b" - integrity sha512-X1iPSwXG/iF9bVs+/obt2n6F64uH0ETkA8zp7qFDmLW9/+A6ueHGeb/+qD67T21qUY22owZPMdawljN50ajkqA== - dependencies: - cssnano "^4.1.10" - normalize-html-whitespace "^1.0.0" - posthtml "^0.12.0" - posthtml-render "^1.1.5" - purgecss "^1.4.0" - svgo "^1.3.2" - terser "^4.3.9" - uncss "^0.17.2" - -htmlparser2@^3.9.2: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - http-cache-semantics@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== -http-errors@1.7.3, http-errors@~1.7.2: +http-errors@1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== @@ -6134,11 +4700,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - https-proxy-agent@^2.2.3: version "2.2.4" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" @@ -6174,11 +4735,6 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" -icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= - ieee754@1.1.13, ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -6260,11 +4816,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -6283,16 +4834,6 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ini@^1.3.2, ini@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" @@ -6350,13 +4891,6 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" -invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -6372,16 +4906,6 @@ ip@1.1.5, ip@^1.1.5: resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - -is-absolute-url@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -6406,23 +4930,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - is-bigint@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g== -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-boolean-object@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" @@ -6445,18 +4957,6 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -6557,13 +5057,6 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-html@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-html/-/is-html-1.1.0.tgz#e04f1c18d39485111396f9a0273eab51af218464" - integrity sha1-4E8cGNOUhRETlvmgJz6rUa8hhGQ= - dependencies: - html-tags "^1.0.0" - is-map@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" @@ -6591,11 +5084,6 @@ is-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - is-object@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" @@ -6632,11 +5120,6 @@ is-regex@^1.0.5: dependencies: has "^1.0.3" -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - is-set@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43" @@ -6664,13 +5147,6 @@ is-string@^1.0.4, is-string@^1.0.5: resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - is-symbol@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -6700,11 +5176,6 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-url@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -6725,11 +5196,6 @@ is-windows@^1.0.0, is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - is-wsl@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" @@ -6745,7 +5211,7 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@^2.0.1, isarray@^2.0.5: +isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== @@ -7258,7 +5724,7 @@ jest-worker@^25.5.0: merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^25.5.4: +jest@^25.5.3, jest@^25.5.4: version "25.5.4" resolved "https://registry.yarnpkg.com/jest/-/jest-25.5.4.tgz#f21107b6489cfe32b076ce2adcadee3587acb9db" integrity sha512-hHFJROBTqZahnO+X+PMtT6G2/ztqAZJveGqz//FnWWHurizkD05PQGzRZOhF3XP6z7SJmL+5tCfW8qV06JypwQ== @@ -7277,55 +5743,23 @@ js-base64@^2.1.9: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.2.7, js-yaml@^3.3.1: +js-yaml@^3.13.1, js-yaml@^3.2.7: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== dependencies: argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@^14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.1.0.tgz#916463b6094956b0a6c1782c94e380cd30e1981b" - integrity sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng== - dependencies: - abab "^2.0.0" - acorn "^6.0.4" - acorn-globals "^4.3.0" - array-equal "^1.0.0" - cssom "^0.3.4" - cssstyle "^1.1.1" - data-urls "^1.1.0" - domexception "^1.0.1" - escodegen "^1.11.0" - html-encoding-sniffer "^1.0.2" - nwsapi "^2.1.3" - parse5 "5.1.0" - pn "^1.1.0" - request "^2.88.0" - request-promise-native "^1.0.5" - saxes "^3.1.9" - symbol-tree "^3.2.2" - tough-cookie "^2.5.0" - w3c-hr-time "^1.0.1" - w3c-xmlserializer "^1.1.2" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^7.0.0" - ws "^6.1.2" - xml-name-validator "^3.0.0" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsdom@^15.2.1: version "15.2.1" @@ -7364,73 +5798,68 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -jsii-diff@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsii-diff/-/jsii-diff-1.4.1.tgz#a4111869323940a693ce7a9a7c6559ade51dc6ee" - integrity sha512-7dtYd24w1UNDki0Uc7CJiv7oKoYAnKem1fSRDiEUVcAL1/9iNvYVGPMjUMMNx8RoRYln/oK3988AYB/h6VDxYw== +jsii-diff@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jsii-diff/-/jsii-diff-1.5.0.tgz#a8400ea7ba69e619f8c44cc6a9677a2f71587fc2" + integrity sha512-6Z3ayLF1IMFLq9tSmfpozwF9F/JwEswEYSvKOhFb/vcULP5j743HbvEXoIzRNVX/xTKdpBbo7tXmFFECC3xDEw== dependencies: - "@jsii/spec" "^1.4.1" + "@jsii/spec" "^1.5.0" fs-extra "^9.0.0" - jsii-reflect "^1.4.1" + jsii-reflect "^1.5.0" log4js "^6.2.1" typescript "~3.8.3" yargs "^15.3.1" -jsii-pacmak@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsii-pacmak/-/jsii-pacmak-1.4.1.tgz#ff119b51989b8b89edf2de983779727a43586f9e" - integrity sha512-2RSlhMDsXOoyJI9dCAXAZ29oHQhtJFfcmtfBP4CIz90HFk/UYQlEHz6Mj6E398XwEnSSRaDzu3DA2WEJPb4cNw== +jsii-pacmak@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jsii-pacmak/-/jsii-pacmak-1.5.0.tgz#6de664237eb1f7669ed95d007f1c86a133015498" + integrity sha512-vtTi8640mCUko4cEcPA36zhLLz9IKZXRWtHhRjTH3pKk3PfKDId+jQSzHfCNFe4Gjt9SuJndIrwtvWt7dM+zQg== dependencies: - "@jsii/spec" "^1.4.1" + "@jsii/spec" "^1.5.0" clone "^2.1.2" - codemaker "^1.4.1" + codemaker "^1.5.0" commonmark "^0.29.1" - escape-string-regexp "^3.0.0" + escape-string-regexp "^4.0.0" fs-extra "^9.0.0" - jsii-reflect "^1.4.1" - jsii-rosetta "^1.4.1" + jsii-reflect "^1.5.0" + jsii-rosetta "^1.5.0" semver "^7.3.2" spdx-license-list "^6.2.0" xmlbuilder "^15.1.1" yargs "^15.3.1" -jsii-reflect@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.4.1.tgz#c4f5ef4878ead129740e412e66411a2b74f2c5c8" - integrity sha512-Z4KK6ThkxwstPTaDLaWWn2y3YTCxOY1zOz3WJ2aQnrVNeEVs3Se084fEa44uXiidfq8e9kJ7npUeSMIgQuRDMQ== +jsii-reflect@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jsii-reflect/-/jsii-reflect-1.5.0.tgz#f6007bbb3b262832d93a1b5b87b1c8d570e5c2fc" + integrity sha512-+kDzb9ariTFrox1GaLfclU1Gxs1b40hr5BSBhVBzq03F+opMyTXp2gBPotsTm8Se44wcptDbTPwEmSx1ZxR+rQ== dependencies: - "@jsii/spec" "^1.4.1" + "@jsii/spec" "^1.5.0" colors "^1.4.0" fs-extra "^9.0.0" - oo-ascii-tree "^1.4.1" + oo-ascii-tree "^1.5.0" yargs "^15.3.1" -jsii-rosetta@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.4.1.tgz#50f41aff8066bdeecb6a85141a0bbed6fdf86517" - integrity sha512-6zDlsasizUOr4zLmRYPupL53ZAsk6Tcre/23hhrrMNcAazoe1wZtEa6UtpOm+qbwD67z2VgqcMTXcfFQvPEUAA== +jsii-rosetta@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-1.5.0.tgz#158365c89fbc0022b821746f3500ececfc37fd21" + integrity sha512-ABR9FWLjuEMZJrY19hjec5JCwAS9k6aQMt6F2KXTh5chFwYjU/rHUMJ/IQ9kGNiiv5MDJeVokxH/CM2gERVOdA== dependencies: - "@jsii/spec" "^1.4.1" + "@jsii/spec" "^1.5.0" commonmark "^0.29.1" fs-extra "^9.0.0" typescript "~3.8.3" xmldom "^0.3.0" yargs "^15.3.1" -jsii@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsii/-/jsii-1.4.1.tgz#eaa166829fc90dfe6f207139170e6608a63221be" - integrity sha512-EMBPeLs52JgCujAuPuZb0MQX5Wa3h/XskyzJNKgP5NqSLrntKtXb9379g4W0RBF2+df4lJyXDfa6dr59jefi2g== +jsii@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jsii/-/jsii-1.5.0.tgz#dcf62a953bb765e0c55ba23b0711f25a349baafb" + integrity sha512-1dWN55Bttwx9zr58iSOxCkj9O99YKtzs/51FNwjGs20KNXvVfiY6ZBnUGhq57G5mSmb+NZosX71EFknoYrFoLA== dependencies: - "@jsii/spec" "^1.4.1" + "@jsii/spec" "^1.5.0" case "^1.6.3" colors "^1.4.0" - deep-equal "^2.0.2" + deep-equal "^2.0.3" fs-extra "^9.0.0" log4js "^6.2.1" semver "^7.3.2" @@ -7628,13 +6057,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -7730,11 +6152,6 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= -lodash.clone@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= - lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -7775,7 +6192,7 @@ lodash.isplainobject@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= -lodash.memoize@4.x, lodash.memoize@^4.1.2: +lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= @@ -7815,7 +6232,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1: +lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -7825,13 +6242,6 @@ log-driver@^1.2.7: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - log4js@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.2.1.tgz#fc23a3bf287f40f5b48259958e5e0ed30d558eeb" @@ -7850,13 +6260,6 @@ lolex@^5.0.0: dependencies: "@sinonjs/commons" "^1.7.0" -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -7885,13 +6288,6 @@ macos-release@^2.2.0: resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -magic-string@^0.22.4: - version "0.22.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" - integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== - dependencies: - vlq "^0.2.2" - make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -7973,15 +6369,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - md5@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" @@ -7991,16 +6378,6 @@ md5@^2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -mdn-data@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" - integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== - mdurl@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" @@ -8057,13 +6434,6 @@ merge-descriptors@~1.0.0: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= -merge-source-map@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" - integrity sha1-pd5GU42uhNQRTMXqArR3KmNGcB8= - dependencies: - source-map "^0.5.6" - merge-source-map@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" @@ -8089,7 +6459,7 @@ micromatch@4.x, micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -8108,14 +6478,6 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - mime-db@1.43.0: version "1.43.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" @@ -8128,11 +6490,6 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.43.0" -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -8143,16 +6500,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - minimatch@>=3.0, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -8181,6 +6528,13 @@ minipass@^2.2.0, minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2. safe-buffer "^5.1.2" yallist "^3.0.0" +minipass@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" + integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w== + dependencies: + yallist "^4.0.0" + minizlib@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" @@ -8219,12 +6573,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@1.x: +mkdirp@*: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -8268,11 +6622,6 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -8307,11 +6656,6 @@ mz@^2.5.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -8375,11 +6719,6 @@ nock@^12.0.3: lodash "^4.17.13" propagate "^2.0.0" -node-addon-api@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" - integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== - node-fetch-npm@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4" @@ -8394,11 +6733,6 @@ node-fetch@^2.3.0, node-fetch@^2.5.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -node-forge@^0.7.1: - version "0.7.6" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" - integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== - node-gyp@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.0.tgz#8e31260a7af4a2e2f994b0673d4e0b3866156332" @@ -8421,35 +6755,6 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-libs-browser@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - node-modules-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" @@ -8473,11 +6778,6 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^1.1.53: - version "1.1.53" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" - integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== - nodeunit@^0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/nodeunit/-/nodeunit-0.11.3.tgz#313afae26cd11b407b731ff774b8e35e5d6f9568" @@ -8494,11 +6794,6 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-html-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz#5e3c8e192f1b06c3b9eee4b7e7f28854c7601e34" - integrity sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA== - normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -8521,7 +6816,7 @@ normalize-path@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^3.0.0, normalize-url@^3.3.0: +normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== @@ -8604,13 +6899,6 @@ npmlog@^4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - null-check@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" @@ -8621,7 +6909,7 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -nwsapi@^2.1.3, nwsapi@^2.2.0: +nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== @@ -8694,7 +6982,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -8713,12 +7001,7 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-inspect@~1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" - integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== - -object-is@^1.0.2: +object-is@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== @@ -8726,7 +7009,7 @@ object-is@^1.0.2: define-properties "^1.1.3" es-abstract "^1.17.5" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -8748,7 +7031,7 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: +object.getownpropertydescriptors@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== @@ -8778,13 +7061,6 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -8806,23 +7082,16 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.4.1.tgz#c48aa8afcb90863e9efcae9dbfa07d897c98e964" - integrity sha512-8bCnzfbDQvJCOirc77ISBjR0X8ziploaydwJyQD5ZgF6W6Nh3Ds3C8Q/95Lc095TBfDU+m+VZLxk3z3DgW/t+w== +oo-ascii-tree@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/oo-ascii-tree/-/oo-ascii-tree-1.5.0.tgz#e462474b98910dd33fec6518629358c74845ce1a" + integrity sha512-6s+nBxOutQeDvForKX5oFUchFSDpD2KGFIkqyv4VDX0FZl79iCx8E9R4Y/7o2umjTjuK9CrBJzO0kFKNKWbZQA== opener@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== -opn@^5.1.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - optionator@^0.8.1, optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -8835,23 +7104,6 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" -ora@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" - integrity sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA== - dependencies: - chalk "^2.3.1" - cli-cursor "^2.1.0" - cli-spinners "^1.1.0" - log-symbols "^2.2.0" - strip-ansi "^4.0.0" - wcwidth "^1.0.1" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - os-homedir@^1.0.0, os-homedir@^1.0.1, os-homedir@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -9045,12 +7297,7 @@ package-hash@^4.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" -pako@^0.2.5: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= - -pako@~1.0.2, pako@~1.0.5: +pako@~1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -9064,71 +7311,6 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -parcel-bundler@^1.12.4: - version "1.12.4" - resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.12.4.tgz#31223f4ab4d00323a109fce28d5e46775409a9ee" - integrity sha512-G+iZGGiPEXcRzw0fiRxWYCKxdt/F7l9a0xkiU4XbcVRJCSlBnioWEwJMutOCCpoQmaQtjB4RBHDGIHN85AIhLQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/core" "^7.4.4" - "@babel/generator" "^7.4.4" - "@babel/parser" "^7.4.4" - "@babel/plugin-transform-flow-strip-types" "^7.4.4" - "@babel/plugin-transform-modules-commonjs" "^7.4.4" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/preset-env" "^7.4.4" - "@babel/runtime" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" - "@iarna/toml" "^2.2.0" - "@parcel/fs" "^1.11.0" - "@parcel/logger" "^1.11.1" - "@parcel/utils" "^1.11.0" - "@parcel/watcher" "^1.12.1" - "@parcel/workers" "^1.11.0" - ansi-to-html "^0.6.4" - babylon-walk "^1.0.2" - browserslist "^4.1.0" - chalk "^2.1.0" - clone "^2.1.1" - command-exists "^1.2.6" - commander "^2.11.0" - core-js "^2.6.5" - cross-spawn "^6.0.4" - css-modules-loader-core "^1.1.0" - cssnano "^4.0.0" - deasync "^0.1.14" - dotenv "^5.0.0" - dotenv-expand "^5.1.0" - envinfo "^7.3.1" - fast-glob "^2.2.2" - filesize "^3.6.0" - get-port "^3.2.0" - htmlnano "^0.2.2" - is-glob "^4.0.0" - is-url "^1.2.2" - js-yaml "^3.10.0" - json5 "^1.0.1" - micromatch "^3.0.4" - mkdirp "^0.5.1" - node-forge "^0.7.1" - node-libs-browser "^2.0.0" - opn "^5.1.0" - postcss "^7.0.11" - postcss-value-parser "^3.3.1" - posthtml "^0.11.2" - posthtml-parser "^0.4.0" - posthtml-render "^1.1.3" - resolve "^1.4.0" - semver "^5.4.1" - serialize-to-js "^3.0.0" - serve-static "^1.12.4" - source-map "0.6.1" - terser "^3.7.3" - v8-compile-cache "^2.0.0" - ws "^5.1.1" - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -9136,18 +7318,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - parse-github-repo-url@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" @@ -9201,21 +7371,11 @@ parse5@5.1.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -9288,27 +7448,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -physical-cpu-count@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" - integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= - picomatch@^2.0.4, picomatch@^2.0.5: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -9337,415 +7481,47 @@ pinkie-promise@^2.0.0: pinkie "^2.0.0" pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pirates@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== - dependencies: - node-modules-regexp "^1.0.0" - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.1.0, pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== - dependencies: - postcss "^7.0.27" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" - -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" - -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -postcss-modules-extract-imports@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" - integrity sha1-thTJcgvmgW6u41+zpfqh26agXds= - dependencies: - postcss "^6.0.1" - -postcss-modules-local-by-default@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" - integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= - dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" - -postcss-modules-scope@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" - integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= - dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" - -postcss-modules-values@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" - integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= - dependencies: - icss-replace-symbols "^1.1.0" - postcss "^6.0.1" - -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" - -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-selector-parser@6.0.2, postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" - integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== - dependencies: - dot-prop "^5.2.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-svgo@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== - dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== - dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - -postcss-value-parser@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" - integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -postcss@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" - integrity sha1-AA29H47vIXqjaLmiEsX8QLKo8/I= +pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== dependencies: - chalk "^1.1.3" - source-map "^0.5.6" - supports-color "^3.2.3" + node-modules-regexp "^1.0.0" -postcss@^6.0.1: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" + find-up "^2.1.0" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.27: - version "7.0.27" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" - integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" + find-up "^3.0.0" -posthtml-parser@^0.4.0, posthtml-parser@^0.4.1, posthtml-parser@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.2.tgz#a132bbdf0cd4bc199d34f322f5c1599385d7c6c1" - integrity sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg== +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: - htmlparser2 "^3.9.2" - -posthtml-render@^1.1.3, posthtml-render@^1.1.5, posthtml-render@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.2.2.tgz#f554a19ed40d40e2bfc160826b0a91d4a23656cd" - integrity sha512-MbIXTWwAfJ9qET6Zl29UNwJcDJEEz9Zkr5oDhiujitJa7YBJwEpbkX2cmuklCDxubTMoRWpid3q8DrSyGnUUzQ== + find-up "^4.0.0" -posthtml@^0.11.2: - version "0.11.6" - resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.6.tgz#e349d51af7929d0683b9d8c3abd8166beecc90a8" - integrity sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw== - dependencies: - posthtml-parser "^0.4.1" - posthtml-render "^1.1.5" +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== -posthtml@^0.12.0: - version "0.12.2" - resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.12.2.tgz#81d1ca9892a54941639bfd0f546957eaa1d3497a" - integrity sha512-vDMikGrmr2Ce4ralyBwfoTymA9Ycv2QSeaV+U9CdF/kHstsGSBVsTZ3Jt/BdACFuqCNyaICMdJI/rvGEreL7pA== - dependencies: - posthtml-parser "^0.4.2" - posthtml-render "^1.2.2" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= prelude-ls@~1.1.2: version "1.1.2" @@ -9772,11 +7548,6 @@ pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -9789,11 +7560,6 @@ process-on-spawn@^1.0.0: dependencies: fromentries "^1.2.0" -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -9895,18 +7661,6 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -9937,12 +7691,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.0.0, punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -9952,17 +7701,7 @@ pure-rand@^2.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-2.0.0.tgz#3324633545207907fe964c2f0ebf05d8e9a7f129" integrity sha512-mk98aayyd00xbfHgE3uEmAUGzz3jCdm8Mkf5DUXUhc7egmOaGG2D7qhVlynGenNe9VaNJZvzO9hkc8myuTkDgw== -purgecss@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-1.4.2.tgz#67ab50cb4f5c163fcefde56002467c974e577f41" - integrity sha512-hkOreFTgiyMHMmC2BxzdIw5DuC6kxAbP/gGOGd3MEsF3+5m69rIvUEPaxrnoUtfODTFKe9hcXjGwC6jcjoyhOw== - dependencies: - glob "^7.1.3" - postcss "^7.0.14" - postcss-selector-parser "^6.0.0" - yargs "^14.0.0" - -q@^1.1.2, q@^1.5.1: +q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= @@ -9972,11 +7711,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -9987,35 +7721,6 @@ quick-lru@^1.0.0: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= -quote-stream@^1.0.1, quote-stream@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" - integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI= - dependencies: - buffer-equal "0.0.1" - minimist "^1.1.3" - through2 "^2.0.0" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - raw-body@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" @@ -10144,7 +7849,7 @@ read@1, read@^1.0.4, read@~1.0.1: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.3, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -10186,15 +7891,6 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - realpath-native@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" @@ -10216,36 +7912,11 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== -regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== - dependencies: - "@babel/runtime" "^7.8.4" - private "^0.1.8" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -10272,30 +7943,6 @@ regexpp@^3.0.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -regexpu-core@^4.6.0, regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== - -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== - dependencies: - jsesc "~0.5.0" - release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -10332,7 +7979,7 @@ request-promise-core@1.1.3: dependencies: lodash "^4.17.15" -request-promise-native@^1.0.5, request-promise-native@^1.0.7: +request-promise-native@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== @@ -10421,7 +8068,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@1.x, resolve@^1.1.5, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.4.0: +resolve@^1.10.0, resolve@^1.11.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2: version "1.16.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c" integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== @@ -10466,16 +8113,6 @@ rfdc@^1.1.4: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -10497,14 +8134,6 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -10531,7 +8160,7 @@ rxjs@^6.4.0, rxjs@^6.5.3: dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -10573,7 +8202,7 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= -sax@>=0.6.0, sax@~1.2.4: +sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -10597,55 +8226,21 @@ semver-intersect@^1.4.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@6.3.0, semver@6.x, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@6.x, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== +semver@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.1.tgz#29104598a197d6cbe4733eeecbe968f7b43a9667" + integrity sha512-WfuG+fl6eh3eZ2qAf6goB7nhiCd7NPXhmyFxigB/TOkQyeLP8w8GsVehvtGNtnNmyboz4TgeK40B1Kbql/8c5A== semver@^7.2.2, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-to-js@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-3.1.1.tgz#b3e77d0568ee4a60bfe66287f991e104d3a1a4ac" - integrity sha512-F+NGU0UHMBO4Q965tjw7rvieNVjlH6Lqi2emq/Lc9LUURYJbiCzmpi4Cy1OOjjVPtxu0c+NE85LU6968Wko5ZA== - -serve-static@^1.12.4: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -10666,24 +8261,11 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - setprototypeof@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -10691,11 +8273,6 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shallow-copy@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" - integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA= - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -10738,13 +8315,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - sinon@^9.0.1, sinon@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.2.tgz#b9017e24633f4b1c98dfb6e784a5f0509f5fd85d" @@ -10865,7 +8435,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.10, source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12: +source-map-support@^0.5.10, source-map-support@^0.5.19, source-map-support@^0.5.6: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -10878,16 +8448,16 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" @@ -10996,23 +8566,18 @@ ssri@^6.0.0, ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - stack-utils@^1.0.1, stack-utils@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== -standard-version@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/standard-version/-/standard-version-7.1.0.tgz#021dd79eac749548677c876d5a94791df50f1f36" - integrity sha512-bHY2E/1tYGeVl+0XSXFivb+54h2fA4pWJocXAd6FGbtSFUvGsnfmMbIXYDxrYErpq7oEqoKreV8xTAp78WoATA== +standard-version@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/standard-version/-/standard-version-8.0.0.tgz#3bb1ab495702cf01a9dc602b2b91df1ade6f008e" + integrity sha512-cS/U9yhYPHfyokFce6e/H3U8MaKwZKSGzH25J776sChrae/doDQjsl3vCQ0hW1MSzdrUTb7pir4ApjnbDt/TAg== dependencies: chalk "2.4.2" - conventional-changelog "3.1.15" + conventional-changelog "3.1.18" conventional-changelog-config-spec "2.1.0" conventional-changelog-conventionalcommits "4.2.3" conventional-recommended-bump "6.0.5" @@ -11023,16 +8588,9 @@ standard-version@^7.1.0: find-up "4.1.0" fs-access "1.0.1" git-semver-tags "3.0.1" - semver "6.3.0" + semver "7.1.1" stringify-package "1.0.1" - yargs "15.0.2" - -static-eval@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.5.tgz#f0782e66999c4b3651cda99d9ce59c507d188f71" - integrity sha512-nNbV6LbGtMBgv7e9LFkt5JV8RVlRsyJrphfAt9tOtBBW/SfnzZDf2KnS72an8e434A+9e/BmJuTxeGPvrAK7KA== - dependencies: - escodegen "^1.11.1" + yargs "15.3.1" static-extend@^0.1.1: version "0.1.2" @@ -11042,27 +8600,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -static-module@^2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" - integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ== - dependencies: - concat-stream "~1.6.0" - convert-source-map "^1.5.1" - duplexer2 "~0.1.4" - escodegen "~1.9.0" - falafel "^2.1.0" - has "^1.0.1" - magic-string "^0.22.4" - merge-source-map "1.0.4" - object-inspect "~1.4.0" - quote-stream "~1.0.2" - readable-stream "~2.3.3" - shallow-copy "~0.0.1" - static-eval "^2.0.0" - through2 "~2.0.3" - -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: +"statuses@>= 1.5.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -11072,14 +8610,6 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" @@ -11088,17 +8618,6 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - stream-shift@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" @@ -11195,7 +8714,7 @@ string.prototype.trimstart@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -11300,28 +8819,7 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - -supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -11350,25 +8848,6 @@ supports-hyperlinks@^2.0.0: has-flag "^4.0.0" supports-color "^7.0.0" -svgo@^1.0.0, svgo@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -11384,31 +8863,28 @@ table@^5.2.3, table@^5.4.6: slice-ansi "^2.1.0" string-width "^3.0.0" -tap-mocha-reporter@^3.0.9: - version "3.0.9" - resolved "https://registry.yarnpkg.com/tap-mocha-reporter/-/tap-mocha-reporter-3.0.9.tgz#ea41e741149a94c278d106cbcccc37fec2dfeeaa" - integrity sha512-VO07vhC9EG27EZdOe7bWBj1ldbK+DL9TnRadOgdQmiQOVZjFpUEQuuqO7+rNSO2kfmkq5hWeluYXDWNG/ytXTQ== +tap-mocha-reporter@^3.0.9, tap-mocha-reporter@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/tap-mocha-reporter/-/tap-mocha-reporter-5.0.1.tgz#74f00be2ddd2a380adad45e085795137bc39497a" + integrity sha512-1knFWOwd4khx/7uSEnUeaP9IPW3w+sqTgJMhrwah6t46nZ8P25atOKAjSvVDsT67lOPu0nfdOqUwoyKn+3E5pA== dependencies: color-support "^1.1.0" - debug "^2.1.3" - diff "^1.3.2" - escape-string-regexp "^1.0.3" + debug "^4.1.1" + diff "^4.0.1" + escape-string-regexp "^2.0.0" glob "^7.0.5" - js-yaml "^3.3.1" - tap-parser "^5.1.0" - unicode-length "^1.0.0" - optionalDependencies: - readable-stream "^2.1.5" + tap-parser "^10.0.0" + tap-yaml "^1.0.0" + unicode-length "^2.0.2" -tap-parser@^5.1.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-5.4.0.tgz#6907e89725d7b7fa6ae41ee2c464c3db43188aec" - integrity sha512-BIsIaGqv7uTQgTW1KLTMNPSEQf4zDDPgYOBRdgOfuB+JFOLRBfEu6cLa/KvMvmqggu1FKXDfitjLwsq4827RvA== +tap-parser@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-10.0.1.tgz#b63c2500eeef2be8fbf09d512914196d1f12ebec" + integrity sha512-qdT15H0DoJIi7zOqVXDn9X0gSM68JjNy1w3VemwTJlDnETjbi6SutnqmBfjDJAwkFS79NJ97gZKqie00ZCGmzg== dependencies: events-to-array "^1.0.1" - js-yaml "^3.2.7" - optionalDependencies: - readable-stream "^2" + minipass "^3.0.0" + tap-yaml "^1.0.0" tap-parser@^7.0.0: version "7.0.0" @@ -11419,6 +8895,13 @@ tap-parser@^7.0.0: js-yaml "^3.2.7" minipass "^2.2.0" +tap-yaml@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tap-yaml/-/tap-yaml-1.0.0.tgz#4e31443a5489e05ca8bbb3e36cef71b5dec69635" + integrity sha512-Rxbx4EnrWkYk0/ztcm5u3/VznbyFJpyXO12dDBHKWiDVxy7O2Qw6MRrwO5H6Ww0U5YhRY/4C/VzWmFPhBQc4qQ== + dependencies: + yaml "^1.5.0" + tap@^12.0.1: version "12.7.0" resolved "https://registry.yarnpkg.com/tap/-/tap-12.7.0.tgz#6e0c40eb7ec1347a9311aa3ce9dee098dc41b566" @@ -11521,24 +9004,6 @@ terminal-link@^2.0.0: ansi-escapes "^4.2.1" supports-hyperlinks "^2.0.0" -terser@^3.7.3: - version "3.17.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" - integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== - dependencies: - commander "^2.19.0" - source-map "~0.6.1" - source-map-support "~0.5.10" - -terser@^4.3.9: - version "4.6.11" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f" - integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - test-exclude@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" @@ -11587,7 +9052,7 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -through2@^2.0.0, through2@^2.0.2, through2@~2.0.3: +through2@^2.0.0, through2@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -11612,18 +9077,6 @@ thunkify@^2.1.2: resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d" integrity sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0= -timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== - dependencies: - setimmediate "^1.0.4" - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - tiny-glob@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.6.tgz#9e056e169d9788fe8a734dfa1ff02e9b92ed7eda" @@ -11632,11 +9085,6 @@ tiny-glob@^0.2.6: globalyzer "^0.1.0" globrex "^0.1.1" -tiny-inflate@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" - integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== - tmatch@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-4.0.0.tgz#ba178007f30bf6a70f37c643fca5045fb2f8c448" @@ -11654,16 +9102,6 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -11706,7 +9144,7 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== -tough-cookie@^2.3.3, tough-cookie@^2.5.0, tough-cookie@~2.5.0: +tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -11755,10 +9193,10 @@ trivial-deferred@^1.0.1: resolved "https://registry.yarnpkg.com/trivial-deferred/-/trivial-deferred-1.0.1.tgz#376d4d29d951d6368a6f7a0ae85c2f4d5e0658f3" integrity sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM= -ts-jest@^25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.4.0.tgz#5ad504299f8541d463a52e93e5e9d76876be0ba4" - integrity sha512-+0ZrksdaquxGUBwSdTIcdX7VXdwLIlSRsyjivVA9gcO+Cvr6ByqDhu/mi5+HCcb6cMkiQp5xZ8qRO7/eCqLeyw== +ts-jest@^25.5.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.5.0.tgz#f56f039b6caa15d9e32d064b0a8902886ab2fe72" + integrity sha512-govrjbOk1UEzcJ5cX5k8X8IUtFuP3lp3mrF3ZuKtCdAOQzdeCM7qualhb/U8s8SWFwEDutOqfF5PLkJ+oaYD4w== dependencies: bs-logger "0.x" buffer-from "1.x" @@ -11767,8 +9205,7 @@ ts-jest@^25.4.0: lodash.memoize "4.x" make-error "1.x" micromatch "4.x" - mkdirp "1.x" - resolve "1.x" + mkdirp "0.x" semver "6.x" yargs-parser "18.x" @@ -11841,11 +9278,6 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -11935,60 +9367,14 @@ umask@^1.1.0: resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= -uncss@^0.17.2: - version "0.17.3" - resolved "https://registry.yarnpkg.com/uncss/-/uncss-0.17.3.tgz#50fc1eb4ed573ffff763458d801cd86e4d69ea11" - integrity sha512-ksdDWl81YWvF/X14fOSw4iu8tESDHFIeyKIeDrK6GEVTQvqJc1WlOEXqostNwOCi3qAj++4EaLsdAgPmUbEyog== - dependencies: - commander "^2.20.0" - glob "^7.1.4" - is-absolute-url "^3.0.1" - is-html "^1.1.0" - jsdom "^14.1.0" - lodash "^4.17.15" - postcss "^7.0.17" - postcss-selector-parser "6.0.2" - request "^2.88.0" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-length@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/unicode-length/-/unicode-length-1.0.3.tgz#5ada7a7fed51841a418a328cf149478ac8358abb" - integrity sha1-Wtp6f+1RhBpBijKM8UlHisg1irs= +unicode-length@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unicode-length/-/unicode-length-2.0.2.tgz#e5eb4c0d523fdf7bebb59ca261c9ca1cf732da96" + integrity sha512-Ph/j1VbS3/r77nhoY2WU0GWGjVYOHL3xpKp0y/Eq2e5r0mT/6b649vm7KFO6RdAdrZkYLdxphYVgvODxPB+Ebg== dependencies: - punycode "^1.3.2" + punycode "^2.0.0" strip-ansi "^3.0.1" -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== - -unicode-trie@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" - integrity sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU= - dependencies: - pako "^0.2.5" - tiny-inflate "^1.0.0" - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -11999,16 +9385,6 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -12052,11 +9428,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -12065,7 +9436,7 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.1.1, upath@^1.2.0: +upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== @@ -12090,14 +9461,6 @@ url@0.10.3: punycode "1.3.2" querystring "0.2.0" -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -12120,30 +9483,6 @@ util-promisify@^2.1.0: dependencies: object.getownpropertydescriptors "^2.0.3" -util.promisify@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - uuid@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" @@ -12159,7 +9498,7 @@ uuid@^8.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== -v8-compile-cache@^2.0.0, v8-compile-cache@^2.0.3: +v8-compile-cache@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== @@ -12188,11 +9527,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -vendors@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -12202,16 +9536,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vlq@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - w3c-hr-time@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -12235,7 +9559,7 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -wcwidth@^1.0.0, wcwidth@^1.0.1: +wcwidth@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= @@ -12299,7 +9623,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which-typed-array@^1.1.1: +which-typed-array@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== @@ -12443,20 +9767,6 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -ws@^5.1.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== - dependencies: - async-limiter "~1.0.0" - -ws@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - ws@^7.0.0: version "7.2.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" @@ -12500,7 +9810,7 @@ xregexp@2.0.0: resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= -xtend@^4.0.0, xtend@~4.0.1: +xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -12525,7 +9835,12 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yaml@*, yaml@1.9.2, yaml@^1.9.2: +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@*, yaml@1.9.2, yaml@^1.5.0, yaml@^1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.9.2.tgz#f0cfa865f003ab707663e4f04b3956957ea564ed" integrity sha512-HPT7cGGI0DuRcsO51qC1j9O16Dh1mZ2bnXwsi0jrSpsLz0WxOLSLXfkABVl6bZO629py3CU+OMJtpNHDLB97kg== @@ -12568,14 +9883,6 @@ yargs-parser@^15.0.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^16.1.0: - version "16.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" - integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" @@ -12584,10 +9891,10 @@ yargs-parser@^2.4.1: camelcase "^3.0.0" lodash.assign "^4.0.6" -yargs@15.0.2: - version "15.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3" - integrity sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q== +yargs@15.3.1, yargs@^15.0.2, yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -12599,7 +9906,7 @@ yargs@15.0.2: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^16.1.0" + yargs-parser "^18.1.1" yargs@^13.2.2: version "13.3.2" @@ -12634,23 +9941,6 @@ yargs@^14.0.0, yargs@^14.2.2: y18n "^4.0.0" yargs-parser "^15.0.1" -yargs@^15.0.2, yargs@^15.3.1: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.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 "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.1" - yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"