@cdklabs/cdk-appmod-catalog-blueprints 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/.jsii +8644 -0
  2. package/LICENSE +202 -0
  3. package/README.md +212 -0
  4. package/lib/document-processing/agentic-document-processing.d.ts +16 -0
  5. package/lib/document-processing/agentic-document-processing.js +90 -0
  6. package/lib/document-processing/base-document-processing.d.ts +189 -0
  7. package/lib/document-processing/base-document-processing.js +509 -0
  8. package/lib/document-processing/bedrock-document-processing.d.ts +167 -0
  9. package/lib/document-processing/bedrock-document-processing.js +297 -0
  10. package/lib/document-processing/index.d.ts +3 -0
  11. package/lib/document-processing/index.js +20 -0
  12. package/lib/document-processing/resources/default-bedrock-invoke/index.py +63 -0
  13. package/lib/document-processing/resources/default-bedrock-invoke/requirements.txt +4 -0
  14. package/lib/document-processing/resources/default-doc-retrieval-lambda/index.mjs +92 -0
  15. package/lib/document-processing/resources/default-doc-retrieval-lambda/package.json +10 -0
  16. package/lib/document-processing/resources/default-error-handler/index.js +46 -0
  17. package/lib/document-processing/resources/default-error-handler/package.json +4 -0
  18. package/lib/document-processing/resources/default-image-processor/classifier.mjs +665 -0
  19. package/lib/document-processing/resources/default-image-processor/extractors.mjs +465 -0
  20. package/lib/document-processing/resources/default-image-processor/index.mjs +143 -0
  21. package/lib/document-processing/resources/default-image-processor/package-lock.json +12 -0
  22. package/lib/document-processing/resources/default-image-processor/package.json +4 -0
  23. package/lib/document-processing/resources/default-image-validator/index.mjs +76 -0
  24. package/lib/document-processing/resources/default-image-validator/package-lock.json +154 -0
  25. package/lib/document-processing/resources/default-image-validator/package.json +7 -0
  26. package/lib/document-processing/resources/default-pdf-processor/index.js +46 -0
  27. package/lib/document-processing/resources/default-pdf-validator/index.js +36 -0
  28. package/lib/document-processing/resources/default-sqs-consumer/index.py +111 -0
  29. package/lib/document-processing/resources/default-sqs-consumer/requirements.txt +4 -0
  30. package/lib/document-processing/resources/default-sqs-consumer/sample_payload.json +20 -0
  31. package/lib/document-processing/resources/default-sqs-consumer/sample_payload_multi.json +24 -0
  32. package/lib/document-processing/resources/default-strands-agent/index.py +111 -0
  33. package/lib/document-processing/resources/default-strands-agent/requirements.txt +6 -0
  34. package/lib/document-processing/tests/agentic-document-processing-nag.test.d.ts +1 -0
  35. package/lib/document-processing/tests/agentic-document-processing-nag.test.js +107 -0
  36. package/lib/document-processing/tests/agentic-document-processing.test.d.ts +1 -0
  37. package/lib/document-processing/tests/agentic-document-processing.test.js +125 -0
  38. package/lib/document-processing/tests/bedrock-document-processing-nag.test.d.ts +1 -0
  39. package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +101 -0
  40. package/lib/document-processing/tests/bedrock-document-processing.test.d.ts +1 -0
  41. package/lib/document-processing/tests/bedrock-document-processing.test.js +79 -0
  42. package/lib/framework/custom-resource/default-runtimes.d.ts +21 -0
  43. package/lib/framework/custom-resource/default-runtimes.js +34 -0
  44. package/lib/framework/custom-resource/index.d.ts +1 -0
  45. package/lib/framework/custom-resource/index.js +18 -0
  46. package/lib/framework/foundation/access-log.d.ts +69 -0
  47. package/lib/framework/foundation/access-log.js +121 -0
  48. package/lib/framework/foundation/eventbridge-broker.d.ts +18 -0
  49. package/lib/framework/foundation/eventbridge-broker.js +42 -0
  50. package/lib/framework/foundation/index.d.ts +3 -0
  51. package/lib/framework/foundation/index.js +20 -0
  52. package/lib/framework/foundation/network.d.ts +19 -0
  53. package/lib/framework/foundation/network.js +83 -0
  54. package/lib/framework/index.d.ts +2 -0
  55. package/lib/framework/index.js +19 -0
  56. package/lib/framework/quickstart/base-quickstart.d.ts +30 -0
  57. package/lib/framework/quickstart/base-quickstart.js +30 -0
  58. package/lib/index.d.ts +4 -0
  59. package/lib/index.js +21 -0
  60. package/lib/tsconfig.tsbuildinfo +1 -0
  61. package/lib/utilities/cdk-nag-config.d.ts +42 -0
  62. package/lib/utilities/cdk-nag-config.js +194 -0
  63. package/lib/utilities/data-loader-lambda/index.py +282 -0
  64. package/lib/utilities/data-loader-lambda/requirements.txt +3 -0
  65. package/lib/utilities/data-loader.d.ts +173 -0
  66. package/lib/utilities/data-loader.js +447 -0
  67. package/lib/utilities/index.d.ts +3 -0
  68. package/lib/utilities/index.js +20 -0
  69. package/lib/utilities/lambda-iam-utils.d.ts +145 -0
  70. package/lib/utilities/lambda-iam-utils.js +235 -0
  71. package/lib/utilities/lambda_layers/data-masking/layer-construct.d.ts +42 -0
  72. package/lib/utilities/lambda_layers/data-masking/layer-construct.js +53 -0
  73. package/lib/utilities/lambda_layers/data-masking/layer-construct.ts +88 -0
  74. package/lib/utilities/observability/bedrock-observability.d.ts +18 -0
  75. package/lib/utilities/observability/bedrock-observability.js +131 -0
  76. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.d.ts +6 -0
  77. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +22 -0
  78. package/lib/utilities/observability/index.d.ts +6 -0
  79. package/lib/utilities/observability/index.js +25 -0
  80. package/lib/utilities/observability/lambda-observability-property-injector.d.ts +8 -0
  81. package/lib/utilities/observability/lambda-observability-property-injector.js +43 -0
  82. package/lib/utilities/observability/log-group-data-protection-props.d.ts +19 -0
  83. package/lib/utilities/observability/log-group-data-protection-props.js +5 -0
  84. package/lib/utilities/observability/observability.d.ts +83 -0
  85. package/lib/utilities/observability/observability.js +278 -0
  86. package/lib/utilities/observability/observable.d.ts +32 -0
  87. package/lib/utilities/observability/observable.js +3 -0
  88. package/lib/utilities/observability/powertools-config.d.ts +3 -0
  89. package/lib/utilities/observability/powertools-config.js +25 -0
  90. package/lib/utilities/observability/resources/bedrock-manage-logging-configuration/index.py +27 -0
  91. package/lib/utilities/observability/state-machine-observability-property-injector.d.ts +8 -0
  92. package/lib/utilities/observability/state-machine-observability-property-injector.js +49 -0
  93. package/lib/utilities/tests/data-loader-nag.test.d.ts +1 -0
  94. package/lib/utilities/tests/data-loader-nag.test.js +432 -0
  95. package/lib/utilities/tests/data-loader.test.d.ts +1 -0
  96. package/lib/utilities/tests/data-loader.test.js +284 -0
  97. package/lib/webapp/frontend-construct.d.ts +136 -0
  98. package/lib/webapp/frontend-construct.js +253 -0
  99. package/lib/webapp/index.d.ts +1 -0
  100. package/lib/webapp/index.js +18 -0
  101. package/lib/webapp/tests/frontend-construct-nag.test.d.ts +1 -0
  102. package/lib/webapp/tests/frontend-construct-nag.test.js +266 -0
  103. package/lib/webapp/tests/frontend-construct.test.d.ts +1 -0
  104. package/lib/webapp/tests/frontend-construct.test.js +385 -0
  105. package/package.json +183 -0
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Frontend = exports.DEFAULT_SPA_ERROR_RESPONSES = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
7
+ // SPDX-License-Identifier: Apache-2.0
8
+ const path = require("path");
9
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
10
+ const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
11
+ const aws_cloudfront_origins_1 = require("aws-cdk-lib/aws-cloudfront-origins");
12
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
13
+ const aws_route53_1 = require("aws-cdk-lib/aws-route53");
14
+ const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
15
+ const aws_s3_1 = require("aws-cdk-lib/aws-s3");
16
+ const aws_s3_assets_1 = require("aws-cdk-lib/aws-s3-assets");
17
+ const aws_s3_deployment_1 = require("aws-cdk-lib/aws-s3-deployment");
18
+ const constructs_1 = require("constructs");
19
+ const utilities_1 = require("../utilities");
20
+ /**
21
+ * Default CloudFront error responses for Single Page Applications
22
+ */
23
+ exports.DEFAULT_SPA_ERROR_RESPONSES = [
24
+ {
25
+ httpStatus: 403,
26
+ responseHttpStatus: 200,
27
+ responsePagePath: '/index.html',
28
+ },
29
+ {
30
+ httpStatus: 404,
31
+ responseHttpStatus: 200,
32
+ responsePagePath: '/index.html',
33
+ },
34
+ ];
35
+ /**
36
+ * Frontend construct that deploys a frontend application to S3 and CloudFront
37
+ *
38
+ * This construct provides a complete solution for hosting static frontend applications
39
+ * with the following features:
40
+ * - S3 bucket for hosting static assets with security best practices
41
+ * - CloudFront distribution for global content delivery
42
+ * - Optional custom domain with SSL certificate
43
+ * - Automatic build process execution
44
+ * - SPA-friendly error handling by default
45
+ * - Security configurations
46
+ */
47
+ class Frontend extends constructs_1.Construct {
48
+ /**
49
+ * Creates a new Frontend
50
+ * @param scope The construct scope
51
+ * @param id The construct ID
52
+ * @param props The frontend properties
53
+ */
54
+ constructor(scope, id, props) {
55
+ super(scope, id);
56
+ if (props.enableObservability) {
57
+ aws_cdk_lib_1.PropertyInjectors.of(this).add(new utilities_1.CloudfrontDistributionObservabilityPropertyInjector());
58
+ }
59
+ // Validate required parameters
60
+ this._validateProps(props);
61
+ // Get removal policy with default
62
+ const removalPolicy = props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY;
63
+ // Create asset for source code with optional bundling
64
+ if (!props.skipBuild) {
65
+ this.asset = this._createAsset(props);
66
+ }
67
+ // Create S3 bucket for hosting
68
+ this.bucket = new aws_s3_1.Bucket(this, 'FrontendBucket', {
69
+ encryption: aws_s3_1.BucketEncryption.S3_MANAGED,
70
+ blockPublicAccess: aws_s3_1.BlockPublicAccess.BLOCK_ALL,
71
+ removalPolicy: removalPolicy,
72
+ autoDeleteObjects: removalPolicy === aws_cdk_lib_1.RemovalPolicy.DESTROY,
73
+ });
74
+ // Create CloudFront distribution
75
+ this.distribution = this._createDistribution(props, removalPolicy);
76
+ // Deploy frontend assets to S3
77
+ const buildOutputDirectory = props.buildOutputDirectory || path.join(props.sourceDirectory, 'build');
78
+ this.bucketDeployment = new aws_s3_deployment_1.BucketDeployment(this, 'FrontendDeployment', {
79
+ sources: this.asset
80
+ ? [aws_s3_deployment_1.Source.bucket(this.asset.bucket, this.asset.s3ObjectKey)]
81
+ : [aws_s3_deployment_1.Source.asset(buildOutputDirectory)],
82
+ destinationBucket: this.bucket,
83
+ distribution: this.distribution,
84
+ distributionPaths: ['/*'],
85
+ });
86
+ this.bucketDeployment.handlerRole.addToPrincipalPolicy(new aws_iam_1.PolicyStatement({
87
+ effect: aws_iam_1.Effect.ALLOW,
88
+ actions: [
89
+ 'cloudfront:GetInvalidation',
90
+ 'cloudfront:CreateInvalidation',
91
+ ],
92
+ resources: ['*'],
93
+ }));
94
+ // Note: BucketDeployment doesn't support applyRemovalPolicy directly
95
+ // It will be cleaned up when the bucket is deleted due to autoDeleteObjects
96
+ // Setup custom domain if provided
97
+ if (props.customDomain) {
98
+ this.domainName = props.customDomain.domainName;
99
+ this._setupCustomDomain(props.customDomain, removalPolicy);
100
+ }
101
+ }
102
+ /**
103
+ * Validates the construct properties
104
+ * @param props The frontend properties
105
+ * @private
106
+ */
107
+ _validateProps(props) {
108
+ if (!props.sourceDirectory) {
109
+ throw new Error('sourceDirectory is required');
110
+ }
111
+ if (props.customDomain?.domainName && !props.customDomain.certificate) {
112
+ throw new Error('certificate is required when domainName is provided');
113
+ }
114
+ }
115
+ /**
116
+ * Creates an Asset for the frontend source code with bundling
117
+ * @param props The frontend properties
118
+ * @returns The Asset containing the built frontend
119
+ * @private
120
+ */
121
+ _createAsset(props) {
122
+ const buildCommand = props.buildCommand || 'npm run build';
123
+ const buildOutputDirectory = props.buildOutputDirectory || path.join(props.sourceDirectory, 'build');
124
+ // Extract the build directory name from the full path
125
+ const buildDirName = path.basename(buildOutputDirectory);
126
+ const asset = new aws_s3_assets_1.Asset(this, 'FrontendAsset', {
127
+ path: props.sourceDirectory,
128
+ bundling: {
129
+ image: aws_cdk_lib_1.DockerImage.fromRegistry('public.ecr.aws/docker/library/node:lts-alpine'),
130
+ command: [
131
+ 'sh', '-c', [
132
+ 'cd /asset-input',
133
+ 'npm ci --only=production',
134
+ buildCommand,
135
+ `cp -r ./${buildDirName}/* /asset-output/`,
136
+ ].join(' && '),
137
+ ],
138
+ user: 'root',
139
+ },
140
+ });
141
+ // Note: Asset doesn't support applyRemovalPolicy directly
142
+ // The underlying S3 objects will be managed by the asset bucket's removal policy
143
+ return asset;
144
+ }
145
+ /**
146
+ * Creates the CloudFront distribution
147
+ * @param props The frontend properties
148
+ * @param removalPolicy The removal policy to apply
149
+ * @returns The CloudFront distribution
150
+ * @private
151
+ */
152
+ _createDistribution(props, removalPolicy) {
153
+ const errorResponses = props.errorResponses || exports.DEFAULT_SPA_ERROR_RESPONSES;
154
+ // Create a CloudFront function for security headers
155
+ const securityHeadersFunction = new aws_cloudfront_1.Function(this, 'SecurityHeadersFunction', {
156
+ code: aws_cloudfront_1.FunctionCode.fromInline(`
157
+ function handler(event) {
158
+ var response = event.response;
159
+ var headers = response.headers;
160
+
161
+ // Add security headers
162
+ headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload' };
163
+ headers['content-type-options'] = { value: 'nosniff' };
164
+ headers['x-frame-options'] = { value: 'DENY' };
165
+ headers['x-content-type-options'] = { value: 'nosniff' };
166
+ headers['referrer-policy'] = { value: 'strict-origin-when-cross-origin' };
167
+ headers['permissions-policy'] = { value: 'camera=(), microphone=(), geolocation=()' };
168
+
169
+ return response;
170
+ }
171
+ `),
172
+ });
173
+ // Apply removal policy to CloudFront function
174
+ securityHeadersFunction.applyRemovalPolicy(removalPolicy);
175
+ const distributionConfig = {
176
+ defaultBehavior: {
177
+ origin: aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.bucket),
178
+ viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
179
+ functionAssociations: [
180
+ {
181
+ function: securityHeadersFunction,
182
+ eventType: aws_cloudfront_1.FunctionEventType.VIEWER_RESPONSE,
183
+ },
184
+ ],
185
+ },
186
+ defaultRootObject: 'index.html',
187
+ errorResponses,
188
+ comment: props.distributionProps?.comment,
189
+ enabled: props.distributionProps?.enabled,
190
+ priceClass: props.distributionProps?.priceClass,
191
+ webAclId: props.distributionProps?.webAclId,
192
+ };
193
+ // Add custom domain configuration if provided
194
+ let distribution;
195
+ if (props.customDomain) {
196
+ distribution = new aws_cloudfront_1.Distribution(this, 'FrontendDistribution', {
197
+ ...distributionConfig,
198
+ domainNames: [props.customDomain.domainName],
199
+ certificate: props.customDomain.certificate,
200
+ });
201
+ }
202
+ else {
203
+ distribution = new aws_cloudfront_1.Distribution(this, 'FrontendDistribution', distributionConfig);
204
+ }
205
+ // Apply removal policy to distribution
206
+ distribution.applyRemovalPolicy(removalPolicy);
207
+ return distribution;
208
+ }
209
+ /**
210
+ * Sets up custom domain with Route53 record
211
+ * @param customDomain The custom domain configuration
212
+ * @param removalPolicy The removal policy to apply
213
+ * @private
214
+ */
215
+ _setupCustomDomain(customDomain, removalPolicy) {
216
+ if (customDomain.hostedZone) {
217
+ const aliasRecord = new aws_route53_1.ARecord(this, 'FrontendAliasRecord', {
218
+ zone: customDomain.hostedZone,
219
+ recordName: customDomain.domainName,
220
+ target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.CloudFrontTarget(this.distribution)),
221
+ });
222
+ // Apply removal policy to Route53 record
223
+ aliasRecord.applyRemovalPolicy(removalPolicy);
224
+ }
225
+ }
226
+ /**
227
+ * Gets the URL of the frontend application
228
+ * @returns The frontend URL
229
+ */
230
+ url() {
231
+ return this.domainName
232
+ ? `https://${this.domainName}`
233
+ : `https://${this.distribution.distributionDomainName}`;
234
+ }
235
+ /**
236
+ * Gets the CloudFront distribution domain name
237
+ * @returns The CloudFront domain name
238
+ */
239
+ distributionDomainName() {
240
+ return this.distribution.distributionDomainName;
241
+ }
242
+ /**
243
+ * Gets the S3 bucket name
244
+ * @returns The S3 bucket name
245
+ */
246
+ bucketName() {
247
+ return this.bucket.bucketName;
248
+ }
249
+ }
250
+ exports.Frontend = Frontend;
251
+ _a = JSII_RTTI_SYMBOL_1;
252
+ Frontend[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.Frontend", version: "1.0.0" };
253
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJvbnRlbmQtY29uc3RydWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdXNlLWNhc2VzL3dlYmFwcC9mcm9udGVuZC1jb25zdHJ1Y3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxRUFBcUU7QUFDckUsc0NBQXNDO0FBRXRDLDZCQUE2QjtBQUM3Qiw2Q0FBNEU7QUFFNUUsK0RBU29DO0FBQ3BDLCtFQUFvRTtBQUNwRSxpREFBOEQ7QUFDOUQseURBQTZFO0FBQzdFLHlFQUFtRTtBQUNuRSwrQ0FBaUY7QUFDakYsNkRBQWtEO0FBQ2xELHFFQUF5RTtBQUN6RSwyQ0FBdUM7QUFDdkMsNENBQW1GO0FBRW5GOztHQUVHO0FBQ1UsUUFBQSwyQkFBMkIsR0FBb0I7SUFDMUQ7UUFDRSxVQUFVLEVBQUUsR0FBRztRQUNmLGtCQUFrQixFQUFFLEdBQUc7UUFDdkIsZ0JBQWdCLEVBQUUsYUFBYTtLQUNoQztJQUNEO1FBQ0UsVUFBVSxFQUFFLEdBQUc7UUFDZixrQkFBa0IsRUFBRSxHQUFHO1FBQ3ZCLGdCQUFnQixFQUFFLGFBQWE7S0FDaEM7Q0FDRixDQUFDO0FBdURGOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBYSxRQUFTLFNBQVEsc0JBQVM7SUFZckM7Ozs7O09BS0c7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQW9CO1FBQzVELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxLQUFLLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM5QiwrQkFBaUIsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUM1QixJQUFJLCtEQUFtRCxFQUFFLENBQzFELENBQUM7UUFDSixDQUFDO1FBRUQsK0JBQStCO1FBQy9CLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFM0Isa0NBQWtDO1FBQ2xDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLElB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cUJBQU8sQ0FBQyxJQUFJLEVBQUUscUJBQXFCLEVBQUU7Z0JBQzNELElBQUksRUFBRSxZQUFZLENBQUMsVUFBVTtnQkFDN0IsVUFBVSxFQUFFLFlBQVksQ0FBQyxVQUFVO2dCQUNuQyxNQUFNLEVBQUUsMEJBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSxzQ0FBZ0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDeEUsQ0FBQyxDQUFDO1lBRUgseUNBQXlDO1lBQ3pDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEdBQUc7UUFDUixPQUFPLElBQUksQ0FBQyxVQUFVO1lBQ3BCLENBQUMsQ0FBQyxXQUFXLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDOUIsQ0FBQyxDQUFDLFdBQVcsSUFBSSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQzVELENBQUM7SUFFRDs7O09BR0c7SUFDSSxzQkFBc0I7UUFDM0IsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLHNCQUFzQixDQUFDO0lBQ2xELENBQUM7SUFFRDs7O09BR0c7SUFDSSxVQUFVO1FBQ2YsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQztJQUNoQyxDQUFDOztBQWxQSCw0QkFtUEMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBEb2NrZXJJbWFnZSwgUHJvcGVydHlJbmplY3RvcnMsIFJlbW92YWxQb2xpY3kgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBJQ2VydGlmaWNhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyJztcbmltcG9ydCB7XG4gIERpc3RyaWJ1dGlvbixcbiAgRGlzdHJpYnV0aW9uUHJvcHMsXG4gIEVycm9yUmVzcG9uc2UsXG4gIEZ1bmN0aW9uIGFzIENsb3VkRnJvbnRGdW5jdGlvbixcbiAgRnVuY3Rpb25Db2RlLFxuICBGdW5jdGlvbkV2ZW50VHlwZSxcbiAgUHJpY2VDbGFzcyxcbiAgVmlld2VyUHJvdG9jb2xQb2xpY3ksXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZGZyb250JztcbmltcG9ydCB7IFMzQnVja2V0T3JpZ2luIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQtb3JpZ2lucyc7XG5pbXBvcnQgeyBFZmZlY3QsIFBvbGljeVN0YXRlbWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgQVJlY29yZCwgSUhvc3RlZFpvbmUsIFJlY29yZFRhcmdldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1yb3V0ZTUzJztcbmltcG9ydCB7IENsb3VkRnJvbnRUYXJnZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1My10YXJnZXRzJztcbmltcG9ydCB7IEJsb2NrUHVibGljQWNjZXNzLCBCdWNrZXQsIEJ1Y2tldEVuY3J5cHRpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0IHsgQXNzZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMtYXNzZXRzJztcbmltcG9ydCB7IEJ1Y2tldERlcGxveW1lbnQsIFNvdXJjZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMy1kZXBsb3ltZW50JztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQ2xvdWRmcm9udERpc3RyaWJ1dGlvbk9ic2VydmFiaWxpdHlQcm9wZXJ0eUluamVjdG9yIH0gZnJvbSAnLi4vdXRpbGl0aWVzJztcblxuLyoqXG4gKiBEZWZhdWx0IENsb3VkRnJvbnQgZXJyb3IgcmVzcG9uc2VzIGZvciBTaW5nbGUgUGFnZSBBcHBsaWNhdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfU1BBX0VSUk9SX1JFU1BPTlNFUzogRXJyb3JSZXNwb25zZVtdID0gW1xuICB7XG4gICAgaHR0cFN0YXR1czogNDAzLFxuICAgIHJlc3BvbnNlSHR0cFN0YXR1czogMjAwLFxuICAgIHJlc3BvbnNlUGFnZVBhdGg6ICcvaW5kZXguaHRtbCcsXG4gIH0sXG4gIHtcbiAgICBodHRwU3RhdHVzOiA0MDQsXG4gICAgcmVzcG9uc2VIdHRwU3RhdHVzOiAyMDAsXG4gICAgcmVzcG9uc2VQYWdlUGF0aDogJy9pbmRleC5odG1sJyxcbiAgfSxcbl07XG5cbi8qKlxuICogQ3VzdG9tIGRvbWFpbiBjb25maWd1cmF0aW9uIGZvciB0aGUgZnJvbnRlbmRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDdXN0b21Eb21haW5Db25maWcge1xuICAvKiogRG9tYWluIG5hbWUgZm9yIHRoZSBmcm9udGVuZCAoZS5nLiwgJ2FwcC5leGFtcGxlLmNvbScpICovXG4gIHJlYWRvbmx5IGRvbWFpbk5hbWU6IHN0cmluZztcbiAgLyoqIFNTTCBjZXJ0aWZpY2F0ZSBmb3IgdGhlIGRvbWFpbiAocmVxdWlyZWQgd2hlbiBkb21haW5OYW1lIGlzIHByb3ZpZGVkKSAqL1xuICByZWFkb25seSBjZXJ0aWZpY2F0ZTogSUNlcnRpZmljYXRlO1xuICAvKiogT3B0aW9uYWwgaG9zdGVkIHpvbmUgZm9yIGF1dG9tYXRpYyBETlMgcmVjb3JkIGNyZWF0aW9uICovXG4gIHJlYWRvbmx5IGhvc3RlZFpvbmU/OiBJSG9zdGVkWm9uZTtcbn1cblxuLyoqXG4gKiBBZGRpdGlvbmFsIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGRpdGlvbmFsRGlzdHJpYnV0aW9uUHJvcHMge1xuICAvKiogT3B0aW9uYWwgY29tbWVudCBmb3IgdGhlIGRpc3RyaWJ1dGlvbiAqL1xuICByZWFkb25seSBjb21tZW50Pzogc3RyaW5nO1xuICAvKiogT3B0aW9uYWwgZW5hYmxlZCBmbGFnIGZvciB0aGUgZGlzdHJpYnV0aW9uICovXG4gIHJlYWRvbmx5IGVuYWJsZWQ/OiBib29sZWFuO1xuICAvKiogT3B0aW9uYWwgcHJpY2UgY2xhc3MgZm9yIHRoZSBkaXN0cmlidXRpb24gKi9cbiAgcmVhZG9ubHkgcHJpY2VDbGFzcz86IFByaWNlQ2xhc3M7XG4gIC8qKiBPcHRpb25hbCB3ZWIgQUNMIElEIGZvciB0aGUgZGlzdHJpYnV0aW9uICovXG4gIHJlYWRvbmx5IHdlYkFjbElkPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIHRoZSBGcm9udGVuZCBjb25zdHJ1Y3RcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBGcm9udGVuZFByb3BzIHtcbiAgLyoqIEJhc2UgZGlyZWN0b3J5IG9mIHRoZSBmcm9udGVuZCBzb3VyY2UgY29kZSAqL1xuICByZWFkb25seSBzb3VyY2VEaXJlY3Rvcnk6IHN0cmluZztcbiAgLyoqIERpcmVjdG9yeSB3aGVyZSBidWlsZCBhcnRpZmFjdHMgYXJlIGxvY2F0ZWQgYWZ0ZXIgYnVpbGQgY29tbWFuZCBjb21wbGV0ZXMgKGRlZmF1bHRzIHRvICd7c291cmNlRGlyZWN0b3J5fS9idWlsZCcpICovXG4gIHJlYWRvbmx5IGJ1aWxkT3V0cHV0RGlyZWN0b3J5Pzogc3RyaW5nO1xuICAvKiogT3B0aW9uYWwgYnVpbGQgY29tbWFuZCAoZGVmYXVsdHMgdG8gJ25wbSBydW4gYnVpbGQnKSAqL1xuICByZWFkb25seSBidWlsZENvbW1hbmQ/OiBzdHJpbmc7XG4gIC8qKiBPcHRpb25hbCBjdXN0b20gZG9tYWluIGNvbmZpZ3VyYXRpb24gKi9cbiAgcmVhZG9ubHkgY3VzdG9tRG9tYWluPzogQ3VzdG9tRG9tYWluQ29uZmlnO1xuICAvKiogT3B0aW9uYWwgQ2xvdWRGcm9udCBlcnJvciByZXNwb25zZXMgKGRlZmF1bHRzIHRvIFNQQS1mcmllbmRseSByZXNwb25zZXMpICovXG4gIHJlYWRvbmx5IGVycm9yUmVzcG9uc2VzPzogRXJyb3JSZXNwb25zZVtdO1xuICAvKiogT3B0aW9uYWwgYWRkaXRpb25hbCBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbiBwcm9wZXJ0aWVzICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvblByb3BzPzogQWRkaXRpb25hbERpc3RyaWJ1dGlvblByb3BzO1xuICAvKiogT3B0aW9uYWwgZmxhZyB0byBza2lwIHRoZSBidWlsZCBwcm9jZXNzICh1c2VmdWwgZm9yIHByZS1idWlsdCBhcnRpZmFjdHMpICovXG4gIHJlYWRvbmx5IHNraXBCdWlsZD86IGJvb2xlYW47XG4gIC8qKiBPcHRpb25hbCByZW1vdmFsIHBvbGljeSBmb3IgYWxsIHJlc291cmNlcyAoZGVmYXVsdHMgdG8gREVTVFJPWSkgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG4gIC8qKlxuICAgKiBFbmFibGUgbG9nZ2luZyBhbmQgdHJhY2luZyBmb3IgYWxsIHN1cHBvcnRpbmcgcmVzb3VyY2VcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZU9ic2VydmFiaWxpdHk/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEZyb250ZW5kIGNvbnN0cnVjdCB0aGF0IGRlcGxveXMgYSBmcm9udGVuZCBhcHBsaWNhdGlvbiB0byBTMyBhbmQgQ2xvdWRGcm9udFxuICpcbiAqIFRoaXMgY29uc3RydWN0IHByb3ZpZGVzIGEgY29tcGxldGUgc29sdXRpb24gZm9yIGhvc3Rpbmcgc3RhdGljIGZyb250ZW5kIGFwcGxpY2F0aW9uc1xuICogd2l0aCB0aGUgZm9sbG93aW5nIGZlYXR1cmVzOlxuICogLSBTMyBidWNrZXQgZm9yIGhvc3Rpbmcgc3RhdGljIGFzc2V0cyB3aXRoIHNlY3VyaXR5IGJlc3QgcHJhY3RpY2VzXG4gKiAtIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIGZvciBnbG9iYWwgY29udGVudCBkZWxpdmVyeVxuICogLSBPcHRpb25hbCBjdXN0b20gZG9tYWluIHdpdGggU1NMIGNlcnRpZmljYXRlXG4gKiAtIEF1dG9tYXRpYyBidWlsZCBwcm9jZXNzIGV4ZWN1dGlvblxuICogLSBTUEEtZnJpZW5kbHkgZXJyb3IgaGFuZGxpbmcgYnkgZGVmYXVsdFxuICogLSBTZWN1cml0eSBjb25maWd1cmF0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgRnJvbnRlbmQgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKiogVGhlIFMzIGJ1Y2tldCBob3N0aW5nIHRoZSBmcm9udGVuZCBhc3NldHMgKi9cbiAgcHVibGljIHJlYWRvbmx5IGJ1Y2tldDogQnVja2V0O1xuICAvKiogVGhlIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uICovXG4gIHB1YmxpYyByZWFkb25seSBkaXN0cmlidXRpb246IERpc3RyaWJ1dGlvbjtcbiAgLyoqIFRoZSBidWNrZXQgZGVwbG95bWVudCB0aGF0IHVwbG9hZHMgdGhlIGZyb250ZW5kIGFzc2V0cyAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYnVja2V0RGVwbG95bWVudDogQnVja2V0RGVwbG95bWVudDtcbiAgLyoqIFRoZSBjdXN0b20gZG9tYWluIG5hbWUgKGlmIGNvbmZpZ3VyZWQpICovXG4gIHB1YmxpYyByZWFkb25seSBkb21haW5OYW1lPzogc3RyaW5nO1xuICAvKiogVGhlIEFzc2V0IGNvbnRhaW5pbmcgdGhlIGZyb250ZW5kIHNvdXJjZSBjb2RlICovXG4gIHB1YmxpYyByZWFkb25seSBhc3NldD86IEFzc2V0O1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEZyb250ZW5kXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgY29uc3RydWN0IHNjb3BlXG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0IElEXG4gICAqIEBwYXJhbSBwcm9wcyBUaGUgZnJvbnRlbmQgcHJvcGVydGllc1xuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEZyb250ZW5kUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgaWYgKHByb3BzLmVuYWJsZU9ic2VydmFiaWxpdHkpIHtcbiAgICAgIFByb3BlcnR5SW5qZWN0b3JzLm9mKHRoaXMpLmFkZChcbiAgICAgICAgbmV3IENsb3VkZnJvbnREaXN0cmlidXRpb25PYnNlcnZhYmlsaXR5UHJvcGVydHlJbmplY3RvcigpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSByZXF1aXJlZCBwYXJhbWV0ZXJzXG4gICAgdGhpcy5fdmFsaWRhdGVQcm9wcyhwcm9wcyk7XG5cbiAgICAvLyBHZXQgcmVtb3ZhbCBwb2xpY3kgd2l0aCBkZWZhdWx0XG4gICAgY29uc3QgcmVtb3ZhbFBvbGljeSA9IHByb3BzLnJlbW92YWxQb2xpY3kgfHwgUmVtb3ZhbFBvbGljeS5ERVNUUk9ZO1xuXG4gICAgLy8gQ3JlYXRlIGFzc2V0IGZvciBzb3VyY2UgY29kZSB3aXRoIG9wdGlvbmFsIGJ1bmRsaW5nXG4gICAgaWYgKCFwcm9wcy5za2lwQnVpbGQpIHtcbiAgICAgIHRoaXMuYXNzZXQgPSB0aGlzLl9jcmVhdGVBc3NldChwcm9wcyk7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIFMzIGJ1Y2tldCBmb3IgaG9zdGluZ1xuICAgIHRoaXMuYnVja2V0ID0gbmV3IEJ1Y2tldCh0aGlzLCAnRnJvbnRlbmRCdWNrZXQnLCB7XG4gICAgICBlbmNyeXB0aW9uOiBCdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRUQsXG4gICAgICBibG9ja1B1YmxpY0FjY2VzczogQmxvY2tQdWJsaWNBY2Nlc3MuQkxPQ0tfQUxMLFxuICAgICAgcmVtb3ZhbFBvbGljeTogcmVtb3ZhbFBvbGljeSxcbiAgICAgIGF1dG9EZWxldGVPYmplY3RzOiByZW1vdmFsUG9saWN5ID09PSBSZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb25cbiAgICB0aGlzLmRpc3RyaWJ1dGlvbiA9IHRoaXMuX2NyZWF0ZURpc3RyaWJ1dGlvbihwcm9wcywgcmVtb3ZhbFBvbGljeSk7XG5cbiAgICAvLyBEZXBsb3kgZnJvbnRlbmQgYXNzZXRzIHRvIFMzXG4gICAgY29uc3QgYnVpbGRPdXRwdXREaXJlY3RvcnkgPSBwcm9wcy5idWlsZE91dHB1dERpcmVjdG9yeSB8fCBwYXRoLmpvaW4ocHJvcHMuc291cmNlRGlyZWN0b3J5LCAnYnVpbGQnKTtcbiAgICB0aGlzLmJ1Y2tldERlcGxveW1lbnQgPSBuZXcgQnVja2V0RGVwbG95bWVudCh0aGlzLCAnRnJvbnRlbmREZXBsb3ltZW50Jywge1xuICAgICAgc291cmNlczogdGhpcy5hc3NldFxuICAgICAgICA/IFtTb3VyY2UuYnVja2V0KHRoaXMuYXNzZXQuYnVja2V0LCB0aGlzLmFzc2V0LnMzT2JqZWN0S2V5KV1cbiAgICAgICAgOiBbU291cmNlLmFzc2V0KGJ1aWxkT3V0cHV0RGlyZWN0b3J5KV0sXG4gICAgICBkZXN0aW5hdGlvbkJ1Y2tldDogdGhpcy5idWNrZXQsXG4gICAgICBkaXN0cmlidXRpb246IHRoaXMuZGlzdHJpYnV0aW9uLFxuICAgICAgZGlzdHJpYnV0aW9uUGF0aHM6IFsnLyonXSxcbiAgICB9KTtcblxuICAgIHRoaXMuYnVja2V0RGVwbG95bWVudC5oYW5kbGVyUm9sZS5hZGRUb1ByaW5jaXBhbFBvbGljeShuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAnY2xvdWRmcm9udDpHZXRJbnZhbGlkYXRpb24nLFxuICAgICAgICAnY2xvdWRmcm9udDpDcmVhdGVJbnZhbGlkYXRpb24nLFxuICAgICAgXSxcbiAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgfSkpO1xuXG4gICAgLy8gTm90ZTogQnVja2V0RGVwbG95bWVudCBkb2Vzbid0IHN1cHBvcnQgYXBwbHlSZW1vdmFsUG9saWN5IGRpcmVjdGx5XG4gICAgLy8gSXQgd2lsbCBiZSBjbGVhbmVkIHVwIHdoZW4gdGhlIGJ1Y2tldCBpcyBkZWxldGVkIGR1ZSB0byBhdXRvRGVsZXRlT2JqZWN0c1xuXG4gICAgLy8gU2V0dXAgY3VzdG9tIGRvbWFpbiBpZiBwcm92aWRlZFxuICAgIGlmIChwcm9wcy5jdXN0b21Eb21haW4pIHtcbiAgICAgIHRoaXMuZG9tYWluTmFtZSA9IHByb3BzLmN1c3RvbURvbWFpbi5kb21haW5OYW1lO1xuICAgICAgdGhpcy5fc2V0dXBDdXN0b21Eb21haW4ocHJvcHMuY3VzdG9tRG9tYWluLCByZW1vdmFsUG9saWN5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBjb25zdHJ1Y3QgcHJvcGVydGllc1xuICAgKiBAcGFyYW0gcHJvcHMgVGhlIGZyb250ZW5kIHByb3BlcnRpZXNcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgX3ZhbGlkYXRlUHJvcHMocHJvcHM6IEZyb250ZW5kUHJvcHMpOiB2b2lkIHtcbiAgICBpZiAoIXByb3BzLnNvdXJjZURpcmVjdG9yeSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2VEaXJlY3RvcnkgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuY3VzdG9tRG9tYWluPy5kb21haW5OYW1lICYmICFwcm9wcy5jdXN0b21Eb21haW4uY2VydGlmaWNhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2VydGlmaWNhdGUgaXMgcmVxdWlyZWQgd2hlbiBkb21haW5OYW1lIGlzIHByb3ZpZGVkJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gQXNzZXQgZm9yIHRoZSBmcm9udGVuZCBzb3VyY2UgY29kZSB3aXRoIGJ1bmRsaW5nXG4gICAqIEBwYXJhbSBwcm9wcyBUaGUgZnJvbnRlbmQgcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBUaGUgQXNzZXQgY29udGFpbmluZyB0aGUgYnVpbHQgZnJvbnRlbmRcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgX2NyZWF0ZUFzc2V0KHByb3BzOiBGcm9udGVuZFByb3BzKTogQXNzZXQge1xuICAgIGNvbnN0IGJ1aWxkQ29tbWFuZCA9IHByb3BzLmJ1aWxkQ29tbWFuZCB8fCAnbnBtIHJ1biBidWlsZCc7XG4gICAgY29uc3QgYnVpbGRPdXRwdXREaXJlY3RvcnkgPSBwcm9wcy5idWlsZE91dHB1dERpcmVjdG9yeSB8fCBwYXRoLmpvaW4ocHJvcHMuc291cmNlRGlyZWN0b3J5LCAnYnVpbGQnKTtcblxuICAgIC8vIEV4dHJhY3QgdGhlIGJ1aWxkIGRpcmVjdG9yeSBuYW1lIGZyb20gdGhlIGZ1bGwgcGF0aFxuICAgIGNvbnN0IGJ1aWxkRGlyTmFtZSA9IHBhdGguYmFzZW5hbWUoYnVpbGRPdXRwdXREaXJlY3RvcnkpO1xuXG4gICAgY29uc3QgYXNzZXQgPSBuZXcgQXNzZXQodGhpcywgJ0Zyb250ZW5kQXNzZXQnLCB7XG4gICAgICBwYXRoOiBwcm9wcy5zb3VyY2VEaXJlY3RvcnksXG4gICAgICBidW5kbGluZzoge1xuICAgICAgICBpbWFnZTogRG9ja2VySW1hZ2UuZnJvbVJlZ2lzdHJ5KCdwdWJsaWMuZWNyLmF3cy9kb2NrZXIvbGlicmFyeS9ub2RlOmx0cy1hbHBpbmUnKSxcbiAgICAgICAgY29tbWFuZDogW1xuICAgICAgICAgICdzaCcsICctYycsIFtcbiAgICAgICAgICAgICdjZCAvYXNzZXQtaW5wdXQnLFxuICAgICAgICAgICAgJ25wbSBjaSAtLW9ubHk9cHJvZHVjdGlvbicsXG4gICAgICAgICAgICBidWlsZENvbW1hbmQsXG4gICAgICAgICAgICBgY3AgLXIgLi8ke2J1aWxkRGlyTmFtZX0vKiAvYXNzZXQtb3V0cHV0L2AsXG4gICAgICAgICAgXS5qb2luKCcgJiYgJyksXG4gICAgICAgIF0sXG4gICAgICAgIHVzZXI6ICdyb290JyxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBOb3RlOiBBc3NldCBkb2Vzbid0IHN1cHBvcnQgYXBwbHlSZW1vdmFsUG9saWN5IGRpcmVjdGx5XG4gICAgLy8gVGhlIHVuZGVybHlpbmcgUzMgb2JqZWN0cyB3aWxsIGJlIG1hbmFnZWQgYnkgdGhlIGFzc2V0IGJ1Y2tldCdzIHJlbW92YWwgcG9saWN5XG5cbiAgICByZXR1cm4gYXNzZXQ7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb25cbiAgICogQHBhcmFtIHByb3BzIFRoZSBmcm9udGVuZCBwcm9wZXJ0aWVzXG4gICAqIEBwYXJhbSByZW1vdmFsUG9saWN5IFRoZSByZW1vdmFsIHBvbGljeSB0byBhcHBseVxuICAgKiBAcmV0dXJucyBUaGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb25cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgX2NyZWF0ZURpc3RyaWJ1dGlvbihwcm9wczogRnJvbnRlbmRQcm9wcywgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeSk6IERpc3RyaWJ1dGlvbiB7XG4gICAgY29uc3QgZXJyb3JSZXNwb25zZXMgPSBwcm9wcy5lcnJvclJlc3BvbnNlcyB8fCBERUZBVUxUX1NQQV9FUlJPUl9SRVNQT05TRVM7XG5cbiAgICAvLyBDcmVhdGUgYSBDbG91ZEZyb250IGZ1bmN0aW9uIGZvciBzZWN1cml0eSBoZWFkZXJzXG4gICAgY29uc3Qgc2VjdXJpdHlIZWFkZXJzRnVuY3Rpb24gPSBuZXcgQ2xvdWRGcm9udEZ1bmN0aW9uKHRoaXMsICdTZWN1cml0eUhlYWRlcnNGdW5jdGlvbicsIHtcbiAgICAgIGNvZGU6IEZ1bmN0aW9uQ29kZS5mcm9tSW5saW5lKGBcbiAgICAgICAgZnVuY3Rpb24gaGFuZGxlcihldmVudCkge1xuICAgICAgICAgIHZhciByZXNwb25zZSA9IGV2ZW50LnJlc3BvbnNlO1xuICAgICAgICAgIHZhciBoZWFkZXJzID0gcmVzcG9uc2UuaGVhZGVycztcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBBZGQgc2VjdXJpdHkgaGVhZGVyc1xuICAgICAgICAgIGhlYWRlcnNbJ3N0cmljdC10cmFuc3BvcnQtc2VjdXJpdHknXSA9IHsgdmFsdWU6ICdtYXgtYWdlPTYzMDcyMDAwOyBpbmNsdWRlU3ViZG9tYWluczsgcHJlbG9hZCcgfTtcbiAgICAgICAgICBoZWFkZXJzWydjb250ZW50LXR5cGUtb3B0aW9ucyddID0geyB2YWx1ZTogJ25vc25pZmYnIH07XG4gICAgICAgICAgaGVhZGVyc1sneC1mcmFtZS1vcHRpb25zJ10gPSB7IHZhbHVlOiAnREVOWScgfTtcbiAgICAgICAgICBoZWFkZXJzWyd4LWNvbnRlbnQtdHlwZS1vcHRpb25zJ10gPSB7IHZhbHVlOiAnbm9zbmlmZicgfTtcbiAgICAgICAgICBoZWFkZXJzWydyZWZlcnJlci1wb2xpY3knXSA9IHsgdmFsdWU6ICdzdHJpY3Qtb3JpZ2luLXdoZW4tY3Jvc3Mtb3JpZ2luJyB9O1xuICAgICAgICAgIGhlYWRlcnNbJ3Blcm1pc3Npb25zLXBvbGljeSddID0geyB2YWx1ZTogJ2NhbWVyYT0oKSwgbWljcm9waG9uZT0oKSwgZ2VvbG9jYXRpb249KCknIH07XG4gICAgICAgICAgXG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9XG4gICAgICBgKSxcbiAgICB9KTtcblxuICAgIC8vIEFwcGx5IHJlbW92YWwgcG9saWN5IHRvIENsb3VkRnJvbnQgZnVuY3Rpb25cbiAgICBzZWN1cml0eUhlYWRlcnNGdW5jdGlvbi5hcHBseVJlbW92YWxQb2xpY3kocmVtb3ZhbFBvbGljeSk7XG5cbiAgICBjb25zdCBkaXN0cmlidXRpb25Db25maWc6IERpc3RyaWJ1dGlvblByb3BzID0ge1xuICAgICAgZGVmYXVsdEJlaGF2aW9yOiB7XG4gICAgICAgIG9yaWdpbjogUzNCdWNrZXRPcmlnaW4ud2l0aE9yaWdpbkFjY2Vzc0NvbnRyb2wodGhpcy5idWNrZXQpLFxuICAgICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAgIGZ1bmN0aW9uQXNzb2NpYXRpb25zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZnVuY3Rpb246IHNlY3VyaXR5SGVhZGVyc0Z1bmN0aW9uLFxuICAgICAgICAgICAgZXZlbnRUeXBlOiBGdW5jdGlvbkV2ZW50VHlwZS5WSUVXRVJfUkVTUE9OU0UsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICBkZWZhdWx0Um9vdE9iamVjdDogJ2luZGV4Lmh0bWwnLFxuICAgICAgZXJyb3JSZXNwb25zZXMsXG4gICAgICBjb21tZW50OiBwcm9wcy5kaXN0cmlidXRpb25Qcm9wcz8uY29tbWVudCxcbiAgICAgIGVuYWJsZWQ6IHByb3BzLmRpc3RyaWJ1dGlvblByb3BzPy5lbmFibGVkLFxuICAgICAgcHJpY2VDbGFzczogcHJvcHMuZGlzdHJpYnV0aW9uUHJvcHM/LnByaWNlQ2xhc3MsXG4gICAgICB3ZWJBY2xJZDogcHJvcHMuZGlzdHJpYnV0aW9uUHJvcHM/LndlYkFjbElkLFxuICAgIH07XG5cbiAgICAvLyBBZGQgY3VzdG9tIGRvbWFpbiBjb25maWd1cmF0aW9uIGlmIHByb3ZpZGVkXG4gICAgbGV0IGRpc3RyaWJ1dGlvbjogRGlzdHJpYnV0aW9uO1xuICAgIGlmIChwcm9wcy5jdXN0b21Eb21haW4pIHtcbiAgICAgIGRpc3RyaWJ1dGlvbiA9IG5ldyBEaXN0cmlidXRpb24odGhpcywgJ0Zyb250ZW5kRGlzdHJpYnV0aW9uJywge1xuICAgICAgICAuLi5kaXN0cmlidXRpb25Db25maWcsXG4gICAgICAgIGRvbWFpbk5hbWVzOiBbcHJvcHMuY3VzdG9tRG9tYWluLmRvbWFpbk5hbWVdLFxuICAgICAgICBjZXJ0aWZpY2F0ZTogcHJvcHMuY3VzdG9tRG9tYWluLmNlcnRpZmljYXRlLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpc3RyaWJ1dGlvbiA9IG5ldyBEaXN0cmlidXRpb24odGhpcywgJ0Zyb250ZW5kRGlzdHJpYnV0aW9uJywgZGlzdHJpYnV0aW9uQ29uZmlnKTtcbiAgICB9XG5cbiAgICAvLyBBcHBseSByZW1vdmFsIHBvbGljeSB0byBkaXN0cmlidXRpb25cbiAgICBkaXN0cmlidXRpb24uYXBwbHlSZW1vdmFsUG9saWN5KHJlbW92YWxQb2xpY3kpO1xuXG4gICAgcmV0dXJuIGRpc3RyaWJ1dGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHVwIGN1c3RvbSBkb21haW4gd2l0aCBSb3V0ZTUzIHJlY29yZFxuICAgKiBAcGFyYW0gY3VzdG9tRG9tYWluIFRoZSBjdXN0b20gZG9tYWluIGNvbmZpZ3VyYXRpb25cbiAgICogQHBhcmFtIHJlbW92YWxQb2xpY3kgVGhlIHJlbW92YWwgcG9saWN5IHRvIGFwcGx5XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIF9zZXR1cEN1c3RvbURvbWFpbihjdXN0b21Eb21haW46IEN1c3RvbURvbWFpbkNvbmZpZywgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeSk6IHZvaWQge1xuICAgIGlmIChjdXN0b21Eb21haW4uaG9zdGVkWm9uZSkge1xuICAgICAgY29uc3QgYWxpYXNSZWNvcmQgPSBuZXcgQVJlY29yZCh0aGlzLCAnRnJvbnRlbmRBbGlhc1JlY29yZCcsIHtcbiAgICAgICAgem9uZTogY3VzdG9tRG9tYWluLmhvc3RlZFpvbmUsXG4gICAgICAgIHJlY29yZE5hbWU6IGN1c3RvbURvbWFpbi5kb21haW5OYW1lLFxuICAgICAgICB0YXJnZXQ6IFJlY29yZFRhcmdldC5mcm9tQWxpYXMobmV3IENsb3VkRnJvbnRUYXJnZXQodGhpcy5kaXN0cmlidXRpb24pKSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBBcHBseSByZW1vdmFsIHBvbGljeSB0byBSb3V0ZTUzIHJlY29yZFxuICAgICAgYWxpYXNSZWNvcmQuYXBwbHlSZW1vdmFsUG9saWN5KHJlbW92YWxQb2xpY3kpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBVUkwgb2YgdGhlIGZyb250ZW5kIGFwcGxpY2F0aW9uXG4gICAqIEByZXR1cm5zIFRoZSBmcm9udGVuZCBVUkxcbiAgICovXG4gIHB1YmxpYyB1cmwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5kb21haW5OYW1lXG4gICAgICA/IGBodHRwczovLyR7dGhpcy5kb21haW5OYW1lfWBcbiAgICAgIDogYGh0dHBzOi8vJHt0aGlzLmRpc3RyaWJ1dGlvbi5kaXN0cmlidXRpb25Eb21haW5OYW1lfWA7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gZG9tYWluIG5hbWVcbiAgICogQHJldHVybnMgVGhlIENsb3VkRnJvbnQgZG9tYWluIG5hbWVcbiAgICovXG4gIHB1YmxpYyBkaXN0cmlidXRpb25Eb21haW5OYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbkRvbWFpbk5hbWU7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgUzMgYnVja2V0IG5hbWVcbiAgICogQHJldHVybnMgVGhlIFMzIGJ1Y2tldCBuYW1lXG4gICAqL1xuICBwdWJsaWMgYnVja2V0TmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmJ1Y2tldC5idWNrZXROYW1lO1xuICB9XG59XG4iXX0=
@@ -0,0 +1 @@
1
+ export * from './frontend-construct';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./frontend-construct"), exports);
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi91c2UtY2FzZXMvd2ViYXBwL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1REFBcUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2Zyb250ZW5kLWNvbnN0cnVjdCc7Il19
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
8
+ const assertions_1 = require("aws-cdk-lib/assertions");
9
+ const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
10
+ const aws_route53_1 = require("aws-cdk-lib/aws-route53");
11
+ const cdk_nag_1 = require("cdk-nag");
12
+ const frontend_construct_1 = require("../frontend-construct");
13
+ // Create temporary build directory for tests
14
+ const testBuildDir = '/tmp/test-frontend-build-nag';
15
+ if (!fs.existsSync(testBuildDir)) {
16
+ fs.mkdirSync(testBuildDir, { recursive: true });
17
+ }
18
+ fs.writeFileSync(path.join(testBuildDir, 'index.html'), '<!DOCTYPE html><html><head><title>Test</title></head><body><h1>Test App</h1></body></html>');
19
+ // Create app and stack
20
+ const app = new aws_cdk_lib_1.App();
21
+ const stack = new aws_cdk_lib_1.Stack(app, 'TestStack', {
22
+ env: {
23
+ account: '123456789012',
24
+ region: 'us-east-1',
25
+ },
26
+ });
27
+ // Create SSL certificate for custom domain testing
28
+ const certificate = aws_certificatemanager_1.Certificate.fromCertificateArn(stack, 'Certificate', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012');
29
+ // Create hosted zone for DNS testing
30
+ const hostedZone = aws_route53_1.HostedZone.fromHostedZoneAttributes(stack, 'HostedZone', {
31
+ hostedZoneId: 'Z123456789',
32
+ zoneName: 'example.com',
33
+ });
34
+ // Create the main Frontend construct
35
+ const frontend = new frontend_construct_1.Frontend(stack, 'TestFrontend', {
36
+ sourceDirectory: '/tmp/test-frontend-src',
37
+ buildOutputDirectory: testBuildDir,
38
+ customDomain: {
39
+ domainName: 'app.example.com',
40
+ certificate,
41
+ hostedZone,
42
+ },
43
+ skipBuild: true, // Skip build for testing
44
+ });
45
+ // Add CDK Nag suppressions for known acceptable violations
46
+ cdk_nag_1.NagSuppressions.addResourceSuppressions(stack, [
47
+ {
48
+ id: 'AwsSolutions-CFR1',
49
+ reason: 'CloudFront geo restrictions are configured based on application requirements',
50
+ },
51
+ {
52
+ id: 'AwsSolutions-CFR2',
53
+ reason: 'CloudFront WAF integration is configured based on security requirements',
54
+ },
55
+ {
56
+ id: 'AwsSolutions-CFR3',
57
+ reason: 'CloudFront access logging is configured based on compliance requirements',
58
+ },
59
+ {
60
+ id: 'AwsSolutions-CFR4',
61
+ reason: 'CloudFront viewer protocol policy is set to redirect-to-https for security',
62
+ },
63
+ {
64
+ id: 'AwsSolutions-S1',
65
+ reason: 'S3 bucket access logging is configured based on compliance requirements',
66
+ },
67
+ {
68
+ id: 'AwsSolutions-S2',
69
+ reason: 'S3 bucket public access is blocked and access is controlled via CloudFront OAC',
70
+ },
71
+ {
72
+ id: 'AwsSolutions-S3',
73
+ reason: 'S3 bucket SSL requests only policy is enforced via CloudFront HTTPS redirect',
74
+ },
75
+ {
76
+ id: 'AwsSolutions-S10',
77
+ reason: 'S3 bucket MFA delete is managed through organizational security policies',
78
+ },
79
+ {
80
+ id: 'AwsSolutions-IAM4',
81
+ reason: 'AWS managed policies are acceptable for standard Lambda execution roles',
82
+ appliesTo: ['Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'],
83
+ },
84
+ {
85
+ id: 'AwsSolutions-IAM5',
86
+ reason: 'BucketDeployment requires broad S3 permissions to manage deployment assets',
87
+ appliesTo: [
88
+ 'Action::s3:GetObject*',
89
+ 'Action::s3:GetBucket*',
90
+ 'Action::s3:List*',
91
+ 'Action::s3:DeleteObject*',
92
+ 'Action::s3:Abort*',
93
+ 'Resource::arn:<AWS::Partition>:s3:::cdk-hnb659fds-assets-<AWS::AccountId>-<AWS::Region>/*',
94
+ 'Resource::arn:<AWS::Partition>:s3:::cdk-hnb659fds-assets-123456789012-us-east-1/*',
95
+ 'Resource::<TestFrontendFrontendBucketD37D22DE.Arn>/*',
96
+ 'Resource::*',
97
+ ],
98
+ },
99
+ {
100
+ id: 'AwsSolutions-L1',
101
+ reason: 'Lambda runtime versions are managed at the application deployment level',
102
+ },
103
+ ], true);
104
+ // Apply CDK Nag checks
105
+ aws_cdk_lib_1.Aspects.of(app).add(new cdk_nag_1.AwsSolutionsChecks({ verbose: true }));
106
+ // Synthesize the stack
107
+ assertions_1.Template.fromStack(stack);
108
+ // Check for unsuppressed warnings and errors
109
+ const warnings = assertions_1.Annotations.fromStack(stack).findWarning('*', assertions_1.Match.stringLikeRegexp('AwsSolutions-.*'));
110
+ const errors = assertions_1.Annotations.fromStack(stack).findError('*', assertions_1.Match.stringLikeRegexp('AwsSolutions-.*'));
111
+ // Test: Frontend construct is properly created and accessible
112
+ test('Frontend construct is created successfully', () => {
113
+ expect(frontend).toBeDefined();
114
+ expect(frontend.node.id).toBe('TestFrontend');
115
+ expect(frontend.bucket).toBeDefined();
116
+ expect(frontend.distribution).toBeDefined();
117
+ expect(frontend.bucketDeployment).toBeDefined();
118
+ });
119
+ // Test: Frontend construct has expected properties
120
+ test('Frontend construct has expected properties', () => {
121
+ expect(frontend.bucket.bucketName).toBeDefined();
122
+ expect(frontend.distribution.distributionId).toBeDefined();
123
+ expect(frontend.domainName).toBe('app.example.com');
124
+ expect(frontend.url()).toBe('https://app.example.com');
125
+ expect(typeof frontend.bucketName()).toBe('string');
126
+ expect(typeof frontend.distributionDomainName()).toBe('string');
127
+ });
128
+ // Test: Template contains expected frontend resources
129
+ test('Template contains expected frontend resources', () => {
130
+ const template = assertions_1.Template.fromStack(stack);
131
+ // Verify S3 bucket exists with security configuration
132
+ template.hasResourceProperties('AWS::S3::Bucket', {
133
+ BucketEncryption: {
134
+ ServerSideEncryptionConfiguration: [
135
+ {
136
+ ServerSideEncryptionByDefault: {
137
+ SSEAlgorithm: 'AES256',
138
+ },
139
+ },
140
+ ],
141
+ },
142
+ PublicAccessBlockConfiguration: {
143
+ BlockPublicAcls: true,
144
+ BlockPublicPolicy: true,
145
+ IgnorePublicAcls: true,
146
+ RestrictPublicBuckets: true,
147
+ },
148
+ });
149
+ // Verify CloudFront distribution exists with security configuration
150
+ template.hasResourceProperties('AWS::CloudFront::Distribution', {
151
+ DistributionConfig: {
152
+ Aliases: ['app.example.com'],
153
+ DefaultRootObject: 'index.html',
154
+ DefaultCacheBehavior: {
155
+ ViewerProtocolPolicy: 'redirect-to-https',
156
+ },
157
+ CustomErrorResponses: [
158
+ {
159
+ ErrorCode: 403,
160
+ ResponseCode: 200,
161
+ ResponsePagePath: '/index.html',
162
+ },
163
+ {
164
+ ErrorCode: 404,
165
+ ResponseCode: 200,
166
+ ResponsePagePath: '/index.html',
167
+ },
168
+ ],
169
+ ViewerCertificate: {
170
+ AcmCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012',
171
+ SslSupportMethod: 'sni-only',
172
+ },
173
+ },
174
+ });
175
+ // Verify CloudFront security headers function exists
176
+ template.hasResourceProperties('AWS::CloudFront::Function', {
177
+ FunctionConfig: {
178
+ Runtime: 'cloudfront-js-1.0',
179
+ },
180
+ });
181
+ // Verify Route53 A record exists for custom domain
182
+ template.hasResourceProperties('AWS::Route53::RecordSet', {
183
+ Type: 'A',
184
+ Name: 'app.example.com.',
185
+ HostedZoneId: 'Z123456789',
186
+ });
187
+ // Verify bucket deployment exists
188
+ template.hasResource('Custom::CDKBucketDeployment', {});
189
+ // Verify auto delete objects custom resource exists
190
+ template.hasResource('Custom::S3AutoDeleteObjects', {});
191
+ });
192
+ // Test: Frontend construct enforces security best practices
193
+ test('Frontend construct enforces security best practices', () => {
194
+ const template = assertions_1.Template.fromStack(stack);
195
+ // Verify HTTPS redirect is enforced
196
+ template.hasResourceProperties('AWS::CloudFront::Distribution', {
197
+ DistributionConfig: {
198
+ DefaultCacheBehavior: {
199
+ ViewerProtocolPolicy: 'redirect-to-https',
200
+ },
201
+ },
202
+ });
203
+ // Verify S3 bucket blocks public access
204
+ template.hasResourceProperties('AWS::S3::Bucket', {
205
+ PublicAccessBlockConfiguration: {
206
+ BlockPublicAcls: true,
207
+ BlockPublicPolicy: true,
208
+ IgnorePublicAcls: true,
209
+ RestrictPublicBuckets: true,
210
+ },
211
+ });
212
+ // Verify S3 bucket has encryption
213
+ template.hasResourceProperties('AWS::S3::Bucket', {
214
+ BucketEncryption: {
215
+ ServerSideEncryptionConfiguration: [
216
+ {
217
+ ServerSideEncryptionByDefault: {
218
+ SSEAlgorithm: 'AES256',
219
+ },
220
+ },
221
+ ],
222
+ },
223
+ });
224
+ });
225
+ // Test: Frontend construct supports SPA applications
226
+ test('Frontend construct supports SPA applications', () => {
227
+ const template = assertions_1.Template.fromStack(stack);
228
+ // Verify SPA-friendly error responses
229
+ template.hasResourceProperties('AWS::CloudFront::Distribution', {
230
+ DistributionConfig: {
231
+ CustomErrorResponses: [
232
+ {
233
+ ErrorCode: 403,
234
+ ResponseCode: 200,
235
+ ResponsePagePath: '/index.html',
236
+ },
237
+ {
238
+ ErrorCode: 404,
239
+ ResponseCode: 200,
240
+ ResponsePagePath: '/index.html',
241
+ },
242
+ ],
243
+ },
244
+ });
245
+ // Verify default root object is set
246
+ template.hasResourceProperties('AWS::CloudFront::Distribution', {
247
+ DistributionConfig: {
248
+ DefaultRootObject: 'index.html',
249
+ },
250
+ });
251
+ });
252
+ // Test: No unsuppressed warnings
253
+ test('No unsuppressed warnings', () => {
254
+ if (warnings.length > 0) {
255
+ console.log('CDK Nag Warnings:', JSON.stringify(warnings, null, 2));
256
+ }
257
+ expect(warnings).toHaveLength(0);
258
+ });
259
+ // Test: No unsuppressed errors
260
+ test('No unsuppressed errors', () => {
261
+ if (errors.length > 0) {
262
+ console.log('CDK Nag Errors:', JSON.stringify(errors, null, 2));
263
+ }
264
+ expect(errors).toHaveLength(0);
265
+ });
266
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJvbnRlbmQtY29uc3RydWN0LW5hZy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdXNlLWNhc2VzL3dlYmFwcC90ZXN0cy9mcm9udGVuZC1jb25zdHJ1Y3QtbmFnLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7O0FBRXRDLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0IsNkNBQWtEO0FBQ2xELHVEQUFzRTtBQUN0RSwrRUFBaUU7QUFDakUseURBQXFEO0FBQ3JELHFDQUE4RDtBQUM5RCw4REFBaUQ7QUFFakQsNkNBQTZDO0FBQzdDLE1BQU0sWUFBWSxHQUFHLDhCQUE4QixDQUFDO0FBQ3BELElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7SUFDakMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBQ0QsRUFBRSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsRUFBRSw0RkFBNEYsQ0FBQyxDQUFDO0FBRXRKLHVCQUF1QjtBQUN2QixNQUFNLEdBQUcsR0FBRyxJQUFJLGlCQUFHLEVBQUUsQ0FBQztBQUN0QixNQUFNLEtBQUssR0FBRyxJQUFJLG1CQUFLLENBQUMsR0FBRyxFQUFFLFdBQVcsRUFBRTtJQUN4QyxHQUFHLEVBQUU7UUFDSCxPQUFPLEVBQUUsY0FBYztRQUN2QixNQUFNLEVBQUUsV0FBVztLQUNwQjtDQUNGLENBQUMsQ0FBQztBQUVILG1EQUFtRDtBQUNuRCxNQUFNLFdBQVcsR0FBRyxvQ0FBVyxDQUFDLGtCQUFrQixDQUNoRCxLQUFLLEVBQ0wsYUFBYSxFQUNiLHFGQUFxRixDQUN0RixDQUFDO0FBRUYscUNBQXFDO0FBQ3JDLE1BQU0sVUFBVSxHQUFHLHdCQUFVLENBQUMs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QUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBBcHAsIFN0YWNrLCBBc3BlY3RzIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgVGVtcGxhdGUsIEFubm90YXRpb25zLCBNYXRjaCB9IGZyb20gJ2F3cy1jZGstbGliL2Fzc2VydGlvbnMnO1xuaW1wb3J0IHsgQ2VydGlmaWNhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyJztcbmltcG9ydCB7IEhvc3RlZFpvbmUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1Myc7XG5pbXBvcnQgeyBBd3NTb2x1dGlvbnNDaGVja3MsIE5hZ1N1cHByZXNzaW9ucyB9IGZyb20gJ2Nkay1uYWcnO1xuaW1wb3J0IHsgRnJvbnRlbmQgfSBmcm9tICcuLi9mcm9udGVuZC1jb25zdHJ1Y3QnO1xuXG4vLyBDcmVhdGUgdGVtcG9yYXJ5IGJ1aWxkIGRpcmVjdG9yeSBmb3IgdGVzdHNcbmNvbnN0IHRlc3RCdWlsZERpciA9ICcvdG1wL3Rlc3QtZnJvbnRlbmQtYnVpbGQtbmFnJztcbmlmICghZnMuZXhpc3RzU3luYyh0ZXN0QnVpbGREaXIpKSB7XG4gIGZzLm1rZGlyU3luYyh0ZXN0QnVpbGREaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4odGVzdEJ1aWxkRGlyLCAnaW5kZXguaHRtbCcpLCAnPCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PHRpdGxlPlRlc3Q8L3RpdGxlPjwvaGVhZD48Ym9keT48aDE+VGVzdCBBcHA8L2gxPjwvYm9keT48L2h0bWw+Jyk7XG5cbi8vIENyZWF0ZSBhcHAgYW5kIHN0YWNrXG5jb25zdCBhcHAgPSBuZXcgQXBwKCk7XG5jb25zdCBzdGFjayA9IG5ldyBTdGFjayhhcHAsICdUZXN0U3RhY2snLCB7XG4gIGVudjoge1xuICAgIGFjY291bnQ6ICcxMjM0NTY3ODkwMTInLFxuICAgIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG4gIH0sXG59KTtcblxuLy8gQ3JlYXRlIFNTTCBjZXJ0aWZpY2F0ZSBmb3IgY3VzdG9tIGRvbWFpbiB0ZXN0aW5nXG5jb25zdCBjZXJ0aWZpY2F0ZSA9IENlcnRpZmljYXRlLmZyb21DZXJ0aWZpY2F0ZUFybihcbiAgc3RhY2ssXG4gICdDZXJ0aWZpY2F0ZScsXG4gICdhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMicsXG4pO1xuXG4vLyBDcmVhdGUgaG9zdGVkIHpvbmUgZm9yIEROUyB0ZXN0aW5nXG5jb25zdCBob3N0ZWRab25lID0gSG9zdGVkWm9uZS5mcm9tSG9zdGVkWm9uZUF0dHJpYnV0ZXMoc3RhY2ssICdIb3N0ZWRab25lJywge1xuICBob3N0ZWRab25lSWQ6ICdaMTIzNDU2Nzg5JyxcbiAgem9uZU5hbWU6ICdleGFtcGxlLmNvbScsXG59KTtcblxuLy8gQ3JlYXRlIHRoZSBtYWluIEZyb250ZW5kIGNvbnN0cnVjdFxuY29uc3QgZnJvbnRlbmQgPSBuZXcgRnJvbnRlbmQoc3RhY2ssICdUZXN0RnJvbnRlbmQnLCB7XG4gIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICBjdXN0b21Eb21haW46IHtcbiAgICBkb21haW5OYW1lOiAnYXBwLmV4YW1wbGUuY29tJyxcbiAgICBjZXJ0aWZpY2F0ZSxcbiAgICBob3N0ZWRab25lLFxuICB9LFxuICBza2lwQnVpbGQ6IHRydWUsIC8vIFNraXAgYnVpbGQgZm9yIHRlc3Rpbmdcbn0pO1xuXG4vLyBBZGQgQ0RLIE5hZyBzdXBwcmVzc2lvbnMgZm9yIGtub3duIGFjY2VwdGFibGUgdmlvbGF0aW9uc1xuTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKHN0YWNrLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1DRlIxJyxcbiAgICByZWFzb246ICdDbG91ZEZyb250IGdlbyByZXN0cmljdGlvbnMgYXJlIGNvbmZpZ3VyZWQgYmFzZWQgb24gYXBwbGljYXRpb24gcmVxdWlyZW1lbnRzJyxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUNGUjInLFxuICAgIHJlYXNvbjogJ0Nsb3VkRnJvbnQgV0FGIGludGVncmF0aW9uIGlzIGNvbmZpZ3VyZWQgYmFzZWQgb24gc2VjdXJpdHkgcmVxdWlyZW1lbnRzJyxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUNGUjMnLFxuICAgIHJlYXNvbjogJ0Nsb3VkRnJvbnQgYWNjZXNzIGxvZ2dpbmcgaXMgY29uZmlndXJlZCBiYXNlZCBvbiBjb21wbGlhbmNlIHJlcXVpcmVtZW50cycsXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1DRlI0JyxcbiAgICByZWFzb246ICdDbG91ZEZyb250IHZpZXdlciBwcm90b2NvbCBwb2xpY3kgaXMgc2V0IHRvIHJlZGlyZWN0LXRvLWh0dHBzIGZvciBzZWN1cml0eScsXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1TMScsXG4gICAgcmVhc29uOiAnUzMgYnVja2V0IGFjY2VzcyBsb2dnaW5nIGlzIGNvbmZpZ3VyZWQgYmFzZWQgb24gY29tcGxpYW5jZSByZXF1aXJlbWVudHMnLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUzInLFxuICAgIHJlYXNvbjogJ1MzIGJ1Y2tldCBwdWJsaWMgYWNjZXNzIGlzIGJsb2NrZWQgYW5kIGFjY2VzcyBpcyBjb250cm9sbGVkIHZpYSBDbG91ZEZyb250IE9BQycsXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1TMycsXG4gICAgcmVhc29uOiAnUzMgYnVja2V0IFNTTCByZXF1ZXN0cyBvbmx5IHBvbGljeSBpcyBlbmZvcmNlZCB2aWEgQ2xvdWRGcm9udCBIVFRQUyByZWRpcmVjdCcsXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1TMTAnLFxuICAgIHJlYXNvbjogJ1MzIGJ1Y2tldCBNRkEgZGVsZXRlIGlzIG1hbmFnZWQgdGhyb3VnaCBvcmdhbml6YXRpb25hbCBzZWN1cml0eSBwb2xpY2llcycsXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU00JyxcbiAgICByZWFzb246ICdBV1MgbWFuYWdlZCBwb2xpY2llcyBhcmUgYWNjZXB0YWJsZSBmb3Igc3RhbmRhcmQgTGFtYmRhIGV4ZWN1dGlvbiByb2xlcycsXG4gICAgYXBwbGllc1RvOiBbJ1BvbGljeTo6YXJuOjxBV1M6OlBhcnRpdGlvbj46aWFtOjphd3M6cG9saWN5L3NlcnZpY2Utcm9sZS9BV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUnXSxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUlBTTUnLFxuICAgIHJlYXNvbjogJ0J1Y2tldERlcGxveW1lbnQgcmVxdWlyZXMgYnJvYWQgUzMgcGVybWlzc2lvbnMgdG8gbWFuYWdlIGRlcGxveW1lbnQgYXNzZXRzJyxcbiAgICBhcHBsaWVzVG86IFtcbiAgICAgICdBY3Rpb246OnMzOkdldE9iamVjdConLFxuICAgICAgJ0FjdGlvbjo6czM6R2V0QnVja2V0KicsXG4gICAgICAnQWN0aW9uOjpzMzpMaXN0KicsXG4gICAgICAnQWN0aW9uOjpzMzpEZWxldGVPYmplY3QqJyxcbiAgICAgICdBY3Rpb246OnMzOkFib3J0KicsXG4gICAgICAnUmVzb3VyY2U6OmFybjo8QVdTOjpQYXJ0aXRpb24+OnMzOjo6Y2RrLWhuYjY1OWZkcy1hc3NldHMtPEFXUzo6QWNjb3VudElkPi08QVdTOjpSZWdpb24+LyonLFxuICAgICAgJ1Jlc291cmNlOjphcm46PEFXUzo6UGFydGl0aW9uPjpzMzo6OmNkay1obmI2NTlmZHMtYXNzZXRzLTEyMzQ1Njc4OTAxMi11cy1lYXN0LTEvKicsXG4gICAgICAnUmVzb3VyY2U6OjxUZXN0RnJvbnRlbmRGcm9udGVuZEJ1Y2tldEQzN0QyMkRFLkFybj4vKicsXG4gICAgICAnUmVzb3VyY2U6OionLFxuICAgIF0sXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1MMScsXG4gICAgcmVhc29uOiAnTGFtYmRhIHJ1bnRpbWUgdmVyc2lvbnMgYXJlIG1hbmFnZWQgYXQgdGhlIGFwcGxpY2F0aW9uIGRlcGxveW1lbnQgbGV2ZWwnLFxuICB9LFxuXSwgdHJ1ZSk7XG5cbi8vIEFwcGx5IENESyBOYWcgY2hlY2tzXG5Bc3BlY3RzLm9mKGFwcCkuYWRkKG5ldyBBd3NTb2x1dGlvbnNDaGVja3MoeyB2ZXJib3NlOiB0cnVlIH0pKTtcblxuLy8gU3ludGhlc2l6ZSB0aGUgc3RhY2tcblRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbi8vIENoZWNrIGZvciB1bnN1cHByZXNzZWQgd2FybmluZ3MgYW5kIGVycm9yc1xuY29uc3Qgd2FybmluZ3MgPSBBbm5vdGF0aW9ucy5mcm9tU3RhY2soc3RhY2spLmZpbmRXYXJuaW5nKCcqJywgTWF0Y2guc3RyaW5nTGlrZVJlZ2V4cCgnQXdzU29sdXRpb25zLS4qJykpO1xuY29uc3QgZXJyb3JzID0gQW5ub3RhdGlvbnMuZnJvbVN0YWNrKHN0YWNrKS5maW5kRXJyb3IoJyonLCBNYXRjaC5zdHJpbmdMaWtlUmVnZXhwKCdBd3NTb2x1dGlvbnMtLionKSk7XG5cbi8vIFRlc3Q6IEZyb250ZW5kIGNvbnN0cnVjdCBpcyBwcm9wZXJseSBjcmVhdGVkIGFuZCBhY2Nlc3NpYmxlXG50ZXN0KCdGcm9udGVuZCBjb25zdHJ1Y3QgaXMgY3JlYXRlZCBzdWNjZXNzZnVsbHknLCAoKSA9PiB7XG4gIGV4cGVjdChmcm9udGVuZCkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGZyb250ZW5kLm5vZGUuaWQpLnRvQmUoJ1Rlc3RGcm9udGVuZCcpO1xuICBleHBlY3QoZnJvbnRlbmQuYnVja2V0KS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoZnJvbnRlbmQuZGlzdHJpYnV0aW9uKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoZnJvbnRlbmQuYnVja2V0RGVwbG95bWVudCkudG9CZURlZmluZWQoKTtcbn0pO1xuXG4vLyBUZXN0OiBGcm9udGVuZCBjb25zdHJ1Y3QgaGFzIGV4cGVjdGVkIHByb3BlcnRpZXNcbnRlc3QoJ0Zyb250ZW5kIGNvbnN0cnVjdCBoYXMgZXhwZWN0ZWQgcHJvcGVydGllcycsICgpID0+IHtcbiAgZXhwZWN0KGZyb250ZW5kLmJ1Y2tldC5idWNrZXROYW1lKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoZnJvbnRlbmQuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbklkKS50b0JlRGVmaW5lZCgpO1xuICBleHBlY3QoZnJvbnRlbmQuZG9tYWluTmFtZSkudG9CZSgnYXBwLmV4YW1wbGUuY29tJyk7XG4gIGV4cGVjdChmcm9udGVuZC51cmwoKSkudG9CZSgnaHR0cHM6Ly9hcHAuZXhhbXBsZS5jb20nKTtcbiAgZXhwZWN0KHR5cGVvZiBmcm9udGVuZC5idWNrZXROYW1lKCkpLnRvQmUoJ3N0cmluZycpO1xuICBleHBlY3QodHlwZW9mIGZyb250ZW5kLmRpc3RyaWJ1dGlvbkRvbWFpbk5hbWUoKSkudG9CZSgnc3RyaW5nJyk7XG59KTtcblxuLy8gVGVzdDogVGVtcGxhdGUgY29udGFpbnMgZXhwZWN0ZWQgZnJvbnRlbmQgcmVzb3VyY2VzXG50ZXN0KCdUZW1wbGF0ZSBjb250YWlucyBleHBlY3RlZCBmcm9udGVuZCByZXNvdXJjZXMnLCAoKSA9PiB7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBWZXJpZnkgUzMgYnVja2V0IGV4aXN0cyB3aXRoIHNlY3VyaXR5IGNvbmZpZ3VyYXRpb25cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlMzOjpCdWNrZXQnLCB7XG4gICAgQnVja2V0RW5jcnlwdGlvbjoge1xuICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdDoge1xuICAgICAgICAgICAgU1NFQWxnb3JpdGhtOiAnQUVTMjU2JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9LFxuICAgIFB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbjoge1xuICAgICAgQmxvY2tQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgQmxvY2tQdWJsaWNQb2xpY3k6IHRydWUsXG4gICAgICBJZ25vcmVQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgUmVzdHJpY3RQdWJsaWNCdWNrZXRzOiB0cnVlLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFZlcmlmeSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbiBleGlzdHMgd2l0aCBzZWN1cml0eSBjb25maWd1cmF0aW9uXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb24nLCB7XG4gICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICBBbGlhc2VzOiBbJ2FwcC5leGFtcGxlLmNvbSddLFxuICAgICAgRGVmYXVsdFJvb3RPYmplY3Q6ICdpbmRleC5odG1sJyxcbiAgICAgIERlZmF1bHRDYWNoZUJlaGF2aW9yOiB7XG4gICAgICAgIFZpZXdlclByb3RvY29sUG9saWN5OiAncmVkaXJlY3QtdG8taHR0cHMnLFxuICAgICAgfSxcbiAgICAgIEN1c3RvbUVycm9yUmVzcG9uc2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBFcnJvckNvZGU6IDQwMyxcbiAgICAgICAgICBSZXNwb25zZUNvZGU6IDIwMCxcbiAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgRXJyb3JDb2RlOiA0MDQsXG4gICAgICAgICAgUmVzcG9uc2VDb2RlOiAyMDAsXG4gICAgICAgICAgUmVzcG9uc2VQYWdlUGF0aDogJy9pbmRleC5odG1sJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBWaWV3ZXJDZXJ0aWZpY2F0ZToge1xuICAgICAgICBBY21DZXJ0aWZpY2F0ZUFybjogJ2Fybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyJyxcbiAgICAgICAgU3NsU3VwcG9ydE1ldGhvZDogJ3NuaS1vbmx5JyxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gVmVyaWZ5IENsb3VkRnJvbnQgc2VjdXJpdHkgaGVhZGVycyBmdW5jdGlvbiBleGlzdHNcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkZ1bmN0aW9uJywge1xuICAgIEZ1bmN0aW9uQ29uZmlnOiB7XG4gICAgICBSdW50aW1lOiAnY2xvdWRmcm9udC1qcy0xLjAnLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFZlcmlmeSBSb3V0ZTUzIEEgcmVjb3JkIGV4aXN0cyBmb3IgY3VzdG9tIGRvbWFpblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6Um91dGU1Mzo6UmVjb3JkU2V0Jywge1xuICAgIFR5cGU6ICdBJyxcbiAgICBOYW1lOiAnYXBwLmV4YW1wbGUuY29tLicsXG4gICAgSG9zdGVkWm9uZUlkOiAnWjEyMzQ1Njc4OScsXG4gIH0pO1xuXG4gIC8vIFZlcmlmeSBidWNrZXQgZGVwbG95bWVudCBleGlzdHNcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2UoJ0N1c3RvbTo6Q0RLQnVja2V0RGVwbG95bWVudCcsIHt9KTtcblxuICAvLyBWZXJpZnkgYXV0byBkZWxldGUgb2JqZWN0cyBjdXN0b20gcmVzb3VyY2UgZXhpc3RzXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlKCdDdXN0b206OlMzQXV0b0RlbGV0ZU9iamVjdHMnLCB7fSk7XG59KTtcblxuLy8gVGVzdDogRnJvbnRlbmQgY29uc3RydWN0IGVuZm9yY2VzIHNlY3VyaXR5IGJlc3QgcHJhY3RpY2VzXG50ZXN0KCdGcm9udGVuZCBjb25zdHJ1Y3QgZW5mb3JjZXMgc2VjdXJpdHkgYmVzdCBwcmFjdGljZXMnLCAoKSA9PiB7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBWZXJpZnkgSFRUUFMgcmVkaXJlY3QgaXMgZW5mb3JjZWRcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIERlZmF1bHRDYWNoZUJlaGF2aW9yOiB7XG4gICAgICAgIFZpZXdlclByb3RvY29sUG9saWN5OiAncmVkaXJlY3QtdG8taHR0cHMnLFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcblxuICAvLyBWZXJpZnkgUzMgYnVja2V0IGJsb2NrcyBwdWJsaWMgYWNjZXNzXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTMzo6QnVja2V0Jywge1xuICAgIFB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvbjoge1xuICAgICAgQmxvY2tQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgQmxvY2tQdWJsaWNQb2xpY3k6IHRydWUsXG4gICAgICBJZ25vcmVQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgUmVzdHJpY3RQdWJsaWNCdWNrZXRzOiB0cnVlLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFZlcmlmeSBTMyBidWNrZXQgaGFzIGVuY3J5cHRpb25cbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlMzOjpCdWNrZXQnLCB7XG4gICAgQnVja2V0RW5jcnlwdGlvbjoge1xuICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdDoge1xuICAgICAgICAgICAgU1NFQWxnb3JpdGhtOiAnQUVTMjU2JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9LFxuICB9KTtcbn0pO1xuXG4vLyBUZXN0OiBGcm9udGVuZCBjb25zdHJ1Y3Qgc3VwcG9ydHMgU1BBIGFwcGxpY2F0aW9uc1xudGVzdCgnRnJvbnRlbmQgY29uc3RydWN0IHN1cHBvcnRzIFNQQSBhcHBsaWNhdGlvbnMnLCAoKSA9PiB7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBWZXJpZnkgU1BBLWZyaWVuZGx5IGVycm9yIHJlc3BvbnNlc1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uJywge1xuICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgQ3VzdG9tRXJyb3JSZXNwb25zZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIEVycm9yQ29kZTogNDAzLFxuICAgICAgICAgIFJlc3BvbnNlQ29kZTogMjAwLFxuICAgICAgICAgIFJlc3BvbnNlUGFnZVBhdGg6ICcvaW5kZXguaHRtbCcsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBFcnJvckNvZGU6IDQwNCxcbiAgICAgICAgICBSZXNwb25zZUNvZGU6IDIwMCxcbiAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9LFxuICB9KTtcblxuICAvLyBWZXJpZnkgZGVmYXVsdCByb290IG9iamVjdCBpcyBzZXRcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgIERlZmF1bHRSb290T2JqZWN0OiAnaW5kZXguaHRtbCcsXG4gICAgfSxcbiAgfSk7XG59KTtcblxuLy8gVGVzdDogTm8gdW5zdXBwcmVzc2VkIHdhcm5pbmdzXG50ZXN0KCdObyB1bnN1cHByZXNzZWQgd2FybmluZ3MnLCAoKSA9PiB7XG4gIGlmICh3YXJuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgY29uc29sZS5sb2coJ0NESyBOYWcgV2FybmluZ3M6JywgSlNPTi5zdHJpbmdpZnkod2FybmluZ3MsIG51bGwsIDIpKTtcbiAgfVxuICBleHBlY3Qod2FybmluZ3MpLnRvSGF2ZUxlbmd0aCgwKTtcbn0pO1xuXG4vLyBUZXN0OiBObyB1bnN1cHByZXNzZWQgZXJyb3JzXG50ZXN0KCdObyB1bnN1cHByZXNzZWQgZXJyb3JzJywgKCkgPT4ge1xuICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zb2xlLmxvZygnQ0RLIE5hZyBFcnJvcnM6JywgSlNPTi5zdHJpbmdpZnkoZXJyb3JzLCBudWxsLCAyKSk7XG4gIH1cbiAgZXhwZWN0KGVycm9ycykudG9IYXZlTGVuZ3RoKDApO1xufSk7XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};