@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.
- package/.jsii +8644 -0
- package/LICENSE +202 -0
- package/README.md +212 -0
- package/lib/document-processing/agentic-document-processing.d.ts +16 -0
- package/lib/document-processing/agentic-document-processing.js +90 -0
- package/lib/document-processing/base-document-processing.d.ts +189 -0
- package/lib/document-processing/base-document-processing.js +509 -0
- package/lib/document-processing/bedrock-document-processing.d.ts +167 -0
- package/lib/document-processing/bedrock-document-processing.js +297 -0
- package/lib/document-processing/index.d.ts +3 -0
- package/lib/document-processing/index.js +20 -0
- package/lib/document-processing/resources/default-bedrock-invoke/index.py +63 -0
- package/lib/document-processing/resources/default-bedrock-invoke/requirements.txt +4 -0
- package/lib/document-processing/resources/default-doc-retrieval-lambda/index.mjs +92 -0
- package/lib/document-processing/resources/default-doc-retrieval-lambda/package.json +10 -0
- package/lib/document-processing/resources/default-error-handler/index.js +46 -0
- package/lib/document-processing/resources/default-error-handler/package.json +4 -0
- package/lib/document-processing/resources/default-image-processor/classifier.mjs +665 -0
- package/lib/document-processing/resources/default-image-processor/extractors.mjs +465 -0
- package/lib/document-processing/resources/default-image-processor/index.mjs +143 -0
- package/lib/document-processing/resources/default-image-processor/package-lock.json +12 -0
- package/lib/document-processing/resources/default-image-processor/package.json +4 -0
- package/lib/document-processing/resources/default-image-validator/index.mjs +76 -0
- package/lib/document-processing/resources/default-image-validator/package-lock.json +154 -0
- package/lib/document-processing/resources/default-image-validator/package.json +7 -0
- package/lib/document-processing/resources/default-pdf-processor/index.js +46 -0
- package/lib/document-processing/resources/default-pdf-validator/index.js +36 -0
- package/lib/document-processing/resources/default-sqs-consumer/index.py +111 -0
- package/lib/document-processing/resources/default-sqs-consumer/requirements.txt +4 -0
- package/lib/document-processing/resources/default-sqs-consumer/sample_payload.json +20 -0
- package/lib/document-processing/resources/default-sqs-consumer/sample_payload_multi.json +24 -0
- package/lib/document-processing/resources/default-strands-agent/index.py +111 -0
- package/lib/document-processing/resources/default-strands-agent/requirements.txt +6 -0
- package/lib/document-processing/tests/agentic-document-processing-nag.test.d.ts +1 -0
- package/lib/document-processing/tests/agentic-document-processing-nag.test.js +107 -0
- package/lib/document-processing/tests/agentic-document-processing.test.d.ts +1 -0
- package/lib/document-processing/tests/agentic-document-processing.test.js +125 -0
- package/lib/document-processing/tests/bedrock-document-processing-nag.test.d.ts +1 -0
- package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +101 -0
- package/lib/document-processing/tests/bedrock-document-processing.test.d.ts +1 -0
- package/lib/document-processing/tests/bedrock-document-processing.test.js +79 -0
- package/lib/framework/custom-resource/default-runtimes.d.ts +21 -0
- package/lib/framework/custom-resource/default-runtimes.js +34 -0
- package/lib/framework/custom-resource/index.d.ts +1 -0
- package/lib/framework/custom-resource/index.js +18 -0
- package/lib/framework/foundation/access-log.d.ts +69 -0
- package/lib/framework/foundation/access-log.js +121 -0
- package/lib/framework/foundation/eventbridge-broker.d.ts +18 -0
- package/lib/framework/foundation/eventbridge-broker.js +42 -0
- package/lib/framework/foundation/index.d.ts +3 -0
- package/lib/framework/foundation/index.js +20 -0
- package/lib/framework/foundation/network.d.ts +19 -0
- package/lib/framework/foundation/network.js +83 -0
- package/lib/framework/index.d.ts +2 -0
- package/lib/framework/index.js +19 -0
- package/lib/framework/quickstart/base-quickstart.d.ts +30 -0
- package/lib/framework/quickstart/base-quickstart.js +30 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +21 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/utilities/cdk-nag-config.d.ts +42 -0
- package/lib/utilities/cdk-nag-config.js +194 -0
- package/lib/utilities/data-loader-lambda/index.py +282 -0
- package/lib/utilities/data-loader-lambda/requirements.txt +3 -0
- package/lib/utilities/data-loader.d.ts +173 -0
- package/lib/utilities/data-loader.js +447 -0
- package/lib/utilities/index.d.ts +3 -0
- package/lib/utilities/index.js +20 -0
- package/lib/utilities/lambda-iam-utils.d.ts +145 -0
- package/lib/utilities/lambda-iam-utils.js +235 -0
- package/lib/utilities/lambda_layers/data-masking/layer-construct.d.ts +42 -0
- package/lib/utilities/lambda_layers/data-masking/layer-construct.js +53 -0
- package/lib/utilities/lambda_layers/data-masking/layer-construct.ts +88 -0
- package/lib/utilities/observability/bedrock-observability.d.ts +18 -0
- package/lib/utilities/observability/bedrock-observability.js +131 -0
- package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.d.ts +6 -0
- package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +22 -0
- package/lib/utilities/observability/index.d.ts +6 -0
- package/lib/utilities/observability/index.js +25 -0
- package/lib/utilities/observability/lambda-observability-property-injector.d.ts +8 -0
- package/lib/utilities/observability/lambda-observability-property-injector.js +43 -0
- package/lib/utilities/observability/log-group-data-protection-props.d.ts +19 -0
- package/lib/utilities/observability/log-group-data-protection-props.js +5 -0
- package/lib/utilities/observability/observability.d.ts +83 -0
- package/lib/utilities/observability/observability.js +278 -0
- package/lib/utilities/observability/observable.d.ts +32 -0
- package/lib/utilities/observability/observable.js +3 -0
- package/lib/utilities/observability/powertools-config.d.ts +3 -0
- package/lib/utilities/observability/powertools-config.js +25 -0
- package/lib/utilities/observability/resources/bedrock-manage-logging-configuration/index.py +27 -0
- package/lib/utilities/observability/state-machine-observability-property-injector.d.ts +8 -0
- package/lib/utilities/observability/state-machine-observability-property-injector.js +49 -0
- package/lib/utilities/tests/data-loader-nag.test.d.ts +1 -0
- package/lib/utilities/tests/data-loader-nag.test.js +432 -0
- package/lib/utilities/tests/data-loader.test.d.ts +1 -0
- package/lib/utilities/tests/data-loader.test.js +284 -0
- package/lib/webapp/frontend-construct.d.ts +136 -0
- package/lib/webapp/frontend-construct.js +253 -0
- package/lib/webapp/index.d.ts +1 -0
- package/lib/webapp/index.js +18 -0
- package/lib/webapp/tests/frontend-construct-nag.test.d.ts +1 -0
- package/lib/webapp/tests/frontend-construct-nag.test.js +266 -0
- package/lib/webapp/tests/frontend-construct.test.d.ts +1 -0
- package/lib/webapp/tests/frontend-construct.test.js +385 -0
- package/package.json +183 -0
|
@@ -0,0 +1,385 @@
|
|
|
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_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
|
|
11
|
+
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
|
|
12
|
+
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
|
|
13
|
+
const aws_s3_deployment_1 = require("aws-cdk-lib/aws-s3-deployment");
|
|
14
|
+
const frontend_construct_1 = require("../frontend-construct");
|
|
15
|
+
// Mock execSync to avoid actual build execution during tests
|
|
16
|
+
jest.mock('child_process', () => ({
|
|
17
|
+
execSync: jest.fn(),
|
|
18
|
+
}));
|
|
19
|
+
describe('@webapp Frontend', () => {
|
|
20
|
+
let app;
|
|
21
|
+
let stack;
|
|
22
|
+
let template;
|
|
23
|
+
let testBuildDir;
|
|
24
|
+
let testSrcDir;
|
|
25
|
+
beforeAll(() => {
|
|
26
|
+
// Create a temporary build directory for tests
|
|
27
|
+
testBuildDir = '/tmp/test-frontend-build';
|
|
28
|
+
if (!fs.existsSync(testBuildDir)) {
|
|
29
|
+
fs.mkdirSync(testBuildDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
fs.writeFileSync(path.join(testBuildDir, 'index.html'), '<!DOCTYPE html><html><head><title>Test</title></head><body><h1>Test App</h1></body></html>');
|
|
32
|
+
// Create a temporary source directory for tests
|
|
33
|
+
testSrcDir = '/tmp/test-frontend-src';
|
|
34
|
+
if (!fs.existsSync(testSrcDir)) {
|
|
35
|
+
fs.mkdirSync(testSrcDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
// Create default build directory inside source directory
|
|
38
|
+
const defaultBuildDir = path.join(testSrcDir, 'build');
|
|
39
|
+
if (!fs.existsSync(defaultBuildDir)) {
|
|
40
|
+
fs.mkdirSync(defaultBuildDir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
fs.writeFileSync(path.join(defaultBuildDir, 'index.html'), '<!DOCTYPE html><html><head><title>Default Test</title></head><body><h1>Default Test App</h1></body></html>');
|
|
43
|
+
});
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
app = new aws_cdk_lib_1.App();
|
|
46
|
+
stack = new aws_cdk_lib_1.Stack(app, 'TestStack');
|
|
47
|
+
});
|
|
48
|
+
describe('@webapp Basic functionality', () => {
|
|
49
|
+
test('@webapp creates frontend construct with minimal configuration', () => {
|
|
50
|
+
const frontend = new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
51
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
52
|
+
buildOutputDirectory: testBuildDir,
|
|
53
|
+
skipBuild: true, // Skip build for testing
|
|
54
|
+
});
|
|
55
|
+
template = assertions_1.Template.fromStack(stack);
|
|
56
|
+
// Verify S3 bucket is created
|
|
57
|
+
template.hasResourceProperties('AWS::S3::Bucket', {
|
|
58
|
+
BucketEncryption: {
|
|
59
|
+
ServerSideEncryptionConfiguration: [
|
|
60
|
+
{
|
|
61
|
+
ServerSideEncryptionByDefault: {
|
|
62
|
+
SSEAlgorithm: 'AES256',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
PublicAccessBlockConfiguration: {
|
|
68
|
+
BlockPublicAcls: true,
|
|
69
|
+
BlockPublicPolicy: true,
|
|
70
|
+
IgnorePublicAcls: true,
|
|
71
|
+
RestrictPublicBuckets: true,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
// Verify CloudFront distribution is created
|
|
75
|
+
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
76
|
+
DistributionConfig: {
|
|
77
|
+
DefaultRootObject: 'index.html',
|
|
78
|
+
CustomErrorResponses: [
|
|
79
|
+
{
|
|
80
|
+
ErrorCode: 403,
|
|
81
|
+
ResponseCode: 200,
|
|
82
|
+
ResponsePagePath: '/index.html',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
ErrorCode: 404,
|
|
86
|
+
ResponseCode: 200,
|
|
87
|
+
ResponsePagePath: '/index.html',
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
// Verify security headers function is created
|
|
93
|
+
template.hasResourceProperties('AWS::CloudFront::Function', {
|
|
94
|
+
FunctionConfig: {
|
|
95
|
+
Runtime: 'cloudfront-js-1.0',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
// Verify bucket deployment is created
|
|
99
|
+
template.hasResource('Custom::CDKBucketDeployment', {});
|
|
100
|
+
// Test public methods
|
|
101
|
+
expect(frontend.bucket).toBeInstanceOf(aws_s3_1.Bucket);
|
|
102
|
+
expect(frontend.distribution).toBeInstanceOf(aws_cloudfront_1.Distribution);
|
|
103
|
+
expect(frontend.bucketDeployment).toBeInstanceOf(aws_s3_deployment_1.BucketDeployment);
|
|
104
|
+
expect(typeof frontend.distributionDomainName()).toBe('string');
|
|
105
|
+
expect(typeof frontend.bucketName()).toBe('string');
|
|
106
|
+
expect(frontend.url()).toContain('https://');
|
|
107
|
+
});
|
|
108
|
+
test('@webapp creates frontend construct with custom build command', () => {
|
|
109
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
110
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
111
|
+
buildOutputDirectory: testBuildDir,
|
|
112
|
+
buildCommand: 'yarn build',
|
|
113
|
+
skipBuild: true,
|
|
114
|
+
});
|
|
115
|
+
template = assertions_1.Template.fromStack(stack);
|
|
116
|
+
// Should still create the same resources
|
|
117
|
+
template.resourceCountIs('AWS::S3::Bucket', 1);
|
|
118
|
+
template.resourceCountIs('AWS::CloudFront::Distribution', 1);
|
|
119
|
+
});
|
|
120
|
+
test('@webapp creates frontend construct with custom error responses', () => {
|
|
121
|
+
const customErrorResponses = [
|
|
122
|
+
{
|
|
123
|
+
httpStatus: 500,
|
|
124
|
+
responseHttpStatus: 200,
|
|
125
|
+
responsePagePath: '/error.html',
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
129
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
130
|
+
buildOutputDirectory: testBuildDir,
|
|
131
|
+
errorResponses: customErrorResponses,
|
|
132
|
+
skipBuild: true,
|
|
133
|
+
});
|
|
134
|
+
template = assertions_1.Template.fromStack(stack);
|
|
135
|
+
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
136
|
+
DistributionConfig: {
|
|
137
|
+
CustomErrorResponses: [
|
|
138
|
+
{
|
|
139
|
+
ErrorCode: 500,
|
|
140
|
+
ResponseCode: 200,
|
|
141
|
+
ResponsePagePath: '/error.html',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('@webapp Custom domain functionality', () => {
|
|
149
|
+
test('@webapp creates frontend construct with custom domain', () => {
|
|
150
|
+
const certificate = aws_certificatemanager_1.Certificate.fromCertificateArn(stack, 'Certificate', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012');
|
|
151
|
+
const frontend = new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
152
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
153
|
+
buildOutputDirectory: testBuildDir,
|
|
154
|
+
customDomain: {
|
|
155
|
+
domainName: 'app.example.com',
|
|
156
|
+
certificate,
|
|
157
|
+
},
|
|
158
|
+
skipBuild: true,
|
|
159
|
+
});
|
|
160
|
+
template = assertions_1.Template.fromStack(stack);
|
|
161
|
+
// Verify CloudFront distribution has custom domain
|
|
162
|
+
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
163
|
+
DistributionConfig: {
|
|
164
|
+
Aliases: ['app.example.com'],
|
|
165
|
+
ViewerCertificate: {
|
|
166
|
+
AcmCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012',
|
|
167
|
+
SslSupportMethod: 'sni-only',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
expect(frontend.domainName).toBe('app.example.com');
|
|
172
|
+
expect(frontend.url()).toBe('https://app.example.com');
|
|
173
|
+
});
|
|
174
|
+
test('@webapp creates frontend construct with custom domain and hosted zone', () => {
|
|
175
|
+
const certificate = aws_certificatemanager_1.Certificate.fromCertificateArn(stack, 'Certificate', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012');
|
|
176
|
+
const hostedZone = aws_route53_1.HostedZone.fromHostedZoneAttributes(stack, 'HostedZone', {
|
|
177
|
+
hostedZoneId: 'Z123456789',
|
|
178
|
+
zoneName: 'example.com',
|
|
179
|
+
});
|
|
180
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
181
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
182
|
+
buildOutputDirectory: testBuildDir,
|
|
183
|
+
customDomain: {
|
|
184
|
+
domainName: 'app.example.com',
|
|
185
|
+
certificate,
|
|
186
|
+
hostedZone,
|
|
187
|
+
},
|
|
188
|
+
skipBuild: true,
|
|
189
|
+
});
|
|
190
|
+
template = assertions_1.Template.fromStack(stack);
|
|
191
|
+
// Verify Route53 A record is created
|
|
192
|
+
template.hasResourceProperties('AWS::Route53::RecordSet', {
|
|
193
|
+
Type: 'A',
|
|
194
|
+
Name: 'app.example.com.',
|
|
195
|
+
HostedZoneId: 'Z123456789',
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
describe('@webapp Validation', () => {
|
|
200
|
+
test('@webapp throws error when sourceDirectory is missing', () => {
|
|
201
|
+
expect(() => {
|
|
202
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
203
|
+
sourceDirectory: '',
|
|
204
|
+
buildOutputDirectory: testBuildDir,
|
|
205
|
+
skipBuild: true,
|
|
206
|
+
});
|
|
207
|
+
}).toThrow('sourceDirectory is required');
|
|
208
|
+
});
|
|
209
|
+
test('@webapp uses default buildOutputDirectory when not provided', () => {
|
|
210
|
+
// Use the existing test build directory
|
|
211
|
+
const frontend = new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
212
|
+
sourceDirectory: testSrcDir,
|
|
213
|
+
// buildOutputDirectory not provided - should use default './build/'
|
|
214
|
+
skipBuild: true,
|
|
215
|
+
});
|
|
216
|
+
expect(frontend).toBeDefined();
|
|
217
|
+
// The construct should be created successfully with default buildOutputDirectory
|
|
218
|
+
});
|
|
219
|
+
test('@webapp applies custom removal policy to resources', () => {
|
|
220
|
+
const retainStack = new aws_cdk_lib_1.Stack(app, 'RetainTestStack');
|
|
221
|
+
const frontend = new frontend_construct_1.Frontend(retainStack, 'Frontend', {
|
|
222
|
+
sourceDirectory: testSrcDir,
|
|
223
|
+
buildOutputDirectory: testBuildDir,
|
|
224
|
+
skipBuild: true,
|
|
225
|
+
removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN,
|
|
226
|
+
});
|
|
227
|
+
expect(frontend).toBeDefined();
|
|
228
|
+
// Check that the bucket has the correct removal policy
|
|
229
|
+
const retainTemplate = assertions_1.Template.fromStack(retainStack);
|
|
230
|
+
retainTemplate.hasResource('AWS::S3::Bucket', {
|
|
231
|
+
DeletionPolicy: 'Retain',
|
|
232
|
+
UpdateReplacePolicy: 'Retain',
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
test('@webapp uses default DESTROY removal policy when not specified', () => {
|
|
236
|
+
const destroyStack = new aws_cdk_lib_1.Stack(app, 'DestroyTestStack');
|
|
237
|
+
const frontend = new frontend_construct_1.Frontend(destroyStack, 'Frontend', {
|
|
238
|
+
sourceDirectory: testSrcDir,
|
|
239
|
+
buildOutputDirectory: testBuildDir,
|
|
240
|
+
skipBuild: true,
|
|
241
|
+
// removalPolicy not specified - should default to DESTROY
|
|
242
|
+
});
|
|
243
|
+
expect(frontend).toBeDefined();
|
|
244
|
+
// Check that the bucket has the default DESTROY removal policy
|
|
245
|
+
const destroyTemplate = assertions_1.Template.fromStack(destroyStack);
|
|
246
|
+
destroyTemplate.hasResource('AWS::S3::Bucket', {
|
|
247
|
+
DeletionPolicy: 'Delete',
|
|
248
|
+
UpdateReplacePolicy: 'Delete',
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
test('@webapp throws error when domainName is provided without certificate', () => {
|
|
252
|
+
expect(() => {
|
|
253
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
254
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
255
|
+
buildOutputDirectory: testBuildDir,
|
|
256
|
+
customDomain: {
|
|
257
|
+
domainName: 'app.example.com',
|
|
258
|
+
}, // Type assertion to bypass TypeScript validation for testing
|
|
259
|
+
skipBuild: true,
|
|
260
|
+
});
|
|
261
|
+
}).toThrow('certificate is required when domainName is provided');
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
describe('@webapp Security features', () => {
|
|
265
|
+
test('@webapp creates S3 bucket with security best practices', () => {
|
|
266
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
267
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
268
|
+
buildOutputDirectory: testBuildDir,
|
|
269
|
+
skipBuild: true,
|
|
270
|
+
});
|
|
271
|
+
template = assertions_1.Template.fromStack(stack);
|
|
272
|
+
// Verify S3 bucket security settings
|
|
273
|
+
template.hasResourceProperties('AWS::S3::Bucket', {
|
|
274
|
+
BucketEncryption: {
|
|
275
|
+
ServerSideEncryptionConfiguration: [
|
|
276
|
+
{
|
|
277
|
+
ServerSideEncryptionByDefault: {
|
|
278
|
+
SSEAlgorithm: 'AES256',
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
},
|
|
283
|
+
PublicAccessBlockConfiguration: {
|
|
284
|
+
BlockPublicAcls: true,
|
|
285
|
+
BlockPublicPolicy: true,
|
|
286
|
+
IgnorePublicAcls: true,
|
|
287
|
+
RestrictPublicBuckets: true,
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
test('@webapp creates CloudFront distribution with security headers', () => {
|
|
292
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
293
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
294
|
+
buildOutputDirectory: testBuildDir,
|
|
295
|
+
skipBuild: true,
|
|
296
|
+
});
|
|
297
|
+
template = assertions_1.Template.fromStack(stack);
|
|
298
|
+
// Verify security headers function exists
|
|
299
|
+
template.hasResourceProperties('AWS::CloudFront::Function', {
|
|
300
|
+
FunctionConfig: {
|
|
301
|
+
Runtime: 'cloudfront-js-1.0',
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
// Verify HTTPS redirect is enabled
|
|
305
|
+
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
306
|
+
DistributionConfig: {
|
|
307
|
+
DefaultCacheBehavior: {
|
|
308
|
+
ViewerProtocolPolicy: 'redirect-to-https',
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
test('@webapp enables auto delete objects on S3 bucket', () => {
|
|
314
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
315
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
316
|
+
buildOutputDirectory: testBuildDir,
|
|
317
|
+
skipBuild: true,
|
|
318
|
+
});
|
|
319
|
+
template = assertions_1.Template.fromStack(stack);
|
|
320
|
+
// Verify auto delete objects custom resource is created
|
|
321
|
+
template.hasResource('Custom::S3AutoDeleteObjects', {});
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
describe('@webapp Default values', () => {
|
|
325
|
+
test('@webapp uses default SPA error responses', () => {
|
|
326
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
327
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
328
|
+
buildOutputDirectory: testBuildDir,
|
|
329
|
+
skipBuild: true,
|
|
330
|
+
});
|
|
331
|
+
template = assertions_1.Template.fromStack(stack);
|
|
332
|
+
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
333
|
+
DistributionConfig: {
|
|
334
|
+
CustomErrorResponses: [
|
|
335
|
+
{
|
|
336
|
+
ErrorCode: 403,
|
|
337
|
+
ResponseCode: 200,
|
|
338
|
+
ResponsePagePath: '/index.html',
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
ErrorCode: 404,
|
|
342
|
+
ResponseCode: 200,
|
|
343
|
+
ResponsePagePath: '/index.html',
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
test('@webapp exports default SPA error responses', () => {
|
|
350
|
+
expect(frontend_construct_1.DEFAULT_SPA_ERROR_RESPONSES).toEqual([
|
|
351
|
+
{
|
|
352
|
+
httpStatus: 403,
|
|
353
|
+
responseHttpStatus: 200,
|
|
354
|
+
responsePagePath: '/index.html',
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
httpStatus: 404,
|
|
358
|
+
responseHttpStatus: 200,
|
|
359
|
+
responsePagePath: '/index.html',
|
|
360
|
+
},
|
|
361
|
+
]);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
describe('@webapp Additional distribution properties', () => {
|
|
365
|
+
test('@webapp accepts additional CloudFront distribution properties', () => {
|
|
366
|
+
new frontend_construct_1.Frontend(stack, 'Frontend', {
|
|
367
|
+
sourceDirectory: '/tmp/test-frontend-src',
|
|
368
|
+
buildOutputDirectory: testBuildDir,
|
|
369
|
+
distributionProps: {
|
|
370
|
+
comment: 'Custom frontend distribution',
|
|
371
|
+
enabled: true,
|
|
372
|
+
},
|
|
373
|
+
skipBuild: true,
|
|
374
|
+
});
|
|
375
|
+
template = assertions_1.Template.fromStack(stack);
|
|
376
|
+
template.hasResourceProperties('AWS::CloudFront::Distribution', {
|
|
377
|
+
DistributionConfig: {
|
|
378
|
+
Comment: 'Custom frontend distribution',
|
|
379
|
+
Enabled: true,
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJvbnRlbmQtY29uc3RydWN0LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi91c2UtY2FzZXMvd2ViYXBwL3Rlc3RzL2Zyb250ZW5kLWNvbnN0cnVjdC50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxxRUFBcUU7QUFDckUsc0NBQXNDOztBQUV0Qyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLDZDQUF3RDtBQUN4RCx1REFBa0Q7QUFDbEQsK0VBQWlFO0FBQ2pFLCtEQUEwRDtBQUMxRCx5REFBcUQ7QUFDckQsK0NBQTRDO0FBQzVDLHFFQUFpRTtBQUNqRSw4REFBOEU7QUFFOUUsNkRBQTZEO0FBQzdELElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDaEMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7Q0FDcEIsQ0FBQyxDQUFDLENBQUM7QUFFSixRQUFRLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO0lBQ2hDLElBQUksR0FBUSxDQUFDO0lBQ2IsSUFBSSxLQUFZLENBQUM7SUFDakIsSUFBSSxRQUFrQixDQUFDO0lBQ3ZCLElBQUksWUFBb0IsQ0FBQztJQUN6QixJQUFJLFVBQWtCLENBQUM7SUFFdkIsU0FBUyxDQUFDLEdBQUcsRUFBRTtRQUNiLCtDQUErQztRQUMvQyxZQUFZLEdBQUcsMEJBQTBCLENBQUM7UUFDMUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUNqQyxFQUFFLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2xELENBQUM7UUFDRCxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxFQUFFLDRGQUE0RixDQUFDLENBQUM7UUFFdEosZ0RBQWdEO1FBQ2hELFVB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Q0FBQywrQkFBK0IsRUFBRTtnQkFDOUQsa0JBQWtCLEVBQUU7b0JBQ2xCLE9BQU8sRUFBRSw4QkFBOEI7b0JBQ3ZDLE9BQU8sRUFBRSxJQUFJO2lCQUNkO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQXBwLCBSZW1vdmFsUG9saWN5LCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IFRlbXBsYXRlIH0gZnJvbSAnYXdzLWNkay1saWIvYXNzZXJ0aW9ucyc7XG5pbXBvcnQgeyBDZXJ0aWZpY2F0ZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jZXJ0aWZpY2F0ZW1hbmFnZXInO1xuaW1wb3J0IHsgRGlzdHJpYnV0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnQnO1xuaW1wb3J0IHsgSG9zdGVkWm9uZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1yb3V0ZTUzJztcbmltcG9ydCB7IEJ1Y2tldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgeyBCdWNrZXREZXBsb3ltZW50IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLWRlcGxveW1lbnQnO1xuaW1wb3J0IHsgRnJvbnRlbmQsIERFRkFVTFRfU1BBX0VSUk9SX1JFU1BPTlNFUyB9IGZyb20gJy4uL2Zyb250ZW5kLWNvbnN0cnVjdCc7XG5cbi8vIE1vY2sgZXhlY1N5bmMgdG8gYXZvaWQgYWN0dWFsIGJ1aWxkIGV4ZWN1dGlvbiBkdXJpbmcgdGVzdHNcbmplc3QubW9jaygnY2hpbGRfcHJvY2VzcycsICgpID0+ICh7XG4gIGV4ZWNTeW5jOiBqZXN0LmZuKCksXG59KSk7XG5cbmRlc2NyaWJlKCdAd2ViYXBwIEZyb250ZW5kJywgKCkgPT4ge1xuICBsZXQgYXBwOiBBcHA7XG4gIGxldCBzdGFjazogU3RhY2s7XG4gIGxldCB0ZW1wbGF0ZTogVGVtcGxhdGU7XG4gIGxldCB0ZXN0QnVpbGREaXI6IHN0cmluZztcbiAgbGV0IHRlc3RTcmNEaXI6IHN0cmluZztcblxuICBiZWZvcmVBbGwoKCkgPT4ge1xuICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBidWlsZCBkaXJlY3RvcnkgZm9yIHRlc3RzXG4gICAgdGVzdEJ1aWxkRGlyID0gJy90bXAvdGVzdC1mcm9udGVuZC1idWlsZCc7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKHRlc3RCdWlsZERpcikpIHtcbiAgICAgIGZzLm1rZGlyU3luYyh0ZXN0QnVpbGREaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH1cbiAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbih0ZXN0QnVpbGREaXIsICdpbmRleC5odG1sJyksICc8IURPQ1RZUEUgaHRtbD48aHRtbD48aGVhZD48dGl0bGU+VGVzdDwvdGl0bGU+PC9oZWFkPjxib2R5PjxoMT5UZXN0IEFwcDwvaDE+PC9ib2R5PjwvaHRtbD4nKTtcblxuICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBzb3VyY2UgZGlyZWN0b3J5IGZvciB0ZXN0c1xuICAgIHRlc3RTcmNEaXIgPSAnL3RtcC90ZXN0LWZyb250ZW5kLXNyYyc7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKHRlc3RTcmNEaXIpKSB7XG4gICAgICBmcy5ta2RpclN5bmModGVzdFNyY0RpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIGRlZmF1bHQgYnVpbGQgZGlyZWN0b3J5IGluc2lkZSBzb3VyY2UgZGlyZWN0b3J5XG4gICAgY29uc3QgZGVmYXVsdEJ1aWxkRGlyID0gcGF0aC5qb2luKHRlc3RTcmNEaXIsICdidWlsZCcpO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhkZWZhdWx0QnVpbGREaXIpKSB7XG4gICAgICBmcy5ta2RpclN5bmMoZGVmYXVsdEJ1aWxkRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4oZGVmYXVsdEJ1aWxkRGlyLCAnaW5kZXguaHRtbCcpLCAnPCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PHRpdGxlPkRlZmF1bHQgVGVzdDwvdGl0bGU+PC9oZWFkPjxib2R5PjxoMT5EZWZhdWx0IFRlc3QgQXBwPC9oMT48L2JvZHk+PC9odG1sPicpO1xuICB9KTtcblxuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICBhcHAgPSBuZXcgQXBwKCk7XG4gICAgc3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnVGVzdFN0YWNrJyk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdAd2ViYXBwIEJhc2ljIGZ1bmN0aW9uYWxpdHknLCAoKSA9PiB7XG4gICAgdGVzdCgnQHdlYmFwcCBjcmVhdGVzIGZyb250ZW5kIGNvbnN0cnVjdCB3aXRoIG1pbmltYWwgY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICAgIGNvbnN0IGZyb250ZW5kID0gbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBza2lwQnVpbGQ6IHRydWUsIC8vIFNraXAgYnVpbGQgZm9yIHRlc3RpbmdcbiAgICAgIH0pO1xuXG4gICAgICB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIC8vIFZlcmlmeSBTMyBidWNrZXQgaXMgY3JlYXRlZFxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlMzOjpCdWNrZXQnLCB7XG4gICAgICAgIEJ1Y2tldEVuY3J5cHRpb246IHtcbiAgICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb246IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQ6IHtcbiAgICAgICAgICAgICAgICBTU0VBbGdvcml0aG06ICdBRVMyNTYnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBQdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgICBCbG9ja1B1YmxpY0FjbHM6IHRydWUsXG4gICAgICAgICAgQmxvY2tQdWJsaWNQb2xpY3k6IHRydWUsXG4gICAgICAgICAgSWdub3JlUHVibGljQWNsczogdHJ1ZSxcbiAgICAgICAgICBSZXN0cmljdFB1YmxpY0J1Y2tldHM6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgLy8gVmVyaWZ5IENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIGlzIGNyZWF0ZWRcbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb24nLCB7XG4gICAgICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgICAgIERlZmF1bHRSb290T2JqZWN0OiAnaW5kZXguaHRtbCcsXG4gICAgICAgICAgQ3VzdG9tRXJyb3JSZXNwb25zZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRXJyb3JDb2RlOiA0MDMsXG4gICAgICAgICAgICAgIFJlc3BvbnNlQ29kZTogMjAwLFxuICAgICAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRXJyb3JDb2RlOiA0MDQsXG4gICAgICAgICAgICAgIFJlc3BvbnNlQ29kZTogMjAwLFxuICAgICAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBzZWN1cml0eSBoZWFkZXJzIGZ1bmN0aW9uIGlzIGNyZWF0ZWRcbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpDbG91ZEZyb250OjpGdW5jdGlvbicsIHtcbiAgICAgICAgRnVuY3Rpb25Db25maWc6IHtcbiAgICAgICAgICBSdW50aW1lOiAnY2xvdWRmcm9udC1qcy0xLjAnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBidWNrZXQgZGVwbG95bWVudCBpcyBjcmVhdGVkXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZSgnQ3VzdG9tOjpDREtCdWNrZXREZXBsb3ltZW50Jywge30pO1xuXG4gICAgICAvLyBUZXN0IHB1YmxpYyBtZXRob2RzXG4gICAgICBleHBlY3QoZnJvbnRlbmQuYnVja2V0KS50b0JlSW5zdGFuY2VPZihCdWNrZXQpO1xuICAgICAgZXhwZWN0KGZyb250ZW5kLmRpc3RyaWJ1dGlvbikudG9CZUluc3RhbmNlT2YoRGlzdHJpYnV0aW9uKTtcbiAgICAgIGV4cGVjdChmcm9udGVuZC5idWNrZXREZXBsb3ltZW50KS50b0JlSW5zdGFuY2VPZihCdWNrZXREZXBsb3ltZW50KTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgZnJvbnRlbmQuZGlzdHJpYnV0aW9uRG9tYWluTmFtZSgpKS50b0JlKCdzdHJpbmcnKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgZnJvbnRlbmQuYnVja2V0TmFtZSgpKS50b0JlKCdzdHJpbmcnKTtcbiAgICAgIGV4cGVjdChmcm9udGVuZC51cmwoKSkudG9Db250YWluKCdodHRwczovLycpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnQHdlYmFwcCBjcmVhdGVzIGZyb250ZW5kIGNvbnN0cnVjdCB3aXRoIGN1c3RvbSBidWlsZCBjb21tYW5kJywgKCkgPT4ge1xuICAgICAgbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBidWlsZENvbW1hbmQ6ICd5YXJuIGJ1aWxkJyxcbiAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgLy8gU2hvdWxkIHN0aWxsIGNyZWF0ZSB0aGUgc2FtZSByZXNvdXJjZXNcbiAgICAgIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpTMzo6QnVja2V0JywgMSk7XG4gICAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uJywgMSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdAd2ViYXBwIGNyZWF0ZXMgZnJvbnRlbmQgY29uc3RydWN0IHdpdGggY3VzdG9tIGVycm9yIHJlc3BvbnNlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGN1c3RvbUVycm9yUmVzcG9uc2VzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaHR0cFN0YXR1czogNTAwLFxuICAgICAgICAgIHJlc3BvbnNlSHR0cFN0YXR1czogMjAwLFxuICAgICAgICAgIHJlc3BvbnNlUGFnZVBhdGg6ICcvZXJyb3IuaHRtbCcsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBuZXcgRnJvbnRlbmQoc3RhY2ssICdGcm9udGVuZCcsIHtcbiAgICAgICAgc291cmNlRGlyZWN0b3J5OiAnL3RtcC90ZXN0LWZyb250ZW5kLXNyYycsXG4gICAgICAgIGJ1aWxkT3V0cHV0RGlyZWN0b3J5OiB0ZXN0QnVpbGREaXIsXG4gICAgICAgIGVycm9yUmVzcG9uc2VzOiBjdXN0b21FcnJvclJlc3BvbnNlcyxcbiAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICAgICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgQ3VzdG9tRXJyb3JSZXNwb25zZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRXJyb3JDb2RlOiA1MDAsXG4gICAgICAgICAgICAgIFJlc3BvbnNlQ29kZTogMjAwLFxuICAgICAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2Vycm9yLmh0bWwnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdAd2ViYXBwIEN1c3RvbSBkb21haW4gZnVuY3Rpb25hbGl0eScsICgpID0+IHtcbiAgICB0ZXN0KCdAd2ViYXBwIGNyZWF0ZXMgZnJvbnRlbmQgY29uc3RydWN0IHdpdGggY3VzdG9tIGRvbWFpbicsICgpID0+IHtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlID0gQ2VydGlmaWNhdGUuZnJvbUNlcnRpZmljYXRlQXJuKFxuICAgICAgICBzdGFjayxcbiAgICAgICAgJ0NlcnRpZmljYXRlJyxcbiAgICAgICAgJ2Fybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyJyxcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGZyb250ZW5kID0gbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBjdXN0b21Eb21haW46IHtcbiAgICAgICAgICBkb21haW5OYW1lOiAnYXBwLmV4YW1wbGUuY29tJyxcbiAgICAgICAgICBjZXJ0aWZpY2F0ZSxcbiAgICAgICAgfSxcbiAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgLy8gVmVyaWZ5IENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIGhhcyBjdXN0b20gZG9tYWluXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uJywge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBBbGlhc2VzOiBbJ2FwcC5leGFtcGxlLmNvbSddLFxuICAgICAgICAgIFZpZXdlckNlcnRpZmljYXRlOiB7XG4gICAgICAgICAgICBBY21DZXJ0aWZpY2F0ZUFybjogJ2Fybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyJyxcbiAgICAgICAgICAgIFNzbFN1cHBvcnRNZXRob2Q6ICdzbmktb25seScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoZnJvbnRlbmQuZG9tYWluTmFtZSkudG9CZSgnYXBwLmV4YW1wbGUuY29tJyk7XG4gICAgICBleHBlY3QoZnJvbnRlbmQudXJsKCkpLnRvQmUoJ2h0dHBzOi8vYXBwLmV4YW1wbGUuY29tJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdAd2ViYXBwIGNyZWF0ZXMgZnJvbnRlbmQgY29uc3RydWN0IHdpdGggY3VzdG9tIGRvbWFpbiBhbmQgaG9zdGVkIHpvbmUnLCAoKSA9PiB7XG4gICAgICBjb25zdCBjZXJ0aWZpY2F0ZSA9IENlcnRpZmljYXRlLmZyb21DZXJ0aWZpY2F0ZUFybihcbiAgICAgICAgc3RhY2ssXG4gICAgICAgICdDZXJ0aWZpY2F0ZScsXG4gICAgICAgICdhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMicsXG4gICAgICApO1xuXG4gICAgICBjb25zdCBob3N0ZWRab25lID0gSG9zdGVkWm9uZS5mcm9tSG9zdGVkWm9uZUF0dHJpYnV0ZXMoc3RhY2ssICdIb3N0ZWRab25lJywge1xuICAgICAgICBob3N0ZWRab25lSWQ6ICdaMTIzNDU2Nzg5JyxcbiAgICAgICAgem9uZU5hbWU6ICdleGFtcGxlLmNvbScsXG4gICAgICB9KTtcblxuICAgICAgbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBjdXN0b21Eb21haW46IHtcbiAgICAgICAgICBkb21haW5OYW1lOiAnYXBwLmV4YW1wbGUuY29tJyxcbiAgICAgICAgICBjZXJ0aWZpY2F0ZSxcbiAgICAgICAgICBob3N0ZWRab25lLFxuICAgICAgICB9LFxuICAgICAgICBza2lwQnVpbGQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICAvLyBWZXJpZnkgUm91dGU1MyBBIHJlY29yZCBpcyBjcmVhdGVkXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6Um91dGU1Mzo6UmVjb3JkU2V0Jywge1xuICAgICAgICBUeXBlOiAnQScsXG4gICAgICAgIE5hbWU6ICdhcHAuZXhhbXBsZS5jb20uJyxcbiAgICAgICAgSG9zdGVkWm9uZUlkOiAnWjEyMzQ1Njc4OScsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0B3ZWJhcHAgVmFsaWRhdGlvbicsICgpID0+IHtcbiAgICB0ZXN0KCdAd2ViYXBwIHRocm93cyBlcnJvciB3aGVuIHNvdXJjZURpcmVjdG9yeSBpcyBtaXNzaW5nJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgICAgc291cmNlRGlyZWN0b3J5OiAnJyxcbiAgICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICAgIHNraXBCdWlsZDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KCdzb3VyY2VEaXJlY3RvcnkgaXMgcmVxdWlyZWQnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ0B3ZWJhcHAgdXNlcyBkZWZhdWx0IGJ1aWxkT3V0cHV0RGlyZWN0b3J5IHdoZW4gbm90IHByb3ZpZGVkJywgKCkgPT4ge1xuICAgICAgLy8gVXNlIHRoZSBleGlzdGluZyB0ZXN0IGJ1aWxkIGRpcmVjdG9yeVxuICAgICAgY29uc3QgZnJvbnRlbmQgPSBuZXcgRnJvbnRlbmQoc3RhY2ssICdGcm9udGVuZCcsIHtcbiAgICAgICAgc291cmNlRGlyZWN0b3J5OiB0ZXN0U3JjRGlyLFxuICAgICAgICAvLyBidWlsZE91dHB1dERpcmVjdG9yeSBub3QgcHJvdmlkZWQgLSBzaG91bGQgdXNlIGRlZmF1bHQgJy4vYnVpbGQvJ1xuICAgICAgICBza2lwQnVpbGQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KGZyb250ZW5kKS50b0JlRGVmaW5lZCgpO1xuICAgICAgLy8gVGhlIGNvbnN0cnVjdCBzaG91bGQgYmUgY3JlYXRlZCBzdWNjZXNzZnVsbHkgd2l0aCBkZWZhdWx0IGJ1aWxkT3V0cHV0RGlyZWN0b3J5XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdAd2ViYXBwIGFwcGxpZXMgY3VzdG9tIHJlbW92YWwgcG9saWN5IHRvIHJlc291cmNlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHJldGFpblN0YWNrID0gbmV3IFN0YWNrKGFwcCwgJ1JldGFpblRlc3RTdGFjaycpO1xuICAgICAgY29uc3QgZnJvbnRlbmQgPSBuZXcgRnJvbnRlbmQocmV0YWluU3RhY2ssICdGcm9udGVuZCcsIHtcbiAgICAgICAgc291cmNlRGlyZWN0b3J5OiB0ZXN0U3JjRGlyLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBza2lwQnVpbGQ6IHRydWUsXG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuUkVUQUlOLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChmcm9udGVuZCkudG9CZURlZmluZWQoKTtcblxuICAgICAgLy8gQ2hlY2sgdGhhdCB0aGUgYnVja2V0IGhhcyB0aGUgY29ycmVjdCByZW1vdmFsIHBvbGljeVxuICAgICAgY29uc3QgcmV0YWluVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2socmV0YWluU3RhY2spO1xuICAgICAgcmV0YWluVGVtcGxhdGUuaGFzUmVzb3VyY2UoJ0FXUzo6UzM6OkJ1Y2tldCcsIHtcbiAgICAgICAgRGVsZXRpb25Qb2xpY3k6ICdSZXRhaW4nLFxuICAgICAgICBVcGRhdGVSZXBsYWNlUG9saWN5OiAnUmV0YWluJyxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnQHdlYmFwcCB1c2VzIGRlZmF1bHQgREVTVFJPWSByZW1vdmFsIHBvbGljeSB3aGVuIG5vdCBzcGVjaWZpZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBkZXN0cm95U3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnRGVzdHJveVRlc3RTdGFjaycpO1xuICAgICAgY29uc3QgZnJvbnRlbmQgPSBuZXcgRnJvbnRlbmQoZGVzdHJveVN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogdGVzdFNyY0RpcixcbiAgICAgICAgYnVpbGRPdXRwdXREaXJlY3Rvcnk6IHRlc3RCdWlsZERpcixcbiAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgICAvLyByZW1vdmFsUG9saWN5IG5vdCBzcGVjaWZpZWQgLSBzaG91bGQgZGVmYXVsdCB0byBERVNUUk9ZXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KGZyb250ZW5kKS50b0JlRGVmaW5lZCgpO1xuXG4gICAgICAvLyBDaGVjayB0aGF0IHRoZSBidWNrZXQgaGFzIHRoZSBkZWZhdWx0IERFU1RST1kgcmVtb3ZhbCBwb2xpY3lcbiAgICAgIGNvbnN0IGRlc3Ryb3lUZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhkZXN0cm95U3RhY2spO1xuICAgICAgZGVzdHJveVRlbXBsYXRlLmhhc1Jlc291cmNlKCdBV1M6OlMzOjpCdWNrZXQnLCB7XG4gICAgICAgIERlbGV0aW9uUG9saWN5OiAnRGVsZXRlJyxcbiAgICAgICAgVXBkYXRlUmVwbGFjZVBvbGljeTogJ0RlbGV0ZScsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ0B3ZWJhcHAgdGhyb3dzIGVycm9yIHdoZW4gZG9tYWluTmFtZSBpcyBwcm92aWRlZCB3aXRob3V0IGNlcnRpZmljYXRlJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgICAgc291cmNlRGlyZWN0b3J5OiAnL3RtcC90ZXN0LWZyb250ZW5kLXNyYycsXG4gICAgICAgICAgYnVpbGRPdXRwdXREaXJlY3Rvcnk6IHRlc3RCdWlsZERpcixcbiAgICAgICAgICBjdXN0b21Eb21haW46IHtcbiAgICAgICAgICAgIGRvbWFpbk5hbWU6ICdhcHAuZXhhbXBsZS5jb20nLFxuICAgICAgICAgIH0gYXMgYW55LCAvLyBUeXBlIGFzc2VydGlvbiB0byBieXBhc3MgVHlwZVNjcmlwdCB2YWxpZGF0aW9uIGZvciB0ZXN0aW5nXG4gICAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ2NlcnRpZmljYXRlIGlzIHJlcXVpcmVkIHdoZW4gZG9tYWluTmFtZSBpcyBwcm92aWRlZCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQHdlYmFwcCBTZWN1cml0eSBmZWF0dXJlcycsICgpID0+IHtcbiAgICB0ZXN0KCdAd2ViYXBwIGNyZWF0ZXMgUzMgYnVja2V0IHdpdGggc2VjdXJpdHkgYmVzdCBwcmFjdGljZXMnLCAoKSA9PiB7XG4gICAgICBuZXcgRnJvbnRlbmQoc3RhY2ssICdGcm9udGVuZCcsIHtcbiAgICAgICAgc291cmNlRGlyZWN0b3J5OiAnL3RtcC90ZXN0LWZyb250ZW5kLXNyYycsXG4gICAgICAgIGJ1aWxkT3V0cHV0RGlyZWN0b3J5OiB0ZXN0QnVpbGREaXIsXG4gICAgICAgIHNraXBCdWlsZDogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIC8vIFZlcmlmeSBTMyBidWNrZXQgc2VjdXJpdHkgc2V0dGluZ3NcbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTMzo6QnVja2V0Jywge1xuICAgICAgICBCdWNrZXRFbmNyeXB0aW9uOiB7XG4gICAgICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIFNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0OiB7XG4gICAgICAgICAgICAgICAgU1NFQWxnb3JpdGhtOiAnQUVTMjU2JyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uOiB7XG4gICAgICAgICAgQmxvY2tQdWJsaWNBY2xzOiB0cnVlLFxuICAgICAgICAgIEJsb2NrUHVibGljUG9saWN5OiB0cnVlLFxuICAgICAgICAgIElnbm9yZVB1YmxpY0FjbHM6IHRydWUsXG4gICAgICAgICAgUmVzdHJpY3RQdWJsaWNCdWNrZXRzOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdAd2ViYXBwIGNyZWF0ZXMgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gd2l0aCBzZWN1cml0eSBoZWFkZXJzJywgKCkgPT4ge1xuICAgICAgbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBza2lwQnVpbGQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICAvLyBWZXJpZnkgc2VjdXJpdHkgaGVhZGVycyBmdW5jdGlvbiBleGlzdHNcbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpDbG91ZEZyb250OjpGdW5jdGlvbicsIHtcbiAgICAgICAgRnVuY3Rpb25Db25maWc6IHtcbiAgICAgICAgICBSdW50aW1lOiAnY2xvdWRmcm9udC1qcy0xLjAnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBIVFRQUyByZWRpcmVjdCBpcyBlbmFibGVkXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uJywge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBEZWZhdWx0Q2FjaGVCZWhhdmlvcjoge1xuICAgICAgICAgICAgVmlld2VyUHJvdG9jb2xQb2xpY3k6ICdyZWRpcmVjdC10by1odHRwcycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnQHdlYmFwcCBlbmFibGVzIGF1dG8gZGVsZXRlIG9iamVjdHMgb24gUzMgYnVja2V0JywgKCkgPT4ge1xuICAgICAgbmV3IEZyb250ZW5kKHN0YWNrLCAnRnJvbnRlbmQnLCB7XG4gICAgICAgIHNvdXJjZURpcmVjdG9yeTogJy90bXAvdGVzdC1mcm9udGVuZC1zcmMnLFxuICAgICAgICBidWlsZE91dHB1dERpcmVjdG9yeTogdGVzdEJ1aWxkRGlyLFxuICAgICAgICBza2lwQnVpbGQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICAvLyBWZXJpZnkgYXV0byBkZWxldGUgb2JqZWN0cyBjdXN0b20gcmVzb3VyY2UgaXMgY3JlYXRlZFxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2UoJ0N1c3RvbTo6UzNBdXRvRGVsZXRlT2JqZWN0cycsIHt9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0B3ZWJhcHAgRGVmYXVsdCB2YWx1ZXMnLCAoKSA9PiB7XG4gICAgdGVzdCgnQHdlYmFwcCB1c2VzIGRlZmF1bHQgU1BBIGVycm9yIHJlc3BvbnNlcycsICgpID0+IHtcbiAgICAgIG5ldyBGcm9udGVuZChzdGFjaywgJ0Zyb250ZW5kJywge1xuICAgICAgICBzb3VyY2VEaXJlY3Rvcnk6ICcvdG1wL3Rlc3QtZnJvbnRlbmQtc3JjJyxcbiAgICAgICAgYnVpbGRPdXRwdXREaXJlY3Rvcnk6IHRlc3RCdWlsZERpcixcbiAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICAgICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgQ3VzdG9tRXJyb3JSZXNwb25zZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRXJyb3JDb2RlOiA0MDMsXG4gICAgICAgICAgICAgIFJlc3BvbnNlQ29kZTogMjAwLFxuICAgICAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRXJyb3JDb2RlOiA0MDQsXG4gICAgICAgICAgICAgIFJlc3BvbnNlQ29kZTogMjAwLFxuICAgICAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdAd2ViYXBwIGV4cG9ydHMgZGVmYXVsdCBTUEEgZXJyb3IgcmVzcG9uc2VzJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KERFRkFVTFRfU1BBX0VSUk9SX1JFU1BPTlNFUykudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICBodHRwU3RhdHVzOiA0MDMsXG4gICAgICAgICAgcmVzcG9uc2VIdHRwU3RhdHVzOiAyMDAsXG4gICAgICAgICAgcmVzcG9uc2VQYWdlUGF0aDogJy9pbmRleC5odG1sJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGh0dHBTdGF0dXM6IDQwNCxcbiAgICAgICAgICByZXNwb25zZUh0dHBTdGF0dXM6IDIwMCxcbiAgICAgICAgICByZXNwb25zZVBhZ2VQYXRoOiAnL2luZGV4Lmh0bWwnLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdAd2ViYXBwIEFkZGl0aW9uYWwgZGlzdHJpYnV0aW9uIHByb3BlcnRpZXMnLCAoKSA9PiB7XG4gICAgdGVzdCgnQHdlYmFwcCBhY2NlcHRzIGFkZGl0aW9uYWwgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gcHJvcGVydGllcycsICgpID0+IHtcbiAgICAgIG5ldyBGcm9udGVuZChzdGFjaywgJ0Zyb250ZW5kJywge1xuICAgICAgICBzb3VyY2VEaXJlY3Rvcnk6ICcvdG1wL3Rlc3QtZnJvbnRlbmQtc3JjJyxcbiAgICAgICAgYnVpbGRPdXRwdXREaXJlY3Rvcnk6IHRlc3RCdWlsZERpcixcbiAgICAgICAgZGlzdHJpYnV0aW9uUHJvcHM6IHtcbiAgICAgICAgICBjb21tZW50OiAnQ3VzdG9tIGZyb250ZW5kIGRpc3RyaWJ1dGlvbicsXG4gICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgc2tpcEJ1aWxkOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvbicsIHtcbiAgICAgICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgQ29tbWVudDogJ0N1c3RvbSBmcm9udGVuZCBkaXN0cmlidXRpb24nLFxuICAgICAgICAgIEVuYWJsZWQ6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|
package/package.json
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cdklabs/cdk-appmod-catalog-blueprints",
|
|
3
|
+
"description": "Serverless infrastructure components organized by business use cases",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git@github.com:cdklabs/cdk-appmod-catalog-blueprints.git"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "npx projen build",
|
|
10
|
+
"build:fast": "npx projen build:fast",
|
|
11
|
+
"bump": "npx projen bump",
|
|
12
|
+
"clobber": "npx projen clobber",
|
|
13
|
+
"compat": "npx projen compat",
|
|
14
|
+
"compile": "npx projen compile",
|
|
15
|
+
"default": "npx projen default",
|
|
16
|
+
"docgen": "npx projen docgen",
|
|
17
|
+
"eject": "npx projen eject",
|
|
18
|
+
"eslint": "npx projen eslint",
|
|
19
|
+
"integ": "npx projen integ",
|
|
20
|
+
"integ:update": "npx projen integ:update",
|
|
21
|
+
"package": "npx projen package",
|
|
22
|
+
"package-all": "npx projen package-all",
|
|
23
|
+
"package:dotnet": "npx projen package:dotnet",
|
|
24
|
+
"package:go": "npx projen package:go",
|
|
25
|
+
"package:java": "npx projen package:java",
|
|
26
|
+
"package:js": "npx projen package:js",
|
|
27
|
+
"package:python": "npx projen package:python",
|
|
28
|
+
"post-compile": "npx projen post-compile",
|
|
29
|
+
"post-upgrade": "npx projen post-upgrade",
|
|
30
|
+
"pre-compile": "npx projen pre-compile",
|
|
31
|
+
"release": "npx projen release",
|
|
32
|
+
"rosetta:extract": "npx projen rosetta:extract",
|
|
33
|
+
"test": "npx projen test",
|
|
34
|
+
"test:cdk-nag:all": "npx projen test:cdk-nag:all",
|
|
35
|
+
"test:cdk-nag:document-processing": "npx projen test:cdk-nag:document-processing",
|
|
36
|
+
"test:cdk-nag:webapp": "npx projen test:cdk-nag:webapp",
|
|
37
|
+
"test:document-processing": "npx projen test:document-processing",
|
|
38
|
+
"test:document-processing:unit": "npx projen test:document-processing:unit",
|
|
39
|
+
"test:security": "npx projen test:security",
|
|
40
|
+
"test:watch": "npx projen test:watch",
|
|
41
|
+
"test:webapp": "npx projen test:webapp",
|
|
42
|
+
"test:webapp:core": "npx projen test:webapp:core",
|
|
43
|
+
"test:webapp:frontend": "npx projen test:webapp:frontend",
|
|
44
|
+
"test:webapp:quickstart": "npx projen test:webapp:quickstart",
|
|
45
|
+
"test:webapp:unit": "npx projen test:webapp:unit",
|
|
46
|
+
"unbump": "npx projen unbump",
|
|
47
|
+
"upgrade": "npx projen upgrade",
|
|
48
|
+
"upgrade-cdklabs-projen-project-types": "npx projen upgrade-cdklabs-projen-project-types",
|
|
49
|
+
"upgrade-dev-deps": "npx projen upgrade-dev-deps",
|
|
50
|
+
"watch": "npx projen watch",
|
|
51
|
+
"projen": "npx projen"
|
|
52
|
+
},
|
|
53
|
+
"author": {
|
|
54
|
+
"name": "Amazon Web Services",
|
|
55
|
+
"email": "aws-cdk-dev@amazon.com",
|
|
56
|
+
"organization": true
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@aws-cdk/aws-lambda-python-alpha": "2.192.0-alpha.0",
|
|
60
|
+
"@aws-cdk/integ-runner": "latest",
|
|
61
|
+
"@aws-cdk/integ-tests-alpha": "latest",
|
|
62
|
+
"@stylistic/eslint-plugin": "^2",
|
|
63
|
+
"@types/jest": "^29.5.14",
|
|
64
|
+
"@types/node": "^18",
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8",
|
|
66
|
+
"@typescript-eslint/parser": "^8",
|
|
67
|
+
"aws-cdk-lib": "2.216.0",
|
|
68
|
+
"cdk-nag": "^2.37.35",
|
|
69
|
+
"cdklabs-projen-project-types": "^0.3.1",
|
|
70
|
+
"commit-and-tag-version": "^12",
|
|
71
|
+
"constructs": "10.0.5",
|
|
72
|
+
"eslint": "^9",
|
|
73
|
+
"eslint-import-resolver-typescript": "^4.2.5",
|
|
74
|
+
"eslint-plugin-import": "^2.31.0",
|
|
75
|
+
"jest": "^29.7.0",
|
|
76
|
+
"jest-junit": "^16",
|
|
77
|
+
"jsii": "~5.9.5",
|
|
78
|
+
"jsii-diff": "^1.110.0",
|
|
79
|
+
"jsii-docgen": "^10.5.0",
|
|
80
|
+
"jsii-pacmak": "^1.110.0",
|
|
81
|
+
"jsii-rosetta": "~5.8.0",
|
|
82
|
+
"projen": "^0.95.2",
|
|
83
|
+
"ts-jest": "^29.3.0",
|
|
84
|
+
"ts-node": "^10.9.2",
|
|
85
|
+
"typescript": "^5.8.2"
|
|
86
|
+
},
|
|
87
|
+
"peerDependencies": {
|
|
88
|
+
"@aws-cdk/aws-lambda-python-alpha": "2.192.0-alpha.0",
|
|
89
|
+
"aws-cdk-lib": "^2.216.0",
|
|
90
|
+
"constructs": "^10.0.5"
|
|
91
|
+
},
|
|
92
|
+
"keywords": [
|
|
93
|
+
"cdk"
|
|
94
|
+
],
|
|
95
|
+
"engines": {
|
|
96
|
+
"node": ">= 18.12.0"
|
|
97
|
+
},
|
|
98
|
+
"main": "lib/index.js",
|
|
99
|
+
"license": "Apache-2.0",
|
|
100
|
+
"publishConfig": {
|
|
101
|
+
"access": "public"
|
|
102
|
+
},
|
|
103
|
+
"version": "1.0.0",
|
|
104
|
+
"jest": {
|
|
105
|
+
"coverageProvider": "v8",
|
|
106
|
+
"testMatch": [
|
|
107
|
+
"<rootDir>/@(use-cases|test)/**/*(*.)@(spec|test).ts?(x)",
|
|
108
|
+
"<rootDir>/@(use-cases|test)/**/__tests__/**/*.ts?(x)",
|
|
109
|
+
"<rootDir>/@(projenrc)/**/*(*.)@(spec|test).ts?(x)",
|
|
110
|
+
"<rootDir>/@(projenrc)/**/__tests__/**/*.ts?(x)"
|
|
111
|
+
],
|
|
112
|
+
"clearMocks": true,
|
|
113
|
+
"collectCoverage": true,
|
|
114
|
+
"coverageReporters": [
|
|
115
|
+
"json",
|
|
116
|
+
"lcov",
|
|
117
|
+
"clover",
|
|
118
|
+
"cobertura",
|
|
119
|
+
"text"
|
|
120
|
+
],
|
|
121
|
+
"coverageDirectory": "coverage",
|
|
122
|
+
"coveragePathIgnorePatterns": [
|
|
123
|
+
"/node_modules/"
|
|
124
|
+
],
|
|
125
|
+
"testPathIgnorePatterns": [
|
|
126
|
+
"/node_modules/"
|
|
127
|
+
],
|
|
128
|
+
"watchPathIgnorePatterns": [
|
|
129
|
+
"/node_modules/"
|
|
130
|
+
],
|
|
131
|
+
"reporters": [
|
|
132
|
+
"default",
|
|
133
|
+
[
|
|
134
|
+
"jest-junit",
|
|
135
|
+
{
|
|
136
|
+
"outputDirectory": "test-reports"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
],
|
|
140
|
+
"transform": {
|
|
141
|
+
"^.+\\.[t]sx?$": [
|
|
142
|
+
"ts-jest",
|
|
143
|
+
{
|
|
144
|
+
"tsconfig": "tsconfig.dev.json"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"types": "lib/index.d.ts",
|
|
150
|
+
"stability": "experimental",
|
|
151
|
+
"jsii": {
|
|
152
|
+
"outdir": "dist",
|
|
153
|
+
"targets": {
|
|
154
|
+
"java": {
|
|
155
|
+
"package": "io.github.cdklabs.appmod.catalog.blueprints",
|
|
156
|
+
"maven": {
|
|
157
|
+
"groupId": "io.github.cdklabs",
|
|
158
|
+
"artifactId": "appmod-catalog-blueprints"
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"python": {
|
|
162
|
+
"distName": "appmod-catalog-blueprints",
|
|
163
|
+
"module": "appmod_catalog_blueprints"
|
|
164
|
+
},
|
|
165
|
+
"dotnet": {
|
|
166
|
+
"namespace": "CdklabsAppmodCatalogBlueprints",
|
|
167
|
+
"packageId": "CdklabsAppmodCatalogBlueprints"
|
|
168
|
+
},
|
|
169
|
+
"go": {
|
|
170
|
+
"moduleName": "github.com/cdklabs/appmod-catalog-blueprints-go"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"tsc": {
|
|
174
|
+
"outDir": "lib",
|
|
175
|
+
"rootDir": "use-cases"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"files": [
|
|
179
|
+
"lib/",
|
|
180
|
+
".jsii"
|
|
181
|
+
],
|
|
182
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
|
|
183
|
+
}
|