@fjall/components-infrastructure 0.86.0 → 0.87.3
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/README.md +3 -3
- package/dist/lib/app.d.ts +166 -6
- package/dist/lib/app.js +212 -20
- package/dist/lib/aspects/resourceInventory.d.ts +4 -4
- package/dist/lib/aspects/resourceInventory.js +3 -3
- package/dist/lib/config/aws/backupGlobalSettings.js +1 -2
- package/dist/lib/config/aws/identityCenter.js +1 -5
- package/dist/lib/config/aws/organisation.js +1 -4
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +7 -1
- package/dist/lib/patterns/aws/buildkite.js +3 -2
- package/dist/lib/patterns/aws/cdn.d.ts +164 -0
- package/dist/lib/patterns/aws/cdn.js +264 -0
- package/dist/lib/patterns/aws/compute.d.ts +278 -59
- package/dist/lib/patterns/aws/compute.js +384 -188
- package/dist/lib/patterns/aws/connections.d.ts +46 -0
- package/dist/lib/patterns/aws/connections.js +159 -0
- package/dist/lib/patterns/aws/database.d.ts +124 -11
- package/dist/lib/patterns/aws/database.js +188 -66
- package/dist/lib/patterns/aws/hostedZone.js +1 -1
- package/dist/lib/patterns/aws/index.d.ts +3 -0
- package/dist/lib/patterns/aws/index.js +4 -1
- package/dist/lib/patterns/aws/interfaces/compute.d.ts +121 -0
- package/dist/lib/patterns/aws/interfaces/compute.js +48 -0
- package/dist/lib/patterns/aws/interfaces/connector.d.ts +183 -0
- package/dist/lib/patterns/aws/interfaces/connector.js +117 -0
- package/dist/lib/patterns/aws/interfaces/database.d.ts +136 -0
- package/dist/lib/patterns/aws/interfaces/database.js +65 -0
- package/dist/lib/patterns/aws/interfaces/index.d.ts +12 -0
- package/dist/lib/patterns/aws/interfaces/index.js +49 -0
- package/dist/lib/patterns/aws/interfaces/messaging.d.ts +146 -0
- package/dist/lib/patterns/aws/interfaces/messaging.js +56 -0
- package/dist/lib/patterns/aws/interfaces/pattern.d.ts +403 -0
- package/dist/lib/patterns/aws/interfaces/pattern.js +36 -0
- package/dist/lib/patterns/aws/interfaces/storage.d.ts +136 -0
- package/dist/lib/patterns/aws/interfaces/storage.js +48 -0
- package/dist/lib/patterns/aws/messaging.d.ts +183 -0
- package/dist/lib/patterns/aws/messaging.js +239 -0
- package/dist/lib/patterns/aws/network.js +4 -4
- package/dist/lib/patterns/aws/pattern.d.ts +67 -0
- package/dist/lib/patterns/aws/pattern.js +69 -0
- package/dist/lib/patterns/aws/payload.d.ts +87 -0
- package/dist/lib/patterns/aws/payload.js +526 -0
- package/dist/lib/patterns/aws/storage.d.ts +127 -15
- package/dist/lib/patterns/aws/storage.js +234 -38
- package/dist/lib/resources/aws/backup/backupPlan.js +1 -6
- package/dist/lib/resources/aws/backup/backupVault.js +1 -2
- package/dist/lib/resources/aws/base/awsStack.d.ts +0 -2
- package/dist/lib/resources/aws/base/awsStack.js +1 -7
- package/dist/lib/resources/aws/cdn/cloudFront.d.ts +71 -0
- package/dist/lib/resources/aws/cdn/cloudFront.js +176 -0
- package/dist/lib/resources/aws/cdn/index.d.ts +1 -0
- package/dist/lib/resources/aws/cdn/index.js +18 -0
- package/dist/lib/resources/aws/compute/ec2.d.ts +5 -0
- package/dist/lib/resources/aws/compute/ec2.js +33 -6
- package/dist/lib/resources/aws/compute/ecs.d.ts +32 -25
- package/dist/lib/resources/aws/compute/ecs.js +31 -115
- package/dist/lib/resources/aws/compute/lambda.d.ts +94 -5
- package/dist/lib/resources/aws/compute/lambda.js +209 -32
- package/dist/lib/resources/aws/database/database.js +1 -1
- package/dist/lib/resources/aws/database/dynamodb.d.ts +70 -0
- package/dist/lib/resources/aws/database/dynamodb.js +181 -0
- package/dist/lib/resources/aws/database/index.d.ts +1 -0
- package/dist/lib/resources/aws/database/index.js +2 -1
- package/dist/lib/resources/aws/database/migrationLambda.d.ts +80 -0
- package/dist/lib/resources/aws/database/migrationLambda.js +119 -0
- package/dist/lib/resources/aws/database/rdsAurora.d.ts +15 -0
- package/dist/lib/resources/aws/database/rdsAurora.js +41 -18
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +12 -8
- package/dist/lib/resources/aws/database/rdsInstance.js +2 -2
- package/dist/lib/resources/aws/index.d.ts +2 -0
- package/dist/lib/resources/aws/index.js +3 -1
- package/dist/lib/resources/aws/messaging/eventbridge.d.ts +28 -0
- package/dist/lib/resources/aws/messaging/eventbridge.js +53 -0
- package/dist/lib/resources/aws/messaging/index.d.ts +3 -0
- package/dist/lib/resources/aws/messaging/index.js +20 -0
- package/dist/lib/resources/aws/messaging/sns.d.ts +35 -0
- package/dist/lib/resources/aws/messaging/sns.js +70 -0
- package/dist/lib/resources/aws/messaging/sqs.d.ts +105 -0
- package/dist/lib/resources/aws/messaging/sqs.js +231 -0
- package/dist/lib/resources/aws/messaging/utils.d.ts +3 -0
- package/dist/lib/resources/aws/messaging/utils.js +7 -0
- package/dist/lib/resources/aws/networking/ipam.js +1 -2
- package/dist/lib/resources/aws/networking/ipamPool.js +3 -2
- package/dist/lib/resources/aws/networking/vpc.js +1 -2
- package/dist/lib/resources/aws/storage/ecr.js +8 -5
- package/dist/lib/resources/aws/storage/s3.js +1 -2
- package/dist/lib/resources/aws/utilities/awsCustomResource.js +1 -1
- package/dist/lib/resources/aws/utilities/customResource.js +1 -1
- package/dist/lib/utils/getConfig.js +3 -2
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/index.js +2 -1
- package/dist/lib/utils/manifestWriter.d.ts +174 -0
- package/dist/lib/utils/manifestWriter.js +233 -0
- package/dist/lib/utils/standardTagsAspect.js +1 -8
- package/dist/lib/utils/validationLogger.d.ts +34 -0
- package/dist/lib/utils/validationLogger.js +83 -0
- package/package.json +3 -3
- package/dist/lib/__tests__/setup.d.ts +0 -48
- package/dist/lib/__tests__/setup.js +0 -1
- package/dist/lib/patterns/aws/cicdRole.d.ts +0 -67
- package/dist/lib/patterns/aws/cicdRole.js +0 -68
- package/dist/lib/resources/aws/cicd/cicdRole.d.ts +0 -65
- package/dist/lib/resources/aws/cicd/cicdRole.js +0 -191
- package/dist/lib/resources/aws/compute/ecsFreeTier.d.ts +0 -75
- package/dist/lib/resources/aws/compute/ecsFreeTier.js +0 -1
- package/dist/lib/resources/aws/compute/ecsSpot.d.ts +0 -75
- package/dist/lib/resources/aws/compute/ecsSpot.js +0 -1
- package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +0 -20
- package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +0 -1
- package/dist/lib/resources/aws/utilities/cfnOutput.d.ts +0 -5
- package/dist/lib/resources/aws/utilities/cfnOutput.js +0 -1
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CdnFactory = exports.Cdn = void 0;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
|
+
const cdn_1 = require("../../resources/aws/cdn");
|
|
6
|
+
const storage_1 = require("./storage");
|
|
7
|
+
const compute_1 = require("./compute");
|
|
8
|
+
const validationLogger_js_1 = require("../../utils/validationLogger.js");
|
|
9
|
+
/**
|
|
10
|
+
* Type guard to check if a value is a Fjall storage resource.
|
|
11
|
+
*/
|
|
12
|
+
function isStorageResource(value) {
|
|
13
|
+
return (value instanceof storage_1.PrivateStorage ||
|
|
14
|
+
value instanceof storage_1.WebsiteStorage ||
|
|
15
|
+
value instanceof storage_1.PublicStorage);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validates CDN props and logs warnings for misconfigured options.
|
|
19
|
+
*/
|
|
20
|
+
function validateCdnProps(props) {
|
|
21
|
+
// Validate certificate region warning
|
|
22
|
+
if (props.certificate && props.domainNames && props.domainNames.length > 0) {
|
|
23
|
+
validationLogger_js_1.FjallLogger.info("CloudFront certificates must be in us-east-1 region. " +
|
|
24
|
+
"Ensure your certificate was created in us-east-1.");
|
|
25
|
+
}
|
|
26
|
+
// Validate domain names require certificate
|
|
27
|
+
if (props.domainNames && props.domainNames.length > 0 && !props.certificate) {
|
|
28
|
+
validationLogger_js_1.FjallLogger.warn("'domainNames' provided but no 'certificate' specified. " +
|
|
29
|
+
"Custom domain names require an ACM certificate in us-east-1.");
|
|
30
|
+
}
|
|
31
|
+
// Validate ALB origin
|
|
32
|
+
if (props.originType === "alb") {
|
|
33
|
+
const albProps = props;
|
|
34
|
+
if ((0, compute_1.isCompute)(albProps.loadBalancer) &&
|
|
35
|
+
(0, compute_1.isEcsCompute)(albProps.loadBalancer)) {
|
|
36
|
+
const lb = albProps.loadBalancer.getLoadBalancer();
|
|
37
|
+
if (!lb) {
|
|
38
|
+
throw new Error("Compute resource does not have a load balancer. " +
|
|
39
|
+
"Ensure ECS compute has loadBalancer enabled for CDN origin.");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Validate smart origin
|
|
44
|
+
if (props.originType === "auto") {
|
|
45
|
+
const smartProps = props;
|
|
46
|
+
if ((0, compute_1.isCompute)(smartProps.origin)) {
|
|
47
|
+
if ((0, compute_1.isEcsCompute)(smartProps.origin)) {
|
|
48
|
+
if (!smartProps.origin.getLoadBalancer()) {
|
|
49
|
+
throw new Error("ECS compute must have a load balancer for CDN origin. " +
|
|
50
|
+
"Enable loadBalancer in your ECS compute configuration.");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if ((0, compute_1.isLambdaCompute)(smartProps.origin)) {
|
|
54
|
+
if (!smartProps.origin.getFunctionUrl()) {
|
|
55
|
+
throw new Error("Lambda compute must have a function URL for CDN origin. " +
|
|
56
|
+
"Enable functionUrl in your Lambda compute configuration.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Must be EC2
|
|
61
|
+
throw new Error("EC2 compute type is not supported for CDN origin. " +
|
|
62
|
+
"Use ECS with load balancer or Lambda with function URL.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* CDN wrapper class that extends CloudFrontDistribution with Fjall patterns.
|
|
69
|
+
*/
|
|
70
|
+
class Cdn extends cdn_1.CloudFrontDistribution {
|
|
71
|
+
constructor(scope, id, props) {
|
|
72
|
+
const resolvedProps = Cdn.resolveProps(props);
|
|
73
|
+
super(scope, id, resolvedProps);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve ICdnProps to CloudFrontDistributionProps.
|
|
77
|
+
*/
|
|
78
|
+
static resolveProps(props) {
|
|
79
|
+
const defaultOrigin = Cdn.resolveDefaultOrigin(props);
|
|
80
|
+
const behaviours = Cdn.resolveBehaviours(props.behaviours);
|
|
81
|
+
return {
|
|
82
|
+
defaultOrigin,
|
|
83
|
+
defaultCachePolicy: props.cachePolicy,
|
|
84
|
+
defaultAllowedMethods: props.defaultAllowedMethods,
|
|
85
|
+
behaviours,
|
|
86
|
+
domainNames: props.domainNames,
|
|
87
|
+
certificate: props.certificate,
|
|
88
|
+
comment: props.comment,
|
|
89
|
+
enableLogging: props.enableLogging,
|
|
90
|
+
logBucket: props.logBucket,
|
|
91
|
+
priceClass: props.priceClass,
|
|
92
|
+
forwardHostHeader: props.forwardHostHeader
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Transform smart behaviours to CdnBehaviour objects.
|
|
97
|
+
*/
|
|
98
|
+
static resolveBehaviours(behaviours) {
|
|
99
|
+
if (!behaviours || behaviours.length === 0) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return behaviours.map((behaviour) => ({
|
|
103
|
+
pathPattern: behaviour.pathPattern,
|
|
104
|
+
origin: Cdn.detectOriginFromResource(behaviour.origin),
|
|
105
|
+
cachePolicy: behaviour.cachePolicy,
|
|
106
|
+
allowedMethods: behaviour.allowedMethods
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the default origin from ICdnProps.
|
|
111
|
+
*/
|
|
112
|
+
static resolveDefaultOrigin(props) {
|
|
113
|
+
switch (props.originType) {
|
|
114
|
+
case "s3": {
|
|
115
|
+
const bucket = isStorageResource(props.bucket)
|
|
116
|
+
? props.bucket.getBucket()
|
|
117
|
+
: props.bucket;
|
|
118
|
+
return {
|
|
119
|
+
type: "s3",
|
|
120
|
+
bucket,
|
|
121
|
+
originPath: props.originPath
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
case "alb": {
|
|
125
|
+
let loadBalancer;
|
|
126
|
+
if ((0, compute_1.isCompute)(props.loadBalancer)) {
|
|
127
|
+
if ((0, compute_1.isEcsCompute)(props.loadBalancer)) {
|
|
128
|
+
const lb = props.loadBalancer.getLoadBalancer();
|
|
129
|
+
if (!lb) {
|
|
130
|
+
throw new Error("Compute resource does not have a load balancer. " +
|
|
131
|
+
"Ensure ECS compute has loadBalancer enabled for CDN origin.");
|
|
132
|
+
}
|
|
133
|
+
loadBalancer = lb;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
throw new Error("Only ECS compute with load balancer is supported for ALB origin. " +
|
|
137
|
+
"Lambda and EC2 compute types are not supported.");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
loadBalancer = props.loadBalancer;
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
type: "alb",
|
|
145
|
+
loadBalancer,
|
|
146
|
+
protocolPolicy: props.protocolPolicy
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
case "http":
|
|
150
|
+
return {
|
|
151
|
+
type: "http",
|
|
152
|
+
domainName: props.domainName,
|
|
153
|
+
originPath: props.originPath,
|
|
154
|
+
protocolPolicy: props.protocolPolicy
|
|
155
|
+
};
|
|
156
|
+
case "auto":
|
|
157
|
+
return Cdn.detectOriginFromResource(props.origin);
|
|
158
|
+
default: {
|
|
159
|
+
const _exhaustive = props;
|
|
160
|
+
throw new Error(`Unsupported CDN origin type: ${props.originType}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Auto-detect origin configuration from a Fjall resource.
|
|
166
|
+
*/
|
|
167
|
+
static detectOriginFromResource(resource) {
|
|
168
|
+
// String → HTTP origin
|
|
169
|
+
if (typeof resource === "string") {
|
|
170
|
+
return {
|
|
171
|
+
type: "http",
|
|
172
|
+
domainName: resource
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// StorageResource → S3 origin
|
|
176
|
+
if (isStorageResource(resource)) {
|
|
177
|
+
return {
|
|
178
|
+
type: "s3",
|
|
179
|
+
bucket: resource.getBucket()
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// ECS Compute → ALB origin
|
|
183
|
+
if ((0, compute_1.isEcsCompute)(resource)) {
|
|
184
|
+
const loadBalancer = resource.getLoadBalancer();
|
|
185
|
+
if (loadBalancer) {
|
|
186
|
+
return {
|
|
187
|
+
type: "alb",
|
|
188
|
+
loadBalancer
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Lambda Compute → HTTP origin (function URL)
|
|
193
|
+
if ((0, compute_1.isLambdaCompute)(resource)) {
|
|
194
|
+
const functionUrl = resource.getFunctionUrl();
|
|
195
|
+
if (functionUrl) {
|
|
196
|
+
// Lambda function URL is an HTTP origin
|
|
197
|
+
// Extract domain from URL token using CloudFormation intrinsics
|
|
198
|
+
// URL format: https://<domain>/
|
|
199
|
+
// Split by "/" gives ["https:", "", "<domain>", ""]
|
|
200
|
+
// Select index 2 to get the domain
|
|
201
|
+
const domainName = aws_cdk_lib_1.Fn.select(2, aws_cdk_lib_1.Fn.split("/", functionUrl));
|
|
202
|
+
return {
|
|
203
|
+
type: "http",
|
|
204
|
+
domainName
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
throw new Error(`Unable to detect CDN origin from resource: ${typeof resource}. ` +
|
|
209
|
+
"Provide explicit origin configuration using originType.");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.Cdn = Cdn;
|
|
213
|
+
/**
|
|
214
|
+
* Factory for creating CDN (CloudFront) distributions.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* // S3 origin
|
|
218
|
+
* const assets = app.addStorage(StorageFactory.build("Assets", { bucketType: "private" }));
|
|
219
|
+
* app.addCdn(CdnFactory.build("AssetsCdn", {
|
|
220
|
+
* originType: "s3",
|
|
221
|
+
* bucket: assets
|
|
222
|
+
* }));
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* // ALB origin (ECS)
|
|
226
|
+
* const api = app.addCompute(ComputeFactory.build("Api", { type: "ecs", ... }));
|
|
227
|
+
* app.addCdn(CdnFactory.build("ApiCdn", {
|
|
228
|
+
* originType: "alb",
|
|
229
|
+
* loadBalancer: api
|
|
230
|
+
* }));
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* // Smart detection
|
|
234
|
+
* app.addCdn(CdnFactory.build("AppCdn", {
|
|
235
|
+
* originType: "auto",
|
|
236
|
+
* origin: assets
|
|
237
|
+
* }));
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* // Custom domain
|
|
241
|
+
* app.addCdn(CdnFactory.build("AppCdn", {
|
|
242
|
+
* originType: "s3",
|
|
243
|
+
* bucket: assets,
|
|
244
|
+
* domainNames: ["app.example.com"],
|
|
245
|
+
* certificate: myCert
|
|
246
|
+
* }));
|
|
247
|
+
*/
|
|
248
|
+
class CdnFactory {
|
|
249
|
+
/**
|
|
250
|
+
* Build a CDN factory function.
|
|
251
|
+
*
|
|
252
|
+
* @param id - Unique identifier for the CDN
|
|
253
|
+
* @param props - CDN configuration properties
|
|
254
|
+
* @returns Factory function that creates the CDN when invoked
|
|
255
|
+
*/
|
|
256
|
+
static build(id, props) {
|
|
257
|
+
return (_app, scope) => {
|
|
258
|
+
validateCdnProps(props);
|
|
259
|
+
return new Cdn(scope, id, props);
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
exports.CdnFactory = CdnFactory;
|
|
264
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vbGliL3BhdHRlcm5zL2F3cy9jZG4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsNkNBQWlDO0FBT2pDLGlEQU1pQztBQUNqQyx1Q0FBMEU7QUFDMUUsdUNBS21CO0FBQ25CLHlFQUE4RDtBQU85RDs7R0FFRztBQUNILFNBQVMsaUJBQWlCLENBQ3hCLEtBQWM7SUFFZCxPQUFPLENBQ0wsS0FBSyxZQUFZLHdCQUFjO1FBQy9CLEtBQUssWUFBWSx3QkFBYztRQUMvQixLQUFLLFlBQVksdUJBQWEsQ0FDL0IsQ0FBQztBQUNKLENBQUM7QUEyRkQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLEtBQWdCO0lBQ3hDLHNDQUFzQztJQUN0QyxJQUFJLEtBQUssQ0FBQyxXQUFXLElBQUksS0FBSyxDQUFDLFdBQVcsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUMzRSxpQ0FBVyxDQUFDLElBQUksQ0FDZCx1REFBdUQ7WUFDckQsbURBQW1ELENBQ3RELENBQUM7SUFDSixDQUFDO0lBRUQsNENBQTRDO0lBQzVDLElBQUksS0FBSyxDQUFDLFdBQVcsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDNUUsaUNBQVcsQ0FBQyxJQUFJLENBQ2QseURBQXlEO1lBQ3ZELDhEQUE4RCxDQUNqRSxDQUFDO0lBQ0osQ0FBQztJQUVELHNCQUFzQjtJQUN0QixJQUFJLEtBQUssQ0FBQyxVQUFVLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDL0IsTUFBTSxRQUFRLEdBQUcsS0FBb0IsQ0FBQztRQUN0QyxJQUNFLElBQUEsbUJBQVMsRUFBQyxRQUFRLENBQUMsWUFBWSxDQUFDO1lBQ2hDLElBQUEsc0JBQVksRUFBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVB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QUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztDQUNGO0FBZEQsZ0NBY0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBGbiB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgdHlwZSBJQnVja2V0IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0IHsgdHlwZSBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVsYXN0aWNsb2FkYmFsYW5jaW5ndjJcIjtcbmltcG9ydCB7IHR5cGUgSUNlcnRpZmljYXRlIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jZXJ0aWZpY2F0ZW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgSUNhY2hlUG9saWN5IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZGZyb250XCI7XG5cbmltcG9ydCB0eXBlIEFwcCBmcm9tIFwiLi4vLi4vYXBwXCI7XG5pbXBvcnQge1xuICBDbG91ZEZyb250RGlzdHJpYnV0aW9uLFxuICB0eXBlIENsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wcyxcbiAgdHlwZSBDZG5PcmlnaW5Db25maWcsXG4gIHR5cGUgQ2RuQmVoYXZpb3VyLFxuICB0eXBlIENhY2hlUG9saWN5UHJlc2V0XG59IGZyb20gXCIuLi8uLi9yZXNvdXJjZXMvYXdzL2NkblwiO1xuaW1wb3J0IHsgUHJpdmF0ZVN0b3JhZ2UsIFdlYnNpdGVTdG9yYWdlLCBQdWJsaWNTdG9yYWdlIH0gZnJvbSBcIi4vc3RvcmFnZVwiO1xuaW1wb3J0IHtcbiAgdHlwZSBBbnlDb21wdXRlLFxuICBpc0NvbXB1dGUsXG4gIGlzRWNzQ29tcHV0ZSxcbiAgaXNMYW1iZGFDb21wdXRlXG59IGZyb20gXCIuL2NvbXB1dGVcIjtcbmltcG9ydCB7IEZqYWxsTG9nZ2VyIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3ZhbGlkYXRpb25Mb2dnZXIuanNcIjtcblxuLyoqXG4gKiBVbmlvbiB0eXBlIGZvciBGamFsbCBTMyBzdG9yYWdlIGNsYXNzZXMuXG4gKi9cbnR5cGUgU3RvcmFnZVJlc291cmNlID0gUHJpdmF0ZVN0b3JhZ2UgfCBXZWJzaXRlU3RvcmFnZSB8IFB1YmxpY1N0b3JhZ2U7XG5cbi8qKlxuICogVHlwZSBndWFyZCB0byBjaGVjayBpZiBhIHZhbHVlIGlzIGEgRmphbGwgc3RvcmFnZSByZXNvdXJjZS5cbiAqL1xuZnVuY3Rpb24gaXNTdG9yYWdlUmVzb3VyY2UoXG4gIHZhbHVlOiB1bmtub3duXG4pOiB2YWx1ZSBpcyBQcml2YXRlU3RvcmFnZSB8IFdlYnNpdGVTdG9yYWdlIHwgUHVibGljU3RvcmFnZSB7XG4gIHJldHVybiAoXG4gICAgdmFsdWUgaW5zdGFuY2VvZiBQcml2YXRlU3RvcmFnZSB8fFxuICAgIHZhbHVlIGluc3RhbmNlb2YgV2Vic2l0ZVN0b3JhZ2UgfHxcbiAgICB2YWx1ZSBpbnN0YW5jZW9mIFB1YmxpY1N0b3JhZ2VcbiAgKTtcbn1cblxuLyoqXG4gKiBTMyBvcmlnaW4gQ0ROIHByb3BzIC0gdXNlIHdpdGggUzMgYnVja2V0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUzNDZG5Qcm9wcyB7XG4gIG9yaWdpblR5cGU6IFwiczNcIjtcbiAgYnVja2V0OiBJQnVja2V0IHwgU3RvcmFnZVJlc291cmNlO1xuICBvcmlnaW5QYXRoPzogc3RyaW5nO1xuICBjYWNoZVBvbGljeT86IENhY2hlUG9saWN5UHJlc2V0IHwgSUNhY2hlUG9saWN5O1xuICBkZWZhdWx0QWxsb3dlZE1ldGhvZHM/OiBcIkdFVF9IRUFEXCIgfCBcIkdFVF9IRUFEX09QVElPTlNcIiB8IFwiQUxMXCI7XG4gIGJlaGF2aW91cnM/OiBTbWFydENkbkJlaGF2aW91cltdO1xuICBkb21haW5OYW1lcz86IHN0cmluZ1tdO1xuICBjZXJ0aWZpY2F0ZT86IElDZXJ0aWZpY2F0ZTtcbiAgY29tbWVudD86IHN0cmluZztcbiAgZW5hYmxlTG9nZ2luZz86IGJvb2xlYW47XG4gIGxvZ0J1Y2tldD86IElCdWNrZXQ7XG4gIHByaWNlQ2xhc3M/OiBcIlByaWNlQ2xhc3NfMTAwXCIgfCBcIlByaWNlQ2xhc3NfMjAwXCIgfCBcIlByaWNlQ2xhc3NfQWxsXCI7XG4gIGZvcndhcmRIb3N0SGVhZGVyPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBTEIgb3JpZ2luIENETiBwcm9wcyAtIHVzZSB3aXRoIEFwcGxpY2F0aW9uIExvYWQgQmFsYW5jZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBbGJDZG5Qcm9wcyB7XG4gIG9yaWdpblR5cGU6IFwiYWxiXCI7XG4gIGxvYWRCYWxhbmNlcjogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIHwgQW55Q29tcHV0ZTtcbiAgcHJvdG9jb2xQb2xpY3k/OiBcIkhUVFBfT05MWVwiIHwgXCJIVFRQU19PTkxZXCIgfCBcIk1BVENIX1ZJRVdFUlwiO1xuICBjYWNoZVBvbGljeT86IENhY2hlUG9saWN5UHJlc2V0IHwgSUNhY2hlUG9saWN5O1xuICBkZWZhdWx0QWxsb3dlZE1ldGhvZHM/OiBcIkdFVF9IRUFEXCIgfCBcIkdFVF9IRUFEX09QVElPTlNcIiB8IFwiQUxMXCI7XG4gIGJlaGF2aW91cnM/OiBTbWFydENkbkJlaGF2aW91cltdO1xuICBkb21haW5OYW1lcz86IHN0cmluZ1tdO1xuICBjZXJ0aWZpY2F0ZT86IElDZXJ0aWZpY2F0ZTtcbiAgY29tbWVudD86IHN0cmluZztcbiAgZW5hYmxlTG9nZ2luZz86IGJvb2xlYW47XG4gIGxvZ0J1Y2tldD86IElCdWNrZXQ7XG4gIHByaWNlQ2xhc3M/OiBcIlByaWNlQ2xhc3NfMTAwXCIgfCBcIlByaWNlQ2xhc3NfMjAwXCIgfCBcIlByaWNlQ2xhc3NfQWxsXCI7XG4gIGZvcndhcmRIb3N0SGVhZGVyPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBIVFRQIG9yaWdpbiBDRE4gcHJvcHMgLSB1c2Ugd2l0aCBjdXN0b20gSFRUUCBlbmRwb2ludFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEh0dHBDZG5Qcm9wcyB7XG4gIG9yaWdpblR5cGU6IFwiaHR0cFwiO1xuICBkb21haW5OYW1lOiBzdHJpbmc7XG4gIG9yaWdpblBhdGg/OiBzdHJpbmc7XG4gIHByb3RvY29sUG9saWN5PzogXCJIVFRQX09OTFlcIiB8IFwiSFRUUFNfT05MWVwiIHwgXCJNQVRDSF9WSUVXRVJcIjtcbiAgY2FjaGVQb2xpY3k/OiBDYWNoZVBvbGljeVByZXNldCB8IElDYWNoZVBvbGljeTtcbiAgZGVmYXVsdEFsbG93ZWRNZXRob2RzPzogXCJHRVRfSEVBRFwiIHwgXCJHRVRfSEVBRF9PUFRJT05TXCIgfCBcIkFMTFwiO1xuICBiZWhhdmlvdXJzPzogU21hcnRDZG5CZWhhdmlvdXJbXTtcbiAgZG9tYWluTmFtZXM/OiBzdHJpbmdbXTtcbiAgY2VydGlmaWNhdGU/OiBJQ2VydGlmaWNhdGU7XG4gIGNvbW1lbnQ/OiBzdHJpbmc7XG4gIGVuYWJsZUxvZ2dpbmc/OiBib29sZWFuO1xuICBsb2dCdWNrZXQ/OiBJQnVja2V0O1xuICBwcmljZUNsYXNzPzogXCJQcmljZUNsYXNzXzEwMFwiIHwgXCJQcmljZUNsYXNzXzIwMFwiIHwgXCJQcmljZUNsYXNzX0FsbFwiO1xuICBmb3J3YXJkSG9zdEhlYWRlcj86IGJvb2xlYW47XG59XG5cbi8qKlxuICogU21hcnQgb3JpZ2luIENETiBwcm9wcyAtIGF1dG8tZGV0ZWN0IG9yaWdpbiB0eXBlIGZyb20gRmphbGwgcmVzb3VyY2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTbWFydENkblByb3BzIHtcbiAgb3JpZ2luVHlwZTogXCJhdXRvXCI7XG4gIG9yaWdpbjogU3RvcmFnZVJlc291cmNlIHwgQW55Q29tcHV0ZSB8IHN0cmluZztcbiAgY2FjaGVQb2xpY3k/OiBDYWNoZVBvbGljeVByZXNldCB8IElDYWNoZVBvbGljeTtcbiAgZGVmYXVsdEFsbG93ZWRNZXRob2RzPzogXCJHRVRfSEVBRFwiIHwgXCJHRVRfSEVBRF9PUFRJT05TXCIgfCBcIkFMTFwiO1xuICBiZWhhdmlvdXJzPzogU21hcnRDZG5CZWhhdmlvdXJbXTtcbiAgZG9tYWluTmFtZXM/OiBzdHJpbmdbXTtcbiAgY2VydGlmaWNhdGU/OiBJQ2VydGlmaWNhdGU7XG4gIGNvbW1lbnQ/OiBzdHJpbmc7XG4gIGVuYWJsZUxvZ2dpbmc/OiBib29sZWFuO1xuICBsb2dCdWNrZXQ/OiBJQnVja2V0O1xuICBwcmljZUNsYXNzPzogXCJQcmljZUNsYXNzXzEwMFwiIHwgXCJQcmljZUNsYXNzXzIwMFwiIHwgXCJQcmljZUNsYXNzX0FsbFwiO1xuICBmb3J3YXJkSG9zdEhlYWRlcj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCB0eXBlIElDZG5Qcm9wcyA9IFMzQ2RuUHJvcHMgfCBBbGJDZG5Qcm9wcyB8IEh0dHBDZG5Qcm9wcyB8IFNtYXJ0Q2RuUHJvcHM7XG5cbi8qKlxuICogU21hcnQgYmVoYXZpb3VyIHR5cGUgdGhhdCBhY2NlcHRzIEZqYWxsIHJlc291cmNlcyBhcyBvcmlnaW5zLlxuICogVGhlIGZhY3Rvcnkgd2lsbCB0cmFuc2Zvcm0gdGhlc2UgdG8gcHJvcGVyIENkbkJlaGF2aW91ciBvYmplY3RzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNtYXJ0Q2RuQmVoYXZpb3VyIHtcbiAgcGF0aFBhdHRlcm46IHN0cmluZztcbiAgb3JpZ2luOiBTdG9yYWdlUmVzb3VyY2UgfCBBbnlDb21wdXRlIHwgc3RyaW5nO1xuICBjYWNoZVBvbGljeT86IENhY2hlUG9saWN5UHJlc2V0IHwgSUNhY2hlUG9saWN5O1xuICBhbGxvd2VkTWV0aG9kcz86IFwiR0VUX0hFQURcIiB8IFwiR0VUX0hFQURfT1BUSU9OU1wiIHwgXCJBTExcIjtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgQ0ROIHByb3BzIGFuZCBsb2dzIHdhcm5pbmdzIGZvciBtaXNjb25maWd1cmVkIG9wdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlQ2RuUHJvcHMocHJvcHM6IElDZG5Qcm9wcyk6IHZvaWQge1xuICAvLyBWYWxpZGF0ZSBjZXJ0aWZpY2F0ZSByZWdpb24gd2FybmluZ1xuICBpZiAocHJvcHMuY2VydGlmaWNhdGUgJiYgcHJvcHMuZG9tYWluTmFtZXMgJiYgcHJvcHMuZG9tYWluTmFtZXMubGVuZ3RoID4gMCkge1xuICAgIEZqYWxsTG9nZ2VyLmluZm8oXG4gICAgICBcIkNsb3VkRnJvbnQgY2VydGlmaWNhdGVzIG11c3QgYmUgaW4gdXMtZWFzdC0xIHJlZ2lvbi4gXCIgK1xuICAgICAgICBcIkVuc3VyZSB5b3VyIGNlcnRpZmljYXRlIHdhcyBjcmVhdGVkIGluIHVzLWVhc3QtMS5cIlxuICAgICk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZSBkb21haW4gbmFtZXMgcmVxdWlyZSBjZXJ0aWZpY2F0ZVxuICBpZiAocHJvcHMuZG9tYWluTmFtZXMgJiYgcHJvcHMuZG9tYWluTmFtZXMubGVuZ3RoID4gMCAmJiAhcHJvcHMuY2VydGlmaWNhdGUpIHtcbiAgICBGamFsbExvZ2dlci53YXJuKFxuICAgICAgXCInZG9tYWluTmFtZXMnIHByb3ZpZGVkIGJ1dCBubyAnY2VydGlmaWNhdGUnIHNwZWNpZmllZC4gXCIgK1xuICAgICAgICBcIkN1c3RvbSBkb21haW4gbmFtZXMgcmVxdWlyZSBhbiBBQ00gY2VydGlmaWNhdGUgaW4gdXMtZWFzdC0xLlwiXG4gICAgKTtcbiAgfVxuXG4gIC8vIFZhbGlkYXRlIEFMQiBvcmlnaW5cbiAgaWYgKHByb3BzLm9yaWdpblR5cGUgPT09IFwiYWxiXCIpIHtcbiAgICBjb25zdCBhbGJQcm9wcyA9IHByb3BzIGFzIEFsYkNkblByb3BzO1xuICAgIGlmIChcbiAgICAgIGlzQ29tcHV0ZShhbGJQcm9wcy5sb2FkQmFsYW5jZXIpICYmXG4gICAgICBpc0Vjc0NvbXB1dGUoYWxiUHJvcHMubG9hZEJhbGFuY2VyKVxuICAgICkge1xuICAgICAgY29uc3QgbGIgPSBhbGJQcm9wcy5sb2FkQmFsYW5jZXIuZ2V0TG9hZEJhbGFuY2VyKCk7XG4gICAgICBpZiAoIWxiKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBcIkNvbXB1dGUgcmVzb3VyY2UgZG9lcyBub3QgaGF2ZSBhIGxvYWQgYmFsYW5jZXIuIFwiICtcbiAgICAgICAgICAgIFwiRW5zdXJlIEVDUyBjb21wdXRlIGhhcyBsb2FkQmFsYW5jZXIgZW5hYmxlZCBmb3IgQ0ROIG9yaWdpbi5cIlxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFZhbGlkYXRlIHNtYXJ0IG9yaWdpblxuICBpZiAocHJvcHMub3JpZ2luVHlwZSA9PT0gXCJhdXRvXCIpIHtcbiAgICBjb25zdCBzbWFydFByb3BzID0gcHJvcHMgYXMgU21hcnRDZG5Qcm9wcztcbiAgICBpZiAoaXNDb21wdXRlKHNtYXJ0UHJvcHMub3JpZ2luKSkge1xuICAgICAgaWYgKGlzRWNzQ29tcHV0ZShzbWFydFByb3BzLm9yaWdpbikpIHtcbiAgICAgICAgaWYgKCFzbWFydFByb3BzLm9yaWdpbi5nZXRMb2FkQmFsYW5jZXIoKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIFwiRUNTIGNvbXB1dGUgbXVzdCBoYXZlIGEgbG9hZCBiYWxhbmNlciBmb3IgQ0ROIG9yaWdpbi4gXCIgK1xuICAgICAgICAgICAgICBcIkVuYWJsZSBsb2FkQmFsYW5jZXIgaW4geW91ciBFQ1MgY29tcHV0ZSBjb25maWd1cmF0aW9uLlwiXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpc0xhbWJkYUNvbXB1dGUoc21hcnRQcm9wcy5vcmlnaW4pKSB7XG4gICAgICAgIGlmICghc21hcnRQcm9wcy5vcmlnaW4uZ2V0RnVuY3Rpb25VcmwoKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIFwiTGFtYmRhIGNvbXB1dGUgbXVzdCBoYXZlIGEgZnVuY3Rpb24gVVJMIGZvciBDRE4gb3JpZ2luLiBcIiArXG4gICAgICAgICAgICAgIFwiRW5hYmxlIGZ1bmN0aW9uVXJsIGluIHlvdXIgTGFtYmRhIGNvbXB1dGUgY29uZmlndXJhdGlvbi5cIlxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE11c3QgYmUgRUMyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBcIkVDMiBjb21wdXRlIHR5cGUgaXMgbm90IHN1cHBvcnRlZCBmb3IgQ0ROIG9yaWdpbi4gXCIgK1xuICAgICAgICAgICAgXCJVc2UgRUNTIHdpdGggbG9hZCBiYWxhbmNlciBvciBMYW1iZGEgd2l0aCBmdW5jdGlvbiBVUkwuXCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDRE4gd3JhcHBlciBjbGFzcyB0aGF0IGV4dGVuZHMgQ2xvdWRGcm9udERpc3RyaWJ1dGlvbiB3aXRoIEZqYWxsIHBhdHRlcm5zLlxuICovXG5leHBvcnQgY2xhc3MgQ2RuIGV4dGVuZHMgQ2xvdWRGcm9udERpc3RyaWJ1dGlvbiB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBJQ2RuUHJvcHMpIHtcbiAgICBjb25zdCByZXNvbHZlZFByb3BzID0gQ2RuLnJlc29sdmVQcm9wcyhwcm9wcyk7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCByZXNvbHZlZFByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIElDZG5Qcm9wcyB0byBDbG91ZEZyb250RGlzdHJpYnV0aW9uUHJvcHMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZXNvbHZlUHJvcHMocHJvcHM6IElDZG5Qcm9wcyk6IENsb3VkRnJvbnREaXN0cmlidXRpb25Qcm9wcyB7XG4gICAgY29uc3QgZGVmYXVsdE9yaWdpbiA9IENkbi5yZXNvbHZlRGVmYXVsdE9yaWdpbihwcm9wcyk7XG4gICAgY29uc3QgYmVoYXZpb3VycyA9IENkbi5yZXNvbHZlQmVoYXZpb3Vycyhwcm9wcy5iZWhhdmlvdXJzKTtcblxuICAgIHJldHVybiB7XG4gICAgICBkZWZhdWx0T3JpZ2luLFxuICAgICAgZGVmYXVsdENhY2hlUG9saWN5OiBwcm9wcy5jYWNoZVBvbGljeSxcbiAgICAgIGRlZmF1bHRBbGxvd2VkTWV0aG9kczogcHJvcHMuZGVmYXVsdEFsbG93ZWRNZXRob2RzLFxuICAgICAgYmVoYXZpb3VycyxcbiAgICAgIGRvbWFpbk5hbWVzOiBwcm9wcy5kb21haW5OYW1lcyxcbiAgICAgIGNlcnRpZmljYXRlOiBwcm9wcy5jZXJ0aWZpY2F0ZSxcbiAgICAgIGNvbW1lbnQ6IHByb3BzLmNvbW1lbnQsXG4gICAgICBlbmFibGVMb2dnaW5nOiBwcm9wcy5lbmFibGVMb2dnaW5nLFxuICAgICAgbG9nQnVja2V0OiBwcm9wcy5sb2dCdWNrZXQsXG4gICAgICBwcmljZUNsYXNzOiBwcm9wcy5wcmljZUNsYXNzLFxuICAgICAgZm9yd2FyZEhvc3RIZWFkZXI6IHByb3BzLmZvcndhcmRIb3N0SGVhZGVyXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2Zvcm0gc21hcnQgYmVoYXZpb3VycyB0byBDZG5CZWhhdmlvdXIgb2JqZWN0cy5cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlc29sdmVCZWhhdmlvdXJzKFxuICAgIGJlaGF2aW91cnM/OiBTbWFydENkbkJlaGF2aW91cltdXG4gICk6IENkbkJlaGF2aW91cltdIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWJlaGF2aW91cnMgfHwgYmVoYXZpb3Vycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJlaGF2aW91cnMubWFwKChiZWhhdmlvdXIpID0+ICh7XG4gICAgICBwYXRoUGF0dGVybjogYmVoYXZpb3VyLnBhdGhQYXR0ZXJuLFxuICAgICAgb3JpZ2luOiBDZG4uZGV0ZWN0T3JpZ2luRnJvbVJlc291cmNlKGJlaGF2aW91ci5vcmlnaW4pLFxuICAgICAgY2FjaGVQb2xpY3k6IGJlaGF2aW91ci5jYWNoZVBvbGljeSxcbiAgICAgIGFsbG93ZWRNZXRob2RzOiBiZWhhdmlvdXIuYWxsb3dlZE1ldGhvZHNcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGUgZGVmYXVsdCBvcmlnaW4gZnJvbSBJQ2RuUHJvcHMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZXNvbHZlRGVmYXVsdE9yaWdpbihwcm9wczogSUNkblByb3BzKTogQ2RuT3JpZ2luQ29uZmlnIHtcbiAgICBzd2l0Y2ggKHByb3BzLm9yaWdpblR5cGUpIHtcbiAgICAgIGNhc2UgXCJzM1wiOiB7XG4gICAgICAgIGNvbnN0IGJ1Y2tldCA9IGlzU3RvcmFnZVJlc291cmNlKHByb3BzLmJ1Y2tldClcbiAgICAgICAgICA/IHByb3BzLmJ1Y2tldC5nZXRCdWNrZXQoKVxuICAgICAgICAgIDogcHJvcHMuYnVja2V0O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiczNcIixcbiAgICAgICAgICBidWNrZXQsXG4gICAgICAgICAgb3JpZ2luUGF0aDogcHJvcHMub3JpZ2luUGF0aFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjYXNlIFwiYWxiXCI6IHtcbiAgICAgICAgbGV0IGxvYWRCYWxhbmNlcjogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyO1xuICAgICAgICBpZiAoaXNDb21wdXRlKHByb3BzLmxvYWRCYWxhbmNlcikpIHtcbiAgICAgICAgICBpZiAoaXNFY3NDb21wdXRlKHByb3BzLmxvYWRCYWxhbmNlcikpIHtcbiAgICAgICAgICAgIGNvbnN0IGxiID0gcHJvcHMubG9hZEJhbGFuY2VyLmdldExvYWRCYWxhbmNlcigpO1xuICAgICAgICAgICAgaWYgKCFsYikge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgXCJDb21wdXRlIHJlc291cmNlIGRvZXMgbm90IGhhdmUgYSBsb2FkIGJhbGFuY2VyLiBcIiArXG4gICAgICAgICAgICAgICAgICBcIkVuc3VyZSBFQ1MgY29tcHV0ZSBoYXMgbG9hZEJhbGFuY2VyIGVuYWJsZWQgZm9yIENETiBvcmlnaW4uXCJcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvYWRCYWxhbmNlciA9IGxiO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIFwiT25seSBFQ1MgY29tcHV0ZSB3aXRoIGxvYWQgYmFsYW5jZXIgaXMgc3VwcG9ydGVkIGZvciBBTEIgb3JpZ2luLiBcIiArXG4gICAgICAgICAgICAgICAgXCJMYW1iZGEgYW5kIEVDMiBjb21wdXRlIHR5cGVzIGFyZSBub3Qgc3VwcG9ydGVkLlwiXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2FkQmFsYW5jZXIgPSBwcm9wcy5sb2FkQmFsYW5jZXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiBcImFsYlwiLFxuICAgICAgICAgIGxvYWRCYWxhbmNlcixcbiAgICAgICAgICBwcm90b2NvbFBvbGljeTogcHJvcHMucHJvdG9jb2xQb2xpY3lcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY2FzZSBcImh0dHBcIjpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiBcImh0dHBcIixcbiAgICAgICAgICBkb21haW5OYW1lOiBwcm9wcy5kb21haW5OYW1lLFxuICAgICAgICAgIG9yaWdpblBhdGg6IHByb3BzLm9yaWdpblBhdGgsXG4gICAgICAgICAgcHJvdG9jb2xQb2xpY3k6IHByb3BzLnByb3RvY29sUG9saWN5XG4gICAgICAgIH07XG5cbiAgICAgIGNhc2UgXCJhdXRvXCI6XG4gICAgICAgIHJldHVybiBDZG4uZGV0ZWN0T3JpZ2luRnJvbVJlc291cmNlKHByb3BzLm9yaWdpbik7XG5cbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgY29uc3QgX2V4aGF1c3RpdmU6IG5ldmVyID0gcHJvcHM7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVW5zdXBwb3J0ZWQgQ0ROIG9yaWdpbiB0eXBlOiAkeyhwcm9wcyBhcyBJQ2RuUHJvcHMpLm9yaWdpblR5cGV9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBdXRvLWRldGVjdCBvcmlnaW4gY29uZmlndXJhdGlvbiBmcm9tIGEgRmphbGwgcmVzb3VyY2UuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBkZXRlY3RPcmlnaW5Gcm9tUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFN0b3JhZ2VSZXNvdXJjZSB8IEFueUNvbXB1dGUgfCBzdHJpbmdcbiAgKTogQ2RuT3JpZ2luQ29uZmlnIHtcbiAgICAvLyBTdHJpbmcg4oaSIEhUVFAgb3JpZ2luXG4gICAgaWYgKHR5cGVvZiByZXNvdXJjZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJodHRwXCIsXG4gICAgICAgIGRvbWFpbk5hbWU6IHJlc291cmNlXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIFN0b3JhZ2VSZXNvdXJjZSDihpIgUzMgb3JpZ2luXG4gICAgaWYgKGlzU3RvcmFnZVJlc291cmNlKHJlc291cmNlKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJzM1wiLFxuICAgICAgICBidWNrZXQ6IHJlc291cmNlLmdldEJ1Y2tldCgpXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEVDUyBDb21wdXRlIOKGkiBBTEIgb3JpZ2luXG4gICAgaWYgKGlzRWNzQ29tcHV0ZShyZXNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IGxvYWRCYWxhbmNlciA9IHJlc291cmNlLmdldExvYWRCYWxhbmNlcigpO1xuICAgICAgaWYgKGxvYWRCYWxhbmNlcikge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiYWxiXCIsXG4gICAgICAgICAgbG9hZEJhbGFuY2VyXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTGFtYmRhIENvbXB1dGUg4oaSIEhUVFAgb3JpZ2luIChmdW5jdGlvbiBVUkwpXG4gICAgaWYgKGlzTGFtYmRhQ29tcHV0ZShyZXNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IGZ1bmN0aW9uVXJsID0gcmVzb3VyY2UuZ2V0RnVuY3Rpb25VcmwoKTtcbiAgICAgIGlmIChmdW5jdGlvblVybCkge1xuICAgICAgICAvLyBMYW1iZGEgZnVuY3Rpb24gVVJMIGlzIGFuIEhUVFAgb3JpZ2luXG4gICAgICAgIC8vIEV4dHJhY3QgZG9tYWluIGZyb20gVVJMIHRva2VuIHVzaW5nIENsb3VkRm9ybWF0aW9uIGludHJpbnNpY3NcbiAgICAgICAgLy8gVVJMIGZvcm1hdDogaHR0cHM6Ly88ZG9tYWluPi9cbiAgICAgICAgLy8gU3BsaXQgYnkgXCIvXCIgZ2l2ZXMgW1wiaHR0cHM6XCIsIFwiXCIsIFwiPGRvbWFpbj5cIiwgXCJcIl1cbiAgICAgICAgLy8gU2VsZWN0IGluZGV4IDIgdG8gZ2V0IHRoZSBkb21haW5cbiAgICAgICAgY29uc3QgZG9tYWluTmFtZSA9IEZuLnNlbGVjdCgyLCBGbi5zcGxpdChcIi9cIiwgZnVuY3Rpb25VcmwpKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiBcImh0dHBcIixcbiAgICAgICAgICBkb21haW5OYW1lXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFVuYWJsZSB0byBkZXRlY3QgQ0ROIG9yaWdpbiBmcm9tIHJlc291cmNlOiAke3R5cGVvZiByZXNvdXJjZX0uIGAgK1xuICAgICAgICBcIlByb3ZpZGUgZXhwbGljaXQgb3JpZ2luIGNvbmZpZ3VyYXRpb24gdXNpbmcgb3JpZ2luVHlwZS5cIlxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBGYWN0b3J5IGZvciBjcmVhdGluZyBDRE4gKENsb3VkRnJvbnQpIGRpc3RyaWJ1dGlvbnMuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFMzIG9yaWdpblxuICogY29uc3QgYXNzZXRzID0gYXBwLmFkZFN0b3JhZ2UoU3RvcmFnZUZhY3RvcnkuYnVpbGQoXCJBc3NldHNcIiwgeyBidWNrZXRUeXBlOiBcInByaXZhdGVcIiB9KSk7XG4gKiBhcHAuYWRkQ2RuKENkbkZhY3RvcnkuYnVpbGQoXCJBc3NldHNDZG5cIiwge1xuICogICBvcmlnaW5UeXBlOiBcInMzXCIsXG4gKiAgIGJ1Y2tldDogYXNzZXRzXG4gKiB9KSk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEFMQiBvcmlnaW4gKEVDUylcbiAqIGNvbnN0IGFwaSA9IGFwcC5hZGRDb21wdXRlKENvbXB1dGVGYWN0b3J5LmJ1aWxkKFwiQXBpXCIsIHsgdHlwZTogXCJlY3NcIiwgLi4uIH0pKTtcbiAqIGFwcC5hZGRDZG4oQ2RuRmFjdG9yeS5idWlsZChcIkFwaUNkblwiLCB7XG4gKiAgIG9yaWdpblR5cGU6IFwiYWxiXCIsXG4gKiAgIGxvYWRCYWxhbmNlcjogYXBpXG4gKiB9KSk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNtYXJ0IGRldGVjdGlvblxuICogYXBwLmFkZENkbihDZG5GYWN0b3J5LmJ1aWxkKFwiQXBwQ2RuXCIsIHtcbiAqICAgb3JpZ2luVHlwZTogXCJhdXRvXCIsXG4gKiAgIG9yaWdpbjogYXNzZXRzXG4gKiB9KSk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEN1c3RvbSBkb21haW5cbiAqIGFwcC5hZGRDZG4oQ2RuRmFjdG9yeS5idWlsZChcIkFwcENkblwiLCB7XG4gKiAgIG9yaWdpblR5cGU6IFwiczNcIixcbiAqICAgYnVja2V0OiBhc3NldHMsXG4gKiAgIGRvbWFpbk5hbWVzOiBbXCJhcHAuZXhhbXBsZS5jb21cIl0sXG4gKiAgIGNlcnRpZmljYXRlOiBteUNlcnRcbiAqIH0pKTtcbiAqL1xuZXhwb3J0IGNsYXNzIENkbkZhY3Rvcnkge1xuICAvKipcbiAgICogQnVpbGQgYSBDRE4gZmFjdG9yeSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGlkIC0gVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBDRE5cbiAgICogQHBhcmFtIHByb3BzIC0gQ0ROIGNvbmZpZ3VyYXRpb24gcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBGYWN0b3J5IGZ1bmN0aW9uIHRoYXQgY3JlYXRlcyB0aGUgQ0ROIHdoZW4gaW52b2tlZFxuICAgKi9cbiAgc3RhdGljIGJ1aWxkKGlkOiBzdHJpbmcsIHByb3BzOiBJQ2RuUHJvcHMpIHtcbiAgICByZXR1cm4gKF9hcHA6IEFwcCwgc2NvcGU6IENvbnN0cnVjdCk6IENkbiA9PiB7XG4gICAgICB2YWxpZGF0ZUNkblByb3BzKHByb3BzKTtcbiAgICAgIHJldHVybiBuZXcgQ2RuKHNjb3BlLCBpZCwgcHJvcHMpO1xuICAgIH07XG4gIH1cbn1cbiJdfQ==
|