@fjall/components-infrastructure 0.86.1 → 0.87.4
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 +6 -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,526 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Payload CMS Pattern.
|
|
4
|
+
*
|
|
5
|
+
* A high-level pattern that creates all infrastructure required for a
|
|
6
|
+
* Payload CMS deployment using OpenNext.
|
|
7
|
+
*
|
|
8
|
+
* Resources created:
|
|
9
|
+
* - RDS PostgreSQL database (Aurora or Instance)
|
|
10
|
+
* - 3 S3 buckets (assets, cache, media)
|
|
11
|
+
* - DynamoDB table (tag cache with GSI)
|
|
12
|
+
* - SQS FIFO queue (revalidation)
|
|
13
|
+
* - 3 Lambda functions (server, image optimisation, revalidation)
|
|
14
|
+
* - CloudFront distribution
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const payload = app.addPattern(PatternFactory.build("PayloadApp", {
|
|
18
|
+
* type: "payload",
|
|
19
|
+
* name: "my-cms"
|
|
20
|
+
* }));
|
|
21
|
+
*
|
|
22
|
+
* // Escape hatches
|
|
23
|
+
* payload.getDatabase().grantConnect(otherLambda);
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Payload = void 0;
|
|
27
|
+
const constructs_1 = require("constructs");
|
|
28
|
+
const crypto_1 = require("crypto");
|
|
29
|
+
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
30
|
+
const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
|
|
31
|
+
const aws_route53_1 = require("aws-cdk-lib/aws-route53");
|
|
32
|
+
const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
|
|
33
|
+
const database_js_1 = require("./database.js");
|
|
34
|
+
const compute_js_1 = require("./compute.js");
|
|
35
|
+
const storage_js_1 = require("./storage.js");
|
|
36
|
+
const messaging_js_1 = require("./messaging.js");
|
|
37
|
+
const cdn_js_1 = require("./cdn.js");
|
|
38
|
+
const validationLogger_js_1 = require("../../utils/validationLogger.js");
|
|
39
|
+
const PAYLOAD_DEFAULTS = {
|
|
40
|
+
/** Path to OpenNext output relative to app folder (CDK runs from fjall/<appname>) */
|
|
41
|
+
SOURCE: "../..",
|
|
42
|
+
DATABASE: {
|
|
43
|
+
TYPE: "Instance",
|
|
44
|
+
BACKUP_RETENTION: 7,
|
|
45
|
+
DELETION_PROTECTION: true
|
|
46
|
+
},
|
|
47
|
+
COMPUTE: {
|
|
48
|
+
SERVER_MEMORY: 1536,
|
|
49
|
+
SERVER_TIMEOUT: 30,
|
|
50
|
+
IMAGE_MEMORY: 1536,
|
|
51
|
+
IMAGE_TIMEOUT: 30,
|
|
52
|
+
REVALIDATION_MEMORY: 768,
|
|
53
|
+
REVALIDATION_TIMEOUT: 300
|
|
54
|
+
},
|
|
55
|
+
CACHE: {
|
|
56
|
+
MAX_AGE_SECONDS: 31536000 // 1 year
|
|
57
|
+
},
|
|
58
|
+
PATHS: {
|
|
59
|
+
STATIC: "/_next/static/*",
|
|
60
|
+
IMAGE: "/_next/image*",
|
|
61
|
+
API: "/api/*",
|
|
62
|
+
ADMIN: "/admin/*"
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Convert a name to a valid database name (snake_case, alphanumeric only).
|
|
67
|
+
*/
|
|
68
|
+
function toValidDatabaseName(name) {
|
|
69
|
+
return name
|
|
70
|
+
.toLowerCase()
|
|
71
|
+
.replace(/-/g, "_")
|
|
72
|
+
.replace(/[^a-z0-9_]/g, "");
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Convert a name to PascalCase for construct IDs.
|
|
76
|
+
*/
|
|
77
|
+
function toPascalCase(name) {
|
|
78
|
+
return name
|
|
79
|
+
.replace(/[-_](.)/g, (_, c) => c.toUpperCase())
|
|
80
|
+
.replace(/^./, (c) => c.toUpperCase());
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Extract root domain from a full domain name.
|
|
84
|
+
* e.g., "cms.example.com" -> "example.com"
|
|
85
|
+
*/
|
|
86
|
+
function extractRootDomain(domain) {
|
|
87
|
+
const parts = domain.split(".");
|
|
88
|
+
return parts.length > 2 ? parts.slice(-2).join(".") : domain;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Safely get the underlying Lambda function from a compute resource.
|
|
92
|
+
* Throws a clear error if the function is not available.
|
|
93
|
+
*/
|
|
94
|
+
function requireFunction(compute, name) {
|
|
95
|
+
const fn = compute.getFunction();
|
|
96
|
+
if (!fn) {
|
|
97
|
+
throw new Error(`${name} Lambda function is not available. ` +
|
|
98
|
+
"This indicates an internal error in compute resource creation.");
|
|
99
|
+
}
|
|
100
|
+
return fn;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Extract Lambda config from props with defaults.
|
|
104
|
+
*/
|
|
105
|
+
function resolveLambdaConfig(config, defaults) {
|
|
106
|
+
return {
|
|
107
|
+
memorySize: config?.memorySize ?? defaults.memory,
|
|
108
|
+
timeout: config?.timeout ?? defaults.timeout,
|
|
109
|
+
ephemeralStorageSize: config?.ephemeralStorageSize
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Payload CMS pattern implementation.
|
|
114
|
+
*
|
|
115
|
+
* Composes all required AWS resources for a Payload deployment.
|
|
116
|
+
*/
|
|
117
|
+
class Payload extends constructs_1.Construct {
|
|
118
|
+
constructor(scope, id, app, props) {
|
|
119
|
+
super(scope, id);
|
|
120
|
+
this.patternType = "payload";
|
|
121
|
+
this.app = app;
|
|
122
|
+
this.props = props;
|
|
123
|
+
this.pascalName = toPascalCase(props.name);
|
|
124
|
+
this.payloadSecret = (0, crypto_1.randomBytes)(32).toString("hex");
|
|
125
|
+
this.registerManifest();
|
|
126
|
+
this.validateProps();
|
|
127
|
+
this.createDatabase();
|
|
128
|
+
this.createStorageBuckets();
|
|
129
|
+
this.createTagCache();
|
|
130
|
+
this.createRevalidationQueue();
|
|
131
|
+
this.createLambdaFunctions();
|
|
132
|
+
this.createCdn();
|
|
133
|
+
this.createDnsRecord();
|
|
134
|
+
}
|
|
135
|
+
registerManifest() {
|
|
136
|
+
const manifestPattern = {
|
|
137
|
+
type: "payload",
|
|
138
|
+
name: this.props.name,
|
|
139
|
+
source: PAYLOAD_DEFAULTS.SOURCE
|
|
140
|
+
};
|
|
141
|
+
this.app.getManifestCollector().setPattern(manifestPattern);
|
|
142
|
+
}
|
|
143
|
+
validateProps() {
|
|
144
|
+
const dbConfig = this.props.database ?? {};
|
|
145
|
+
if (dbConfig.publiclyAccessible) {
|
|
146
|
+
validationLogger_js_1.FjallLogger.warn(`Payload database '${this.props.name}' is configured with public accessibility. ` +
|
|
147
|
+
"This is a security risk and should only be used for development.");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
createDatabase() {
|
|
151
|
+
const dbConfig = this.props.database ?? {};
|
|
152
|
+
const databaseType = dbConfig.type ?? PAYLOAD_DEFAULTS.DATABASE.TYPE;
|
|
153
|
+
this._database =
|
|
154
|
+
databaseType === "Aurora"
|
|
155
|
+
? this.createAuroraDatabase(dbConfig)
|
|
156
|
+
: this.createInstanceDatabase(dbConfig);
|
|
157
|
+
}
|
|
158
|
+
buildBaseDatabaseProps(dbConfig) {
|
|
159
|
+
return {
|
|
160
|
+
databaseName: dbConfig.databaseName ?? toValidDatabaseName(this.props.name),
|
|
161
|
+
databaseEngine: dbConfig.databaseEngine ?? "postgresql",
|
|
162
|
+
backupRetention: dbConfig.backupRetention ?? PAYLOAD_DEFAULTS.DATABASE.BACKUP_RETENTION,
|
|
163
|
+
deletionProtection: dbConfig.deletionProtection ??
|
|
164
|
+
PAYLOAD_DEFAULTS.DATABASE.DELETION_PROTECTION,
|
|
165
|
+
publiclyAccessible: dbConfig.publiclyAccessible,
|
|
166
|
+
port: dbConfig.port,
|
|
167
|
+
performanceInsights: dbConfig.performanceInsights,
|
|
168
|
+
proxy: dbConfig.proxy,
|
|
169
|
+
credentials: dbConfig.credentials,
|
|
170
|
+
snapshotIdentifier: dbConfig.snapshotIdentifier,
|
|
171
|
+
snapshotUsername: dbConfig.snapshotUsername
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
createAuroraDatabase(dbConfig) {
|
|
175
|
+
const auroraProps = {
|
|
176
|
+
type: "Aurora",
|
|
177
|
+
...this.buildBaseDatabaseProps(dbConfig),
|
|
178
|
+
allowedIpCidr: dbConfig.allowedIpCidr,
|
|
179
|
+
encryption: dbConfig.encryption,
|
|
180
|
+
writer: dbConfig.writer,
|
|
181
|
+
readers: dbConfig.readers,
|
|
182
|
+
allowVpcAccess: dbConfig.allowVpcAccess,
|
|
183
|
+
monitoringInterval: dbConfig.monitoringInterval,
|
|
184
|
+
preferredMaintenanceWindow: dbConfig.preferredMaintenanceWindow
|
|
185
|
+
};
|
|
186
|
+
return this.app.addDatabase(database_js_1.DatabaseFactory.build(`${this.pascalName}Database`, auroraProps));
|
|
187
|
+
}
|
|
188
|
+
createInstanceDatabase(dbConfig) {
|
|
189
|
+
const instanceProps = {
|
|
190
|
+
type: "Instance",
|
|
191
|
+
...this.buildBaseDatabaseProps(dbConfig),
|
|
192
|
+
publiclyAccessible: dbConfig.publiclyAccessible ?? false,
|
|
193
|
+
instanceType: dbConfig.instanceType,
|
|
194
|
+
allocatedStorage: dbConfig.allocatedStorage,
|
|
195
|
+
multiAz: dbConfig.multiAz,
|
|
196
|
+
readReplica: dbConfig.readReplica,
|
|
197
|
+
encryption: dbConfig.encryption
|
|
198
|
+
};
|
|
199
|
+
return this.app.addDatabase(database_js_1.DatabaseFactory.build(`${this.pascalName}Database`, instanceProps));
|
|
200
|
+
}
|
|
201
|
+
createStorageBuckets() {
|
|
202
|
+
this._assetsBucket = this.createAssetsBucket();
|
|
203
|
+
this._cacheBucket = this.createCacheBucket();
|
|
204
|
+
this._mediaBucket = this.createMediaBucket();
|
|
205
|
+
}
|
|
206
|
+
createAssetsBucket() {
|
|
207
|
+
const assetsConfig = this.props.storage?.assets ?? {};
|
|
208
|
+
const assetsProps = {
|
|
209
|
+
bucketType: "private",
|
|
210
|
+
versioned: assetsConfig.versioned ?? false,
|
|
211
|
+
deployment: {
|
|
212
|
+
source: `${PAYLOAD_DEFAULTS.SOURCE}/.open-next/assets`,
|
|
213
|
+
prune: true,
|
|
214
|
+
cacheControl: {
|
|
215
|
+
maxAge: PAYLOAD_DEFAULTS.CACHE.MAX_AGE_SECONDS,
|
|
216
|
+
immutable: true
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
return this.app.addStorage(storage_js_1.StorageFactory.build(`${this.pascalName}Assets`, assetsProps));
|
|
221
|
+
}
|
|
222
|
+
createCacheBucket() {
|
|
223
|
+
const cacheConfig = this.props.storage?.cache ?? {};
|
|
224
|
+
const cacheProps = {
|
|
225
|
+
bucketType: "private",
|
|
226
|
+
versioned: cacheConfig.versioned ?? false,
|
|
227
|
+
deployment: {
|
|
228
|
+
source: `${PAYLOAD_DEFAULTS.SOURCE}/.open-next/cache`,
|
|
229
|
+
prune: false // ISR adds files at runtime
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
return this.app.addStorage(storage_js_1.StorageFactory.build(`${this.pascalName}Cache`, cacheProps));
|
|
233
|
+
}
|
|
234
|
+
createMediaBucket() {
|
|
235
|
+
const mediaConfig = this.props.storage?.media ?? {};
|
|
236
|
+
const mediaProps = {
|
|
237
|
+
bucketType: "private",
|
|
238
|
+
versioned: mediaConfig.versioned ?? false
|
|
239
|
+
};
|
|
240
|
+
return this.app.addStorage(storage_js_1.StorageFactory.build(`${this.pascalName}Media`, mediaProps));
|
|
241
|
+
}
|
|
242
|
+
createTagCache() {
|
|
243
|
+
const tagCacheProps = {
|
|
244
|
+
type: "DynamoDB",
|
|
245
|
+
partitionKey: { name: "tag", type: "S" },
|
|
246
|
+
sortKey: { name: "path", type: "S" },
|
|
247
|
+
globalSecondaryIndexes: [
|
|
248
|
+
{
|
|
249
|
+
indexName: "revalidate",
|
|
250
|
+
partitionKey: { name: "path", type: "S" },
|
|
251
|
+
sortKey: { name: "revalidatedAt", type: "N" }
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
};
|
|
255
|
+
this._tagCache = this.app.addDatabase(database_js_1.DatabaseFactory.build(`${this.pascalName}TagCache`, tagCacheProps));
|
|
256
|
+
}
|
|
257
|
+
createRevalidationQueue() {
|
|
258
|
+
const queueConfig = this.props.messaging?.revalidationQueue ?? {};
|
|
259
|
+
const revalidationTimeout = this.props.compute?.revalidation?.timeout ??
|
|
260
|
+
PAYLOAD_DEFAULTS.COMPUTE.REVALIDATION_TIMEOUT;
|
|
261
|
+
// Resolve dead letter queue config
|
|
262
|
+
let dlqConfig;
|
|
263
|
+
if (queueConfig.deadLetterQueue === false) {
|
|
264
|
+
dlqConfig = undefined;
|
|
265
|
+
}
|
|
266
|
+
else if (queueConfig.deadLetterQueue) {
|
|
267
|
+
dlqConfig = {
|
|
268
|
+
enabled: queueConfig.deadLetterQueue.enabled ?? true,
|
|
269
|
+
maxReceiveCount: queueConfig.deadLetterQueue.maxReceiveCount ?? 3
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
dlqConfig = { enabled: true, maxReceiveCount: 3 };
|
|
274
|
+
}
|
|
275
|
+
const queueProps = {
|
|
276
|
+
type: "queue",
|
|
277
|
+
queueType: "fifo",
|
|
278
|
+
visibilityTimeout: queueConfig.visibilityTimeout ?? revalidationTimeout,
|
|
279
|
+
messageRetentionPeriod: queueConfig.messageRetentionPeriod,
|
|
280
|
+
maxMessageSize: queueConfig.maxMessageSize,
|
|
281
|
+
contentBasedDeduplication: true,
|
|
282
|
+
deadLetterQueue: dlqConfig
|
|
283
|
+
};
|
|
284
|
+
this._revalidationQueue = this.app.addMessaging(messaging_js_1.MessagingFactory.build(`${this.pascalName}Revalidation`, queueProps));
|
|
285
|
+
}
|
|
286
|
+
createLambdaFunctions() {
|
|
287
|
+
this._server = this.createServerLambda();
|
|
288
|
+
this._imageOptimisation = this.createImageLambda();
|
|
289
|
+
this._revalidation = this.createRevalidationLambda();
|
|
290
|
+
}
|
|
291
|
+
createServerLambda() {
|
|
292
|
+
const { memorySize, timeout, ephemeralStorageSize } = resolveLambdaConfig(this.props.compute?.server, {
|
|
293
|
+
memory: PAYLOAD_DEFAULTS.COMPUTE.SERVER_MEMORY,
|
|
294
|
+
timeout: PAYLOAD_DEFAULTS.COMPUTE.SERVER_TIMEOUT
|
|
295
|
+
});
|
|
296
|
+
const serverProps = {
|
|
297
|
+
type: "lambda",
|
|
298
|
+
deployment: "code",
|
|
299
|
+
code: aws_lambda_1.Code.fromAsset(`${PAYLOAD_DEFAULTS.SOURCE}/.open-next/server-functions/default`),
|
|
300
|
+
handler: "index.handler",
|
|
301
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
302
|
+
architecture: aws_lambda_1.Architecture.ARM_64,
|
|
303
|
+
memorySize,
|
|
304
|
+
timeout,
|
|
305
|
+
ephemeralStorageSize,
|
|
306
|
+
functionUrl: {
|
|
307
|
+
authType: aws_lambda_1.FunctionUrlAuthType.NONE,
|
|
308
|
+
invokeMode: compute_js_1.InvokeMode.RESPONSE_STREAM
|
|
309
|
+
},
|
|
310
|
+
connections: [this._database],
|
|
311
|
+
secretsImport: {
|
|
312
|
+
DATABASE_USERNAME: this._database
|
|
313
|
+
.getCredentials()
|
|
314
|
+
.getImport("username"),
|
|
315
|
+
DATABASE_PASSWORD: this._database.getCredentials().getImport("password")
|
|
316
|
+
},
|
|
317
|
+
environment: this.buildServerEnvironment()
|
|
318
|
+
};
|
|
319
|
+
const server = this.app.addCompute(compute_js_1.ComputeFactory.build(`${this.pascalName}Server`, serverProps));
|
|
320
|
+
this.grantServerPermissions(server);
|
|
321
|
+
return server;
|
|
322
|
+
}
|
|
323
|
+
buildServerEnvironment() {
|
|
324
|
+
const baseEnv = {
|
|
325
|
+
DATABASE_HOST: this._database.getHostEndpoint(),
|
|
326
|
+
DATABASE_PORT: this._database.getHostPort(),
|
|
327
|
+
DATABASE_NAME: this._database.getDatabaseName(),
|
|
328
|
+
DATABASE_SSL: "true",
|
|
329
|
+
CACHE_BUCKET_NAME: this._cacheBucket.getBucketName(),
|
|
330
|
+
CACHE_BUCKET_REGION: this.app.region ?? "us-east-1",
|
|
331
|
+
CACHE_DYNAMO_TABLE: this._tagCache.getTableName(),
|
|
332
|
+
REVALIDATION_QUEUE_URL: this._revalidationQueue.getQueueUrl(),
|
|
333
|
+
REVALIDATION_QUEUE_REGION: this.app.region ?? "us-east-1",
|
|
334
|
+
MEDIA_BUCKET_NAME: this._mediaBucket.getBucketName(),
|
|
335
|
+
PAYLOAD_SECRET: this.payloadSecret
|
|
336
|
+
};
|
|
337
|
+
// Lock down CORS to custom domain when provided
|
|
338
|
+
const customDomain = this.props.cdn?.domainNames?.[0];
|
|
339
|
+
if (customDomain) {
|
|
340
|
+
baseEnv.NEXT_PUBLIC_SERVER_URL = `https://${customDomain}`;
|
|
341
|
+
}
|
|
342
|
+
return { ...baseEnv, ...this.props.environment };
|
|
343
|
+
}
|
|
344
|
+
grantServerPermissions(server) {
|
|
345
|
+
const serverFunction = requireFunction(server, "Server");
|
|
346
|
+
this._cacheBucket.grantReadWrite(serverFunction);
|
|
347
|
+
this._mediaBucket.grantReadWrite(serverFunction);
|
|
348
|
+
this._tagCache.grantReadWriteData(serverFunction);
|
|
349
|
+
this._revalidationQueue.grantSendMessages(serverFunction);
|
|
350
|
+
}
|
|
351
|
+
createImageLambda() {
|
|
352
|
+
const { memorySize, timeout, ephemeralStorageSize } = resolveLambdaConfig(this.props.compute?.imageOptimisation, {
|
|
353
|
+
memory: PAYLOAD_DEFAULTS.COMPUTE.IMAGE_MEMORY,
|
|
354
|
+
timeout: PAYLOAD_DEFAULTS.COMPUTE.IMAGE_TIMEOUT
|
|
355
|
+
});
|
|
356
|
+
const imageProps = {
|
|
357
|
+
type: "lambda",
|
|
358
|
+
deployment: "code",
|
|
359
|
+
code: aws_lambda_1.Code.fromAsset(`${PAYLOAD_DEFAULTS.SOURCE}/.open-next/image-optimization-function`),
|
|
360
|
+
handler: "index.handler",
|
|
361
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
362
|
+
architecture: aws_lambda_1.Architecture.ARM_64,
|
|
363
|
+
memorySize,
|
|
364
|
+
timeout,
|
|
365
|
+
ephemeralStorageSize,
|
|
366
|
+
functionUrl: { authType: aws_lambda_1.FunctionUrlAuthType.NONE },
|
|
367
|
+
environment: {
|
|
368
|
+
BUCKET_NAME: this._assetsBucket.getBucketName(),
|
|
369
|
+
BUCKET_KEY_PREFIX: "_assets"
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const image = this.app.addCompute(compute_js_1.ComputeFactory.build(`${this.pascalName}ImageOptimisation`, imageProps));
|
|
373
|
+
const imageFunction = requireFunction(image, "ImageOptimisation");
|
|
374
|
+
this._assetsBucket.grantRead(imageFunction);
|
|
375
|
+
return image;
|
|
376
|
+
}
|
|
377
|
+
createRevalidationLambda() {
|
|
378
|
+
const { memorySize, timeout, ephemeralStorageSize } = resolveLambdaConfig(this.props.compute?.revalidation, {
|
|
379
|
+
memory: PAYLOAD_DEFAULTS.COMPUTE.REVALIDATION_MEMORY,
|
|
380
|
+
timeout: PAYLOAD_DEFAULTS.COMPUTE.REVALIDATION_TIMEOUT
|
|
381
|
+
});
|
|
382
|
+
const revalidationProps = {
|
|
383
|
+
type: "lambda",
|
|
384
|
+
deployment: "code",
|
|
385
|
+
code: aws_lambda_1.Code.fromAsset(`${PAYLOAD_DEFAULTS.SOURCE}/.open-next/revalidation-function`),
|
|
386
|
+
handler: "index.handler",
|
|
387
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
388
|
+
architecture: aws_lambda_1.Architecture.ARM_64,
|
|
389
|
+
memorySize,
|
|
390
|
+
timeout,
|
|
391
|
+
ephemeralStorageSize,
|
|
392
|
+
environment: {
|
|
393
|
+
CACHE_DYNAMO_TABLE: this._tagCache.getTableName(),
|
|
394
|
+
CACHE_BUCKET_NAME: this._cacheBucket.getBucketName()
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
const revalidation = this.app.addCompute(compute_js_1.ComputeFactory.build(`${this.pascalName}Revalidation`, revalidationProps));
|
|
398
|
+
const revalidationLambda = revalidation.getLambdaFunction();
|
|
399
|
+
revalidationLambda.addSqsEventSource(this._revalidationQueue.getQueue(), {
|
|
400
|
+
batchSize: 5
|
|
401
|
+
});
|
|
402
|
+
const revalidationFunction = requireFunction(revalidation, "Revalidation");
|
|
403
|
+
this._tagCache.grantReadWriteData(revalidationFunction);
|
|
404
|
+
this._cacheBucket.grantReadWrite(revalidationFunction);
|
|
405
|
+
this._revalidationQueue.grantConsumeMessages(revalidationFunction);
|
|
406
|
+
return revalidation;
|
|
407
|
+
}
|
|
408
|
+
createCdn() {
|
|
409
|
+
const { domainNames, certificate } = this.resolveDomainConfig();
|
|
410
|
+
const cdnProps = {
|
|
411
|
+
originType: "auto",
|
|
412
|
+
origin: this._server,
|
|
413
|
+
cachePolicy: "CACHING_DISABLED",
|
|
414
|
+
defaultAllowedMethods: "ALL",
|
|
415
|
+
forwardHostHeader: true,
|
|
416
|
+
priceClass: "PriceClass_100",
|
|
417
|
+
domainNames,
|
|
418
|
+
certificate,
|
|
419
|
+
behaviours: [
|
|
420
|
+
{
|
|
421
|
+
pathPattern: PAYLOAD_DEFAULTS.PATHS.STATIC,
|
|
422
|
+
origin: this._assetsBucket,
|
|
423
|
+
cachePolicy: "CACHING_OPTIMIZED"
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
pathPattern: PAYLOAD_DEFAULTS.PATHS.IMAGE,
|
|
427
|
+
origin: this._imageOptimisation,
|
|
428
|
+
cachePolicy: "CACHING_OPTIMIZED"
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
pathPattern: PAYLOAD_DEFAULTS.PATHS.API,
|
|
432
|
+
origin: this._server,
|
|
433
|
+
cachePolicy: "CACHING_DISABLED",
|
|
434
|
+
allowedMethods: "ALL"
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
pathPattern: PAYLOAD_DEFAULTS.PATHS.ADMIN,
|
|
438
|
+
origin: this._server,
|
|
439
|
+
cachePolicy: "CACHING_DISABLED",
|
|
440
|
+
allowedMethods: "ALL"
|
|
441
|
+
},
|
|
442
|
+
...(this.props.cdn?.behaviours ?? [])
|
|
443
|
+
]
|
|
444
|
+
};
|
|
445
|
+
this._cdn = this.app.addCdn(cdn_js_1.CdnFactory.build(`${this.pascalName}Cdn`, cdnProps));
|
|
446
|
+
}
|
|
447
|
+
resolveDomainConfig() {
|
|
448
|
+
if (this.props.domain) {
|
|
449
|
+
return this.resolveSimpleDomain();
|
|
450
|
+
}
|
|
451
|
+
if (this.props.cdn?.domainNames?.length) {
|
|
452
|
+
return this.resolveAdvancedDomain();
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
domainNames: undefined,
|
|
456
|
+
certificate: undefined,
|
|
457
|
+
hostedZone: undefined
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
resolveSimpleDomain() {
|
|
461
|
+
const domain = this.props.domain;
|
|
462
|
+
const rootDomain = extractRootDomain(domain);
|
|
463
|
+
const hostedZone = aws_route53_1.HostedZone.fromLookup(this, `${this.pascalName}HostedZone`, { domainName: rootDomain });
|
|
464
|
+
const certificate = new aws_certificatemanager_1.Certificate(this, `${this.pascalName}Certificate`, {
|
|
465
|
+
domainName: domain,
|
|
466
|
+
validation: aws_certificatemanager_1.CertificateValidation.fromDns(hostedZone)
|
|
467
|
+
});
|
|
468
|
+
return { domainNames: [domain], certificate, hostedZone };
|
|
469
|
+
}
|
|
470
|
+
resolveAdvancedDomain() {
|
|
471
|
+
const cdnConfig = this.props.cdn;
|
|
472
|
+
const certificate = cdnConfig.certificate ??
|
|
473
|
+
(cdnConfig.certificateArn
|
|
474
|
+
? aws_certificatemanager_1.Certificate.fromCertificateArn(this, `${this.pascalName}Certificate`, cdnConfig.certificateArn)
|
|
475
|
+
: undefined);
|
|
476
|
+
return {
|
|
477
|
+
domainNames: cdnConfig.domainNames,
|
|
478
|
+
certificate,
|
|
479
|
+
hostedZone: undefined
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
createDnsRecord() {
|
|
483
|
+
if (!this.props.domain)
|
|
484
|
+
return;
|
|
485
|
+
const { hostedZone } = this.resolveDomainConfig();
|
|
486
|
+
if (!hostedZone)
|
|
487
|
+
return;
|
|
488
|
+
new aws_route53_1.ARecord(this, `${this.pascalName}AliasRecord`, {
|
|
489
|
+
zone: hostedZone,
|
|
490
|
+
recordName: this.props.domain,
|
|
491
|
+
target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.CloudFrontTarget(this._cdn.getDistribution()))
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
getDatabase() {
|
|
495
|
+
return this._database;
|
|
496
|
+
}
|
|
497
|
+
getServer() {
|
|
498
|
+
return this._server;
|
|
499
|
+
}
|
|
500
|
+
getImageOptimisation() {
|
|
501
|
+
return this._imageOptimisation;
|
|
502
|
+
}
|
|
503
|
+
getRevalidation() {
|
|
504
|
+
return this._revalidation;
|
|
505
|
+
}
|
|
506
|
+
getAssetsBucket() {
|
|
507
|
+
return this._assetsBucket;
|
|
508
|
+
}
|
|
509
|
+
getCacheBucket() {
|
|
510
|
+
return this._cacheBucket;
|
|
511
|
+
}
|
|
512
|
+
getMediaBucket() {
|
|
513
|
+
return this._mediaBucket;
|
|
514
|
+
}
|
|
515
|
+
getTagCache() {
|
|
516
|
+
return this._tagCache;
|
|
517
|
+
}
|
|
518
|
+
getRevalidationQueue() {
|
|
519
|
+
return this._revalidationQueue;
|
|
520
|
+
}
|
|
521
|
+
getCdn() {
|
|
522
|
+
return this._cdn;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
exports.Payload = Payload;
|
|
526
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5bG9hZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9wYXR0ZXJucy9hd3MvcGF5bG9hZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7OztBQUVILDJDQUF1QztBQUN2QyxtQ0FBcUM7QUFDckMsdURBTWdDO0FBQ2hDLCtFQUk0QztBQUM1Qyx5REFBNEU7QUFDNUUseUVBQW1FO0FBS25FLCtDQU91QjtBQUN2Qiw2Q0FLc0I7QUFDdEIsNkNBSXNCO0FBQ3RCLGlEQUl3QjtBQUN4QixxQ0FBb0U7QUFDcEUseUVBQThEO0FBRTlELE1BQU0sZ0JBQWdCLEdBQUc7SUFDdkIscUZBQXFGO0lBQ3JGLE1BQU0sRUFBRSxPQUFPO0lBQ2YsUUFBUSxFQUFFO1FBQ1IsSUFBSSxFQUFFLFVBQW1CO1FBQ3pCLGdCQUFnQixFQUFFLENBQUM7UUFDbkIsbUJBQW1CLEVBQUUsSUFBSTtLQUMxQjtJQUNELE9BQU8sRUFBRTtRQUNQLGFBQWEsRUFBRSxJQUFJO1FBQ25CLGNBQWMsRUFBRSxFQUFFO1FBQ2xCLFlBQVksRUFBRSxJQUFJO1FBQ2xCLGFBQWEsRUFBRSxFQUFFO1FBQ2pCLG1CQUFtQixFQUFFLEdBQUc7UUFDeEIsb0JBQW9CLEVBQUUsR0FBRztLQUMxQjtJQUNELEtBQUssRUFBRTtRQUNMLGVBQWUsRUFBRSxRQUFRLENBQUMsU0FBUztLQUNwQztJQUNELEtBQUssRUFBRTtRQUNMLE1BQU0sRUFBRSxpQkFBaUI7UUFDekIsS0FBSyxFQUFFLGVBQWU7UUFDdEIsR0FBRyxFQUFFLFFBQVE7UUFDYixLQUFLLEVBQUUsVUFBVTtLQUNsQjtDQUNPLENBQUM7QUFFWDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsSUFBWTtJQUN2QyxPQUFPLElBQUk7U0FDUixXQUFXLEVBQUU7U0FDYixPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQztTQUNsQixPQUFPLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUFDLElBQVk7SUFDaEMsT0FBTyxJQUFJO1NBQ1IsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztTQUM5QyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztBQUMzQyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxpQkFBaUIsQ0FBQyxNQUFjO0lBQ3ZDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDaEMsT0FBTyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0FBQy9ELENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGVBQWUsQ0FBQyxPQUFzQixFQUFFLElBQVk7SUFDM0QsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2pDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNSLE1BQU0sSUFBSSxLQUFLLENBQ2IsR0FBRyxJQUFJLHFDQUFxQztZQUMxQyxnRUFBZ0UsQ0FDbkUsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUM7QUE4QkQ7O0dBRUc7QUFDSCxTQUFTLG1CQUFtQixDQUMxQixNQUVhLEVBQ2IsUUFBNkM7SUFFN0MsT0FBTztRQUNMLFVBQVUsRUFBRSxNQUFNLEVBQUUsVUFBVSxJQUFJLFFBQVEsQ0FBQyxNQUFNO1FBQ2pELE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxJQUFJLFFBQVEsQ0FBQyxPQUFPO1FBQzVDLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxvQkFBb0I7S0FDbkQsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBYSxPQUFRLFNBQVEsc0JBQVM7SUFtQnBDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsR0FBUSxFQUFFLEtBQW9CO1FBQ3RFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFuQkgsZ0JBQVcsR0FBRyxTQUFrQixDQUFDO1FBcUIvQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxVQUFVLEdBQUcsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUEsb0JBQVcsRUFBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFckQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBRXJCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLE1BQU0sZUFBZSxHQUFvQjtZQUN2QyxJQUFJLEVBQUUsU0FBUztZQUNmLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUk7WUFDckIsTUFBTSxFQUFFLGdCQUFnQixDQUFDLE1BQU07U0FDaEMsQ0FBQztRQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVPLGFBQWE7UUFDbkIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO1FBQzNDLElBQUksUUFBUSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDaEMsaUNBQVcsQ0FBQyxJQUFJLENBQ2QscUJBQXFCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSw2Q0FBNkM7Z0JBQy9FLGtFQUFrRSxDQUNyRSxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFTyxjQUFjO1FBQ3BCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUMzQyxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsSUFBSSxJQUFJLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFFckUsSUFBSSxDQUFDLFNBQVM7WUFDWixZQUFZLEtBQUssUUFBUTtnQkFDdkIsQ0FBQyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUM7Z0JBQ3JDLENBQUMsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVPLHNCQUFzQixDQUM1QixRQUFnRDtRQUVoRCxPQUFPO1lBQ0wsWUFBWSxFQUNWLFFBQVEsQ0FBQyxZQUFZLElBQUksbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7WUFDL0QsY0FBYyxFQUFFLFFBQVEsQ0FBQyxjQUFjLElBQUksWUFBWTtZQUN2RCxlQUFlLEVBQ2IsUUFBUSxDQUFDLGVBQWUsSUFBSSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCO1lBQ3hFLGtCQUFrQixFQUNoQixRQUFRLENBQUMsa0JBQWtCO2dCQUMzQixnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsbUJBQW1CO1lBQy9DLGtCQUFrQixFQUFFLFFBQVEsQ0FBQyxrQkFBa0I7WUFDL0MsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO1lBQ25CLG1CQUFtQixFQUFFLFFBQVEsQ0FBQyxtQkFBbUI7WUFDakQsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO1lBQ3JCLFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVztZQUNqQyxrQkFBa0IsRUFBRSxRQUFRLENBQUMsa0JBQWtCO1lBQy9DLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxnQkFBZ0I7U0FDNUMsQ0FBQztJQUNKLENBQUM7SUFFTyxvQkFBb0IsQ0FDMUIsUUFBZ0Q7UUFFaEQsTUFBTSxXQUFXLEdBQXdCO1lBQ3ZDLElBQUksRUFBRSxRQUFRO1lBQ2QsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsUUFBUSxDQUFDO1lBQ3hDLGFBQWEsRUFBRSxRQUFRLENBQUMsYUFBYTtZQUNyQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQStDO1lBQ3BFLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTTtZQUN2QixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87WUFDekIsY0FBYyxFQUFFLFFBQVEsQ0FBQyxjQUFjO1lBQ3ZDLGtCQUFrQixFQUFFLFFBQVEsQ0FBQyxrQkFBa0I7WUFDL0MsMEJBQTBCLEVBQUUsUUFBUSxDQUFDLDBCQUEwQjtTQUNoRSxDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FDekIsNkJBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQ2pFLENBQUM7SUFDSixDQUFDO0lBRU8sc0JBQXNCLENBQzVCLFFBQWdEO1FBRWhELE1BQU0sYUFBYSxHQUEwQjtZQUMzQyxJQUFJLEVBQUUsVUFBVTtZQUNoQixHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLENBQUM7WUFDeEMsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEtBQUs7WUFDeEQsWUFBWSxFQUFFLFFBQVEsQ0FBQyxZQUFZO1lBQ25DLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxnQkFBZ0I7WUFDM0MsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO1lBQ3pCLFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVztZQUNqQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQWlEO1NBQ3ZFLENBQUM7UUFDRixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUN6Qiw2QkFBZSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLFVBQVUsRUFBRSxhQUFhLENBQUMsQ0FDbkUsQ0FBQztJQUNKLENBQUM7SUFFTyxvQkFBb0I7UUFDMUIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMvQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQzdDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDL0MsQ0FBQztJQUVPLGtCQUFrQjtRQUN4QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ3RELE1BQU0sV0FBVyxHQUFtQjtZQUNsQyxVQUFVLEVBQUUsU0FBUztZQUNyQixTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVMsSUFBSSxLQUFLO1lBQzFDLFVBQVUsRUFBRTtnQkFDVixNQUFNLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLG9CQUFvQjtnQkFDdEQsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsWUFBWSxFQUFFO29CQUNaLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsZUFBZTtvQkFDOUMsU0FBUyxFQUFFLElBQUk7aUJBQ2hCO2FBQ0Y7U0FDRixDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FDeEIsMkJBQWMsQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQzlELENBQUM7SUFDSixDQUFDO0lBRU8saUJBQWlCO1FBQ3ZCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDcEQsTUFBTSxVQUFVLEdBQW1CO1lBQ2pDLFVBQVUsRUFBRSxTQUFTO1lBQ3JCLFNBQVMsRUFBRSxXQUFXLENBQUMsU0FBUyxJQUFJLEtBQUs7WUFDekMsVUFBVSxFQUFFO2dCQUNWLE1BQU0sRUFBRSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sbUJBQW1CO2dCQUNyRCxLQUFLLEVBQUUsS0FBSyxDQUFDLDRCQUE0QjthQUMxQztTQUNGLENBQUM7UUFDRixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUN4QiwyQkFBYyxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FDNUQsQ0FBQztJQUNKLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNwRCxNQUFNLFVBQVUsR0FBbUI7WUFDakMsVUFBVSxFQUFFLFNBQVM7WUFDckIsU0FBUyxFQUFFLFdBQVcsQ0FBQyxTQUFTLElBQUksS0FBSztTQUMxQyxDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FDeEIsMkJBQWMsQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQzVELENBQUM7SUFDSixDQUFDO0lBRU8sY0FBYztRQUNwQixNQUFNLGFBQWEsR0FBMEI7WUFDM0MsSUFBSSxFQUFFLFVBQVU7WUFDaEIsWUFBWSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFO1lBQ3hDLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRTtZQUNwQyxzQkFBc0IsRUFBRTtnQkFDdEI7b0JBQ0UsU0FBUyxFQUFFLFlBQVk7b0JBQ3ZCLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRTtvQkFDekMsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFO2lCQUM5QzthQUNGO1NBQ0YsQ0FBQztRQUNGLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQ25DLDZCQUFlLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsVUFBVSxFQUFFLGFBQWEsQ0FBQyxDQUNuRSxDQUFDO0lBQ0osQ0FBQztJQUVPLHVCQUF1QjtRQUM3QixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsSUFBSSxFQUFFLENBQUM7UUFDbEUsTUFBTSxtQkFBbUIsR0FDdkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE9BQU87WUFDekMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDO1FBRWhELG1DQUFtQztRQUNuQyxJQUFJLFNBQXlDLENBQUM7UUFDOUMsSUFBSSxXQUFXLENBQUMsZUFBZSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQzFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDeEIsQ0FBQzthQUFNLElBQUksV0FBVyxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3ZDLFNBQVMsR0FBRztnQkFDVixPQUFPLEVBQUUsV0FBVyxDQUFDLGVBQWUsQ0FBQyxPQUFPLElBQUksSUFBSTtnQkFDcEQsZUFBZSxFQUFFLFdBQVcsQ0FBQyxlQUFlLENBQUMsZUFBZSxJQUFJLENBQUM7YUFDbEUsQ0FBQztRQUNKLENBQUM7YUFBTSxDQUFDO1lBQ04sU0FBUyxHQUFHLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDcEQsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFnQjtZQUM5QixJQUFJLEVBQUUsT0FBTztZQUNiLFNBQVMsRUFBRSxNQUFNO1lBQ2pCLGlCQUFpQixFQUFFLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxtQkFBbUI7WUFDdkUsc0JBQXNCLEVBQUUsV0FBVyxDQUFDLHNCQUFzQjtZQUMxRCxjQUFjLEVBQUUsV0FBVyxDQUFDLGNBQWM7WUFDMUMseUJBQXlCLEVBQUUsSUFBSTtZQUMvQixlQUFlLEVBQUUsU0FBUztTQUMzQixDQUFDO1FBQ0YsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUM3QywrQkFBZ0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQ3JFLENBQUM7SUFDSixDQUFDO0lBRU8scUJBQXFCO1FBQzNCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDekMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDdkQsQ0FBQztJQUVPLGtCQUFrQjtRQUN4QixNQUFNLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxHQUFHLG1CQUFtQixDQUN2RSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQzFCO1lBQ0UsTUFBTSxFQUFFLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxhQUFhO1lBQzlDLE9BQU8sRUFBRSxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsY0FBYztTQUNqRCxDQUNGLENBQUM7UUFFRixNQUFNLFdBQVcsR0FBb0I7WUFDbkMsSUFBSSxFQUFFLFFBQVE7WUFDZCxVQUFVLEVBQUUsTUFBTTtZQUNsQixJQUFJLEVBQUUsaUJBQUksQ0FBQyxTQUFTLENBQ2xCLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxzQ0FBc0MsQ0FDakU7WUFDRCxPQUFPLEVBQUUsZUFBZTtZQUN4QixPQUFPLEVBQUUsb0JBQU8sQ0FBQyxXQUFXO1lBQzVCLFlBQVksRUFBRSx5QkFBWSxDQUFDLE1BQU07WUFDakMsVUFBVTtZQUNWLE9BQU87WUFDUCxvQkFBb0I7WUFDcEIsV0FBVyxFQUFFO2dCQUNYLFFBQVEsRUFBRSxnQ0FBbUIsQ0FBQyxJQUFJO2dCQUNsQyxVQUFVLEVBQUUsdUJBQVUsQ0FBQyxlQUFlO2FBQ3ZDO1lBQ0QsV0FBVyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUM3QixhQUFhLEVBQUU7Z0JBQ2IsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFNBQVM7cUJBQzlCLGNBQWMsRUFBRTtxQkFDaEIsU0FBUyxDQUFDLFVBQVUsQ0FBQztnQkFDeEIsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDO2FBQ3pFO1lBQ0QsV0FBVyxFQUFFLElBQUksQ0FBQyxzQkFBc0IsRUFBRTtTQUMzQyxDQUFDO1FBRUYsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQ2hDLDJCQUFjLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUM5RCxDQUFDO1FBRUYsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BDLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsTUFBTSxPQUFPLEdBQTJCO1lBQ3RDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRTtZQUMvQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUU7WUFDM0MsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFO1lBQy9DLFlBQVksRUFBRSxNQUFNO1lBQ3BCLGlCQUFpQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFO1lBQ3BELG1CQUFtQixFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLFdBQVc7WUFDbkQsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUU7WUFDakQsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFdBQVcsRUFBRTtZQUM3RCx5QkFBeUIsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sSUFBSSxXQUFXO1lBQ3pELGlCQUFpQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFO1lBQ3BELGNBQWMsRUFBRSxJQUFJLENBQUMsYUFBYTtTQUNuQyxDQUFDO1FBRUYsZ0RBQWdEO1FBQ2hELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RELElBQUksWUFBWSxFQUFFLENBQUM7WUFDakIsT0FBTyxDQUFDLHNCQUFzQixHQUFHLFdBQVcsWUFBWSxFQUFFLENBQUM7UUFDN0QsQ0FBQztRQUVELE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbkQsQ0FBQztJQUVPLHNCQUFzQixDQUFDLE1BQXFCO1FBQ2xELE1BQU0sY0FBYyxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsa0JBQWtCLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVPLGlCQUFpQjtRQUN2QixNQUFNLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxHQUFHLG1CQUFtQixDQUN2RSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsRUFDckM7WUFDRSxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLFlBQVk7WUFDN0MsT0FBTyxFQUFFLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxhQUFhO1NBQ2hELENBQ0YsQ0FBQztRQUVGLE1BQU0sVUFBVSxHQUFvQjtZQUNsQyxJQUFJLEVBQUUsUUFBUTtZQUNkLFVBQVUsRUFBRSxNQUFNO1lBQ2xCLElBQUksRUFBRSxpQkFBSSxDQUFDLFNBQVMsQ0FDbEIsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLHlDQUF5QyxDQUNwRTtZQUNELE9BQU8sRUFBRSxlQUFlO1lBQ3hCLE9BQU8sRUFBRSxvQkFBTyxDQUFDLFdBQVc7WUFDNUIsWUFBWSxFQUFFLHlCQUFZLENBQUMsTUFBTTtZQUNqQyxVQUFVO1lBQ1YsT0FBTztZQUNQLG9CQUFvQjtZQUNwQixXQUFXLEVBQUUsRUFBRSxRQUFRLEVBQUUsZ0NBQW1CLENBQUMsSUFBSSxFQUFFO1lBQ25ELFdBQVcsRUFBRTtnQkFDWCxXQUFXLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUU7Z0JBQy9DLGlCQUFpQixFQUFFLFNBQVM7YUFDN0I7U0FDRixDQUFDO1FBRUYsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQy9CLDJCQUFjLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsbUJBQW1CLEVBQUUsVUFBVSxDQUFDLENBQ3hFLENBQUM7UUFFRixNQUFNLGFBQWEsR0FBRyxlQUFlLENBQUMsS0FBSyxFQUFFLG1CQUFtQixDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFNUMsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sd0JBQXdCO1FBQzlCLE1BQU0sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLEdBQUcsbUJBQW1CLENBQ3ZFLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFlBQVksRUFDaEM7WUFDRSxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLG1CQUFtQjtZQUNwRCxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLG9CQUFvQjtTQUN2RCxDQUNGLENBQUM7UUFFRixNQUFNLGlCQUFpQixHQUFvQjtZQUN6QyxJQUFJLEVBQUUsUUFBUTtZQUNkLFVBQVUsRUFBRSxNQUFNO1lBQ2xCLElBQUksRUFBRSxpQkFBSSxDQUFDLFNBQVMsQ0FDbEIsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLG1DQUFtQyxDQUM5RDtZQUNELE9BQU8sRUFBRSxlQUFlO1lBQ3hCLE9BQU8sRUFBRSxvQkFBTyxDQUFDLFdBQVc7WUFDNUIsWUFBWSxFQUFFLHlCQUFZLENBQUMsTUFBTTtZQUNqQyxVQUFVO1lBQ1YsT0FBTztZQUNQLG9CQUFvQjtZQUNwQixXQUFXLEVBQUU7Z0JBQ1gsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUU7Z0JBQ2pELGlCQUFpQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFO2FBQ3JEO1NBQ0YsQ0FBQztRQUVGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUN0QywyQkFBYyxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLGNBQWMsRUFBRSxpQkFBaUIsQ0FBQyxDQUMxRSxDQUFDO1FBRUYsTUFBTSxrQkFBa0IsR0FBRyxZQUFZLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUM1RCxrQkFBa0IsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxFQUFFLEVBQUU7WUFDdkUsU0FBUyxFQUFFLENBQUM7U0FDYixDQUFDLENBQUM7UUFFSCxNQUFNLG9CQUFvQixHQUFHLGVBQWUsQ0FBQyxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDM0UsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFFbkUsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVPLFNBQVM7UUFDZixNQUFNLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRWhFLE1BQU0sUUFBUSxHQUFrQjtZQUM5QixVQUFVLEVBQUUsTUFBTTtZQUNsQixNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDcEIsV0FBVyxFQUFFLGtCQUFrQjtZQUMvQixxQkFBcUIsRUFBRSxLQUFLO1lBQzVCLGlCQUFpQixFQUFFLElBQUk7WUFDdkIsVUFBVSxFQUFFLGdCQUFnQjtZQUM1QixXQUFXO1lBQ1gsV0FBVztZQUNYLFVBQVUsRUFBRTtnQkFDVjtvQkFDRSxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLE1BQU07b0JBQzFDLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYTtvQkFDMUIsV0FBVyxFQUFFLG1CQUFtQjtpQkFDakM7Z0JBQ0Q7b0JBQ0UsV0FBVyxFQUFFLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxLQUFLO29CQUN6QyxNQUFNLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtvQkFDL0IsV0FBVyxFQUFFLG1CQUFtQjtpQkFDakM7Z0JBQ0Q7b0JBQ0UsV0FBVyxFQUFFLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxHQUFHO29CQUN2QyxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU87b0JBQ3BCLFdBQVcsRUFBRSxrQkFBa0I7b0JBQy9CLGNBQWMsRUFBRSxLQUFLO2lCQUN0QjtnQkFDRDtvQkFDRSxXQUFXLEVBQUUsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEtBQUs7b0JBQ3pDLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTztvQkFDcEIsV0FBVyxFQUFFLGtCQUFrQjtvQkFDL0IsY0FBYyxFQUFFLEtBQUs7aUJBQ3RCO2dCQUNELEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDO2FBQ3RDO1NBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQ3pCLG1CQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUNwRCxDQUFDO0lBQ0osQ0FBQztJQUVPLG1CQUFtQjtRQUt6QixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEIsT0FBTyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUNwQyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDeEMsT0FBTyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUN0QyxDQUFDO1FBRUQsT0FBTztZQUNMLFdBQVcsRUFBRSxTQUFTO1lBQ3RCLFdBQVcsRUFBRSxTQUFTO1lBQ3RCLFVBQVUsRUFBRSxTQUFTO1NBQ3RCLENBQUM7SUFDSixDQUFDO0lBRU8sbUJBQW1CO1FBS3pCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTyxDQUFDO1FBQ2xDLE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTdDLE1BQU0sVUFBVSxHQUFHLHdCQUFVLENBQUMsVUFBVSxDQUN0QyxJQUFJLEVBQ0osR0FBRyxJQUFJLENBQUMsVUFBVSxZQUFZLEVBQzlCLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxDQUMzQixDQUFDO1FBRUYsTUFBTSxXQUFXLEdBQUcsSUFBSSxvQ0FBVyxDQUFDLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxVQUFVLGFBQWEsRUFBRTtZQUN6RSxVQUFVLEVBQUUsTUFBTTtZQUNsQixVQUFVLEVBQUUsOENBQXFCLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztTQUN0RCxDQUFDLENBQUM7UUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQzVELENBQUM7SUFFTyxxQkFBcUI7UUFLM0IsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFJLENBQUM7UUFDbEMsTUFBTSxXQUFXLEdBQ2YsU0FBUyxDQUFDLFdBQVc7WUFDckIsQ0FBQyxTQUFTLENBQUMsY0FBYztnQkFDdkIsQ0FBQyxDQUFDLG9DQUFXLENBQUMsa0JBQWtCLENBQzVCLElBQUksRUFDSixHQUFHLElBQUksQ0FBQyxVQUFVLGFBQWEsRUFDL0IsU0FBUyxDQUFDLGNBQWMsQ0FDekI7Z0JBQ0gsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRWpCLE9BQU87WUFDTCxXQUFXLEVBQUUsU0FBUyxDQUFDLFdBQVk7WUFDbkMsV0FBVztZQUNYLFVBQVUsRUFBRSxTQUFTO1NBQ3RCLENBQUM7SUFDSixDQUFDO0lBRU8sZUFBZTtRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNO1lBQUUsT0FBTztRQUUvQixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDbEQsSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPO1FBRXhCLElBQUkscUJBQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsVUFBVSxhQUFhLEVBQUU7WUFDakQsSUFBSSxFQUFFLFVBQVU7WUFDaEIsVUFBVSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTTtZQUM3QixNQUFNLEVBQUUsMEJBQVksQ0FBQyxTQUFTLENBQzVCLElBQUksc0NBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUNsRDtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxTQUFTO1FBQ1AsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztJQUVELGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDNUIsQ0FBQztJQUVELGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDNUIsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVELFdBQVc7UUFDVCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUVELG9CQUFvQjtRQUNsQixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQztJQUNqQyxDQUFDO0lBRUQsTUFBTTtRQUNKLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztJQUNuQixDQUFDO0NBQ0Y7QUEzaUJELDBCQTJpQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBheWxvYWQgQ01TIFBhdHRlcm4uXG4gKlxuICogQSBoaWdoLWxldmVsIHBhdHRlcm4gdGhhdCBjcmVhdGVzIGFsbCBpbmZyYXN0cnVjdHVyZSByZXF1aXJlZCBmb3IgYVxuICogUGF5bG9hZCBDTVMgZGVwbG95bWVudCB1c2luZyBPcGVuTmV4dC5cbiAqXG4gKiBSZXNvdXJjZXMgY3JlYXRlZDpcbiAqIC0gUkRTIFBvc3RncmVTUUwgZGF0YWJhc2UgKEF1cm9yYSBvciBJbnN0YW5jZSlcbiAqIC0gMyBTMyBidWNrZXRzIChhc3NldHMsIGNhY2hlLCBtZWRpYSlcbiAqIC0gRHluYW1vREIgdGFibGUgKHRhZyBjYWNoZSB3aXRoIEdTSSlcbiAqIC0gU1FTIEZJRk8gcXVldWUgKHJldmFsaWRhdGlvbilcbiAqIC0gMyBMYW1iZGEgZnVuY3Rpb25zIChzZXJ2ZXIsIGltYWdlIG9wdGltaXNhdGlvbiwgcmV2YWxpZGF0aW9uKVxuICogLSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvblxuICpcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBwYXlsb2FkID0gYXBwLmFkZFBhdHRlcm4oUGF0dGVybkZhY3RvcnkuYnVpbGQoXCJQYXlsb2FkQXBwXCIsIHtcbiAqICAgdHlwZTogXCJwYXlsb2FkXCIsXG4gKiAgIG5hbWU6IFwibXktY21zXCJcbiAqIH0pKTtcbiAqXG4gKiAvLyBFc2NhcGUgaGF0Y2hlc1xuICogcGF5bG9hZC5nZXREYXRhYmFzZSgpLmdyYW50Q29ubmVjdChvdGhlckxhbWJkYSk7XG4gKi9cblxuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IHtcbiAgQ29kZSxcbiAgUnVudGltZSxcbiAgQXJjaGl0ZWN0dXJlLFxuICBGdW5jdGlvblVybEF1dGhUeXBlLFxuICB0eXBlIElGdW5jdGlvblxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYVwiO1xuaW1wb3J0IHtcbiAgQ2VydGlmaWNhdGUsXG4gIENlcnRpZmljYXRlVmFsaWRhdGlvbixcbiAgdHlwZSBJQ2VydGlmaWNhdGVcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jZXJ0aWZpY2F0ZW1hbmFnZXJcIjtcbmltcG9ydCB7IEhvc3RlZFpvbmUsIEFSZWNvcmQsIFJlY29yZFRhcmdldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtcm91dGU1M1wiO1xuaW1wb3J0IHsgQ2xvdWRGcm9udFRhcmdldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtcm91dGU1My10YXJnZXRzXCI7XG5cbmltcG9ydCB0eXBlIEFwcCBmcm9tIFwiLi4vLi4vYXBwLmpzXCI7XG5pbXBvcnQgeyB0eXBlIElQYXlsb2FkUHJvcHMsIHR5cGUgSVBheWxvYWQgfSBmcm9tIFwiLi9pbnRlcmZhY2VzL3BhdHRlcm4uanNcIjtcbmltcG9ydCB7IHR5cGUgTWFuaWZlc3RQYXR0ZXJuIH0gZnJvbSBcIi4uLy4uL3V0aWxzL21hbmlmZXN0V3JpdGVyLmpzXCI7XG5pbXBvcnQge1xuICB0eXBlIFJlbGF0aW9uYWxEYXRhYmFzZSxcbiAgdHlwZSBEeW5hbW9EQkRhdGFiYXNlLFxuICBEYXRhYmFzZUZhY3RvcnksXG4gIHR5cGUgQXVyb3JhRGF0YWJhc2VQcm9wcyxcbiAgdHlwZSBJbnN0YW5jZURhdGFiYXNlUHJvcHMsXG4gIHR5cGUgRHluYW1vREJEYXRhYmFzZVByb3BzXG59IGZyb20gXCIuL2RhdGFiYXNlLmpzXCI7XG5pbXBvcnQge1xuICBDb21wdXRlRmFjdG9yeSxcbiAgdHlwZSBMYW1iZGFDb21wdXRlLFxuICBJbnZva2VNb2RlLFxuICB0eXBlIENvZGVMYW1iZGFQcm9wc1xufSBmcm9tIFwiLi9jb21wdXRlLmpzXCI7XG5pbXBvcnQge1xuICBTdG9yYWdlRmFjdG9yeSxcbiAgdHlwZSBQcml2YXRlU3RvcmFnZSxcbiAgdHlwZSBQcml2YXRlUzNQcm9wc1xufSBmcm9tIFwiLi9zdG9yYWdlLmpzXCI7XG5pbXBvcnQge1xuICBNZXNzYWdpbmdGYWN0b3J5LFxuICB0eXBlIFF1ZXVlTWVzc2FnaW5nLFxuICB0eXBlIElRdWV1ZVByb3BzXG59IGZyb20gXCIuL21lc3NhZ2luZy5qc1wiO1xuaW1wb3J0IHsgQ2RuRmFjdG9yeSwgdHlwZSBDZG4sIHR5cGUgU21hcnRDZG5Qcm9wcyB9IGZyb20gXCIuL2Nkbi5qc1wiO1xuaW1wb3J0IHsgRmphbGxMb2dnZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHMvdmFsaWRhdGlvbkxvZ2dlci5qc1wiO1xuXG5jb25zdCBQQVlMT0FEX0RFRkFVTFRTID0ge1xuICAvKiogUGF0aCB0byBPcGVuTmV4dCBvdXRwdXQgcmVsYXRpdmUgdG8gYXBwIGZvbGRlciAoQ0RLIHJ1bnMgZnJvbSBmamFsbC88YXBwbmFtZT4pICovXG4gIFNPVVJDRTogXCIuLi8uLlwiLFxuICBEQVRBQkFTRToge1xuICAgIFRZUEU6IFwiSW5zdGFuY2VcIiBhcyBjb25zdCxcbiAgICBCQUNLVVBfUkVURU5USU9OOiA3LFxuICAgIERFTEVUSU9OX1BST1RFQ1RJT046IHRydWVcbiAgfSxcbiAgQ09NUFVURToge1xuICAgIFNFUlZFUl9NRU1PUlk6IDE1MzYsXG4gICAgU0VSVkVSX1RJTUVPVVQ6IDMwLFxuICAgIElNQUdFX01FTU9SWTogMTUzNixcbiAgICBJTUFHRV9USU1FT1VUOiAzMCxcbiAgICBSRVZBTElEQVRJT05fTUVNT1JZOiA3NjgsXG4gICAgUkVWQUxJREFUSU9OX1RJTUVPVVQ6IDMwMFxuICB9LFxuICBDQUNIRToge1xuICAgIE1BWF9BR0VfU0VDT05EUzogMzE1MzYwMDAgLy8gMSB5ZWFyXG4gIH0sXG4gIFBBVEhTOiB7XG4gICAgU1RBVElDOiBcIi9fbmV4dC9zdGF0aWMvKlwiLFxuICAgIElNQUdFOiBcIi9fbmV4dC9pbWFnZSpcIixcbiAgICBBUEk6IFwiL2FwaS8qXCIsXG4gICAgQURNSU46IFwiL2FkbWluLypcIlxuICB9XG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIENvbnZlcnQgYSBuYW1lIHRvIGEgdmFsaWQgZGF0YWJhc2UgbmFtZSAoc25ha2VfY2FzZSwgYWxwaGFudW1lcmljIG9ubHkpLlxuICovXG5mdW5jdGlvbiB0b1ZhbGlkRGF0YWJhc2VOYW1lKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuYW1lXG4gICAgLnRvTG93ZXJDYXNlKClcbiAgICAucmVwbGFjZSgvLS9nLCBcIl9cIilcbiAgICAucmVwbGFjZSgvW15hLXowLTlfXS9nLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgbmFtZSB0byBQYXNjYWxDYXNlIGZvciBjb25zdHJ1Y3QgSURzLlxuICovXG5mdW5jdGlvbiB0b1Bhc2NhbENhc2UobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5hbWVcbiAgICAucmVwbGFjZSgvWy1fXSguKS9nLCAoXywgYykgPT4gYy50b1VwcGVyQ2FzZSgpKVxuICAgIC5yZXBsYWNlKC9eLi8sIChjKSA9PiBjLnRvVXBwZXJDYXNlKCkpO1xufVxuXG4vKipcbiAqIEV4dHJhY3Qgcm9vdCBkb21haW4gZnJvbSBhIGZ1bGwgZG9tYWluIG5hbWUuXG4gKiBlLmcuLCBcImNtcy5leGFtcGxlLmNvbVwiIC0+IFwiZXhhbXBsZS5jb21cIlxuICovXG5mdW5jdGlvbiBleHRyYWN0Um9vdERvbWFpbihkb21haW46IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcnRzID0gZG9tYWluLnNwbGl0KFwiLlwiKTtcbiAgcmV0dXJuIHBhcnRzLmxlbmd0aCA+IDIgPyBwYXJ0cy5zbGljZSgtMikuam9pbihcIi5cIikgOiBkb21haW47XG59XG5cbi8qKlxuICogU2FmZWx5IGdldCB0aGUgdW5kZXJseWluZyBMYW1iZGEgZnVuY3Rpb24gZnJvbSBhIGNvbXB1dGUgcmVzb3VyY2UuXG4gKiBUaHJvd3MgYSBjbGVhciBlcnJvciBpZiB0aGUgZnVuY3Rpb24gaXMgbm90IGF2YWlsYWJsZS5cbiAqL1xuZnVuY3Rpb24gcmVxdWlyZUZ1bmN0aW9uKGNvbXB1dGU6IExhbWJkYUNvbXB1dGUsIG5hbWU6IHN0cmluZyk6IElGdW5jdGlvbiB7XG4gIGNvbnN0IGZuID0gY29tcHV0ZS5nZXRGdW5jdGlvbigpO1xuICBpZiAoIWZuKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7bmFtZX0gTGFtYmRhIGZ1bmN0aW9uIGlzIG5vdCBhdmFpbGFibGUuIGAgK1xuICAgICAgICBcIlRoaXMgaW5kaWNhdGVzIGFuIGludGVybmFsIGVycm9yIGluIGNvbXB1dGUgcmVzb3VyY2UgY3JlYXRpb24uXCJcbiAgICApO1xuICB9XG4gIHJldHVybiBmbjtcbn1cblxuLyoqXG4gKiBCYXNlIGRhdGFiYXNlIHByb3BlcnRpZXMgc2hhcmVkIGJldHdlZW4gQXVyb3JhIGFuZCBJbnN0YW5jZS5cbiAqIFVzZXMgUGljayB0byBleHRyYWN0IGNvbW1vbiBwcm9wZXJ0aWVzIGZyb20gdGhlIGRhdGFiYXNlIGNvbmZpZy5cbiAqL1xudHlwZSBCYXNlRGF0YWJhc2VQcm9wcyA9IFBpY2s8XG4gIEluc3RhbmNlRGF0YWJhc2VQcm9wcyxcbiAgfCBcImRhdGFiYXNlTmFtZVwiXG4gIHwgXCJkYXRhYmFzZUVuZ2luZVwiXG4gIHwgXCJiYWNrdXBSZXRlbnRpb25cIlxuICB8IFwiZGVsZXRpb25Qcm90ZWN0aW9uXCJcbiAgfCBcInB1YmxpY2x5QWNjZXNzaWJsZVwiXG4gIHwgXCJwb3J0XCJcbiAgfCBcInBlcmZvcm1hbmNlSW5zaWdodHNcIlxuICB8IFwicHJveHlcIlxuICB8IFwiY3JlZGVudGlhbHNcIlxuICB8IFwic25hcHNob3RJZGVudGlmaWVyXCJcbiAgfCBcInNuYXBzaG90VXNlcm5hbWVcIlxuPjtcblxuLyoqXG4gKiBMYW1iZGEgY29uZmlndXJhdGlvbiB3aXRoIHJlc29sdmVkIGRlZmF1bHRzLlxuICovXG5pbnRlcmZhY2UgUmVzb2x2ZWRMYW1iZGFDb25maWcge1xuICBtZW1vcnlTaXplOiBudW1iZXI7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAgZXBoZW1lcmFsU3RvcmFnZVNpemU/OiBudW1iZXI7XG59XG5cbi8qKlxuICogRXh0cmFjdCBMYW1iZGEgY29uZmlnIGZyb20gcHJvcHMgd2l0aCBkZWZhdWx0cy5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZUxhbWJkYUNvbmZpZyhcbiAgY29uZmlnOlxuICAgIHwgeyBtZW1vcnlTaXplPzogbnVtYmVyOyB0aW1lb3V0PzogbnVtYmVyOyBlcGhlbWVyYWxTdG9yYWdlU2l6ZT86IG51bWJlciB9XG4gICAgfCB1bmRlZmluZWQsXG4gIGRlZmF1bHRzOiB7IG1lbW9yeTogbnVtYmVyOyB0aW1lb3V0OiBudW1iZXIgfVxuKTogUmVzb2x2ZWRMYW1iZGFDb25maWcge1xuICByZXR1cm4ge1xuICAgIG1lbW9yeVNpemU6IGNvbmZpZz8ubWVtb3J5U2l6ZSA/PyBkZWZhdWx0cy5tZW1vcnksXG4gICAgdGltZW91dDogY29uZmlnPy50aW1lb3V0ID8/IGRlZmF1bHRzLnRpbWVvdXQsXG4gICAgZXBoZW1lcmFsU3RvcmFnZVNpemU6IGNvbmZpZz8uZXBoZW1lcmFsU3RvcmFnZVNpemVcbiAgfTtcbn1cblxuLyoqXG4gKiBQYXlsb2FkIENNUyBwYXR0ZXJuIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIENvbXBvc2VzIGFsbCByZXF1aXJlZCBBV1MgcmVzb3VyY2VzIGZvciBhIFBheWxvYWQgZGVwbG95bWVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIFBheWxvYWQgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJUGF5bG9hZCB7XG4gIHB1YmxpYyByZWFkb25seSBwYXR0ZXJuVHlwZSA9IFwicGF5bG9hZFwiIGFzIGNvbnN0O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgYXBwOiBBcHA7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IElQYXlsb2FkUHJvcHM7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGFzY2FsTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHBheWxvYWRTZWNyZXQ6IHN0cmluZztcblxuICBwcml2YXRlIF9kYXRhYmFzZSE6IFJlbGF0aW9uYWxEYXRhYmFzZTtcbiAgcHJpdmF0ZSBfc2VydmVyITogTGFtYmRhQ29tcHV0ZTtcbiAgcHJpdmF0ZSBfaW1hZ2VPcHRpbWlzYXRpb24hOiBMYW1iZGFDb21wdXRlO1xuICBwcml2YXRlIF9yZXZhbGlkYXRpb24hOiBMYW1iZGFDb21wdXRlO1xuICBwcml2YXRlIF9hc3NldHNCdWNrZXQhOiBQcml2YXRlU3RvcmFnZTtcbiAgcHJpdmF0ZSBfY2FjaGVCdWNrZXQhOiBQcml2YXRlU3RvcmFnZTtcbiAgcHJpdmF0ZSBfbWVkaWFCdWNrZXQhOiBQcml2YXRlU3RvcmFnZTtcbiAgcHJpdmF0ZSBfdGFnQ2FjaGUhOiBEeW5hbW9EQkRhdGFiYXNlO1xuICBwcml2YXRlIF9yZXZhbGlkYXRpb25RdWV1ZSE6IFF1ZXVlTWVzc2FnaW5nO1xuICBwcml2YXRlIF9jZG4hOiBDZG47XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXBwOiBBcHAsIHByb3BzOiBJUGF5bG9hZFByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHRoaXMuYXBwID0gYXBwO1xuICAgIHRoaXMucHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLnBhc2NhbE5hbWUgPSB0b1Bhc2NhbENhc2UocHJvcHMubmFtZSk7XG4gICAgdGhpcy5wYXlsb2FkU2VjcmV0ID0gcmFuZG9tQnl0ZXMoMzIpLnRvU3RyaW5nKFwiaGV4XCIpO1xuXG4gICAgdGhpcy5yZWdpc3Rlck1hbmlmZXN0KCk7XG4gICAgdGhpcy52YWxpZGF0ZVByb3BzKCk7XG5cbiAgICB0aGlzLmNyZWF0ZURhdGFiYXNlKCk7XG4gICAgdGhpcy5jcmVhdGVTdG9yYWdlQnVja2V0cygpO1xuICAgIHRoaXMuY3JlYXRlVGFnQ2FjaGUoKTtcbiAgICB0aGlzLmNyZWF0ZVJldmFsaWRhdGlvblF1ZXVlKCk7XG4gICAgdGhpcy5jcmVhdGVMYW1iZGFGdW5jdGlvbnMoKTtcbiAgICB0aGlzLmNyZWF0ZUNkbigpO1xuICAgIHRoaXMuY3JlYXRlRG5zUmVjb3JkKCk7XG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyTWFuaWZlc3QoKTogdm9pZCB7XG4gICAgY29uc3QgbWFuaWZlc3RQYXR0ZXJuOiBNYW5pZmVzdFBhdHRlcm4gPSB7XG4gICAgICB0eXBlOiBcInBheWxvYWRcIixcbiAgICAgIG5hbWU6IHRoaXMucHJvcHMubmFtZSxcbiAgICAgIHNvdXJjZTogUEFZTE9BRF9ERUZBVUxUUy5TT1VSQ0VcbiAgICB9O1xuICAgIHRoaXMuYXBwLmdldE1hbmlmZXN0Q29sbGVjdG9yKCkuc2V0UGF0dGVybihtYW5pZmVzdFBhdHRlcm4pO1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByb3BzKCk6IHZvaWQge1xuICAgIGNvbnN0IGRiQ29uZmlnID0gdGhpcy5wcm9wcy5kYXRhYmFzZSA/PyB7fTtcbiAgICBpZiAoZGJDb25maWcucHVibGljbHlBY2Nlc3NpYmxlKSB7XG4gICAgICBGamFsbExvZ2dlci53YXJuKFxuICAgICAgICBgUGF5bG9hZCBkYXRhYmFzZSAnJHt0aGlzLnByb3BzLm5hbWV9JyBpcyBjb25maWd1cmVkIHdpdGggcHVibGljIGFjY2Vzc2liaWxpdHkuIGAgK1xuICAgICAgICAgIFwiVGhpcyBpcyBhIHNlY3VyaXR5IHJpc2sgYW5kIHNob3VsZCBvbmx5IGJlIHVzZWQgZm9yIGRldmVsb3BtZW50LlwiXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRGF0YWJhc2UoKTogdm9pZCB7XG4gICAgY29uc3QgZGJDb25maWcgPSB0aGlzLnByb3BzLmRhdGFiYXNlID8/IHt9O1xuICAgIGNvbnN0IGRhdGFiYXNlVHlwZSA9IGRiQ29uZmlnLnR5cGUgPz8gUEFZTE9BRF9ERUZBVUxUUy5EQVRBQkFTRS5UWVBFO1xuXG4gICAgdGhpcy5fZGF0YWJhc2UgPVxuICAgICAgZGF0YWJhc2VUeXBlID09PSBcIkF1cm9yYVwiXG4gICAgICAgID8gdGhpcy5jcmVhdGVBdXJvcmFEYXRhYmFzZShkYkNvbmZpZylcbiAgICAgICAgOiB0aGlzLmNyZWF0ZUluc3RhbmNlRGF0YWJhc2UoZGJDb25maWcpO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZEJhc2VEYXRhYmFzZVByb3BzKFxuICAgIGRiQ29uZmlnOiBOb25OdWxsYWJsZTxJUGF5bG9hZFByb3BzW1wiZGF0YWJhc2VcIl0+XG4gICk6IEJhc2VEYXRhYmFzZVByb3BzIHtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YWJhc2VOYW1lOlxuICAgICAgICBkYkNvbmZpZy5kYXRhYmFzZU5hbWUgPz8gdG9WYWxpZERhdGFiYXNlTmFtZSh0aGlzLnByb3BzLm5hbWUpLFxuICAgICAgZGF0YWJhc2VFbmdpbmU6IGRiQ29uZmlnLmRhdGFiYXNlRW5naW5lID8/IFwicG9zdGdyZXNxbFwiLFxuICAgICAgYmFja3VwUmV0ZW50aW9uOlxuICAgICAgICBkYkNvbmZpZy5iYWNrdXBSZXRlbnRpb24gPz8gUEFZTE9BRF9ERUZBVUxUUy5EQVRBQkFTRS5CQUNLVVBfUkVURU5USU9OLFxuICAgICAgZGVsZXRpb25Qcm90ZWN0aW9uOlxuICAgICAgICBkYkNvbmZpZy5kZWxldGlvblByb3RlY3Rpb24gPz9cbiAgICAgICAgUEFZTE9BRF9ERUZBVUxUUy5EQVRBQkFTRS5ERUxFVElPTl9QUk9URUNUSU9OLFxuICAgICAgcHVibGljbHlBY2Nlc3NpYmxlOiBkYkNvbmZpZy5wdWJsaWNseUFjY2Vzc2libGUsXG4gICAgICBwb3J0OiBkYkNvbmZpZy5wb3J0LFxuICAgICAgcGVyZm9ybWFuY2VJbnNpZ2h0czogZGJDb25maWcucGVyZm9ybWFuY2VJbnNpZ2h0cyxcbiAgICAgIHByb3h5OiBkYkNvbmZpZy5wcm94eSxcbiAgICAgIGNyZWRlbnRpYWxzOiBkYkNvbmZpZy5jcmVkZW50aWFscyxcbiAgICAgIHNuYXBzaG90SWRlbnRpZmllcjogZGJDb25maWcuc25hcHNob3RJZGVudGlmaWVyLFxuICAgICAgc25hcHNob3RVc2VybmFtZTogZGJDb25maWcuc25hcHNob3RVc2VybmFtZVxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUF1cm9yYURhdGFiYXNlKFxuICAgIGRiQ29uZmlnOiBOb25OdWxsYWJsZTxJUGF5bG9hZFByb3BzW1wiZGF0YWJhc2VcIl0+XG4gICk6IFJlbGF0aW9uYWxEYXRhYmFzZSB7XG4gICAgY29uc3QgYXVyb3JhUHJvcHM6IEF1cm9yYURhdGFiYXNlUHJvcHMgPSB7XG4gICAgICB0eXBlOiBcIkF1cm9yYVwiLFxuICAgICAgLi4udGhpcy5idWlsZEJhc2VEYXRhYmFzZVByb3BzKGRiQ29uZmlnKSxcbiAgICAgIGFsbG93ZWRJcENpZHI6IGRiQ29uZmlnLmFsbG93ZWRJcENpZHIsXG4gICAgICBlbmNyeXB0aW9uOiBkYkNvbmZpZy5lbmNyeXB0aW9uIGFzIEF1cm9yYURhdGFiYXNlUHJvcHNbXCJlbmNyeXB0aW9uXCJdLFxuICAgICAgd3JpdGVyOiBkYkNvbmZpZy53cml0ZXIsXG4gICAgICByZWFkZXJzOiBkYkNvbmZpZy5yZWFkZXJzLFxuICAgICAgYWxsb3dWcGNBY2Nlc3M6IGRiQ29uZmlnLmFsbG93VnBjQWNjZXNzLFxuICAgICAgbW9uaXRvcmluZ0ludGVydmFsOiBkYkNvbmZpZy5tb25pdG9yaW5nSW50ZXJ2YWwsXG4gICAgICBwcmVmZXJyZWRNYWludGVuYW5jZVdpbmRvdzogZGJDb25maWcucHJlZmVycmVkTWFpbnRlbmFuY2VXaW5kb3dcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmFwcC5hZGREYXRhYmFzZShcbiAgICAgIERhdGFiYXNlRmFjdG9yeS5idWlsZChgJHt0aGlzLnBhc2NhbE5hbWV9RGF0YWJhc2VgLCBhdXJvcmFQcm9wcylcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVJbnN0YW5jZURhdGFiYXNlKFxuICAgIGRiQ29uZmlnOiBOb25OdWxsYWJsZTxJUGF5bG9hZFByb3BzW1wiZGF0YWJhc2VcIl0+XG4gICk6IFJlbGF0aW9uYWxEYXRhYmFzZSB7XG4gICAgY29uc3QgaW5zdGFuY2VQcm9wczogSW5zdGFuY2VEYXRhYmFzZVByb3BzID0ge1xuICAgICAgdHlwZTogXCJJbnN0YW5jZVwiLFxuICAgICAgLi4udGhpcy5idWlsZEJhc2VEYXRhYmFzZVByb3BzKGRiQ29uZmlnKSxcbiAgICAgIHB1YmxpY2x5QWNjZXNzaWJsZTogZGJDb25maWcucHVibGljbHlBY2Nlc3NpYmxlID8/IGZhbHNlLFxuICAgICAgaW5zdGFuY2VUeXBlOiBkYkNvbmZpZy5pbnN0YW5jZVR5cGUsXG4gICAgICBhbGxvY2F0ZWRTdG9yYWdlOiBkYkNvbmZpZy5hbGxvY2F0ZWRTdG9yYWdlLFxuICAgICAgbXVsdGlBejogZGJDb25maWcubXVsdGlBeixcbiAgICAgIHJlYWRSZXBsaWNhOiBkYkNvbmZpZy5yZWFkUmVwbGljYSxcbiAgICAgIGVuY3J5cHRpb246IGRiQ29uZmlnLmVuY3J5cHRpb24gYXMgSW5zdGFuY2VEYXRhYmFzZVByb3BzW1wiZW5jcnlwdGlvblwiXVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuYXBwLmFkZERhdGFiYXNlKFxuICAgICAgRGF0YWJhc2VGYWN0b3J5LmJ1aWxkKGAke3RoaXMucGFzY2FsTmFtZX1EYXRhYmFzZWAsIGluc3RhbmNlUHJvcHMpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU3RvcmFnZUJ1Y2tldHMoKTogdm9pZCB7XG4gICAgdGhpcy5fYXNzZXRzQnVja2V0ID0gdGhpcy5jcmVhdGVBc3NldHNCdWNrZXQoKTtcbiAgICB0aGlzLl9jYWNoZUJ1Y2tldCA9IHRoaXMuY3JlYXRlQ2FjaGVCdWNrZXQoKTtcbiAgICB0aGlzLl9tZWRpYUJ1Y2tldCA9IHRoaXMuY3JlYXRlTWVkaWFCdWNrZXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQXNzZXRzQnVja2V0KCk6IFByaXZhdGVTdG9yYWdlIHtcbiAgICBjb25zdCBhc3NldHNDb25maWcgPSB0aGlzLnByb3BzLnN0b3JhZ2U/LmFzc2V0cyA/PyB7fTtcbiAgICBjb25zdCBhc3NldHNQcm9wczogUHJpdmF0ZVMzUHJvcHMgPSB7XG4gICAgICBidWNrZXRUeXBlOiBcInByaXZhdGVcIixcbiAgICAgIHZlcnNpb25lZDogYXNzZXRzQ29uZmlnLnZlcnNpb25lZCA/PyBmYWxzZSxcbiAgICAgIGRlcGxveW1lbnQ6IHtcbiAgICAgICAgc291cmNlOiBgJHtQQVlMT0FEX0RFRkFVTFRTLlNPVVJDRX0vLm9wZW4tbmV4dC9hc3NldHNgLFxuICAgICAgICBwcnVuZTogdHJ1ZSxcbiAgICAgICAgY2FjaGVDb250cm9sOiB7XG4gICAgICAgICAgbWF4QWdlOiBQQVlMT0FEX0RFRkFVTFRTLkNBQ0hFLk1BWF9BR0VfU0VDT05EUyxcbiAgICAgICAgICBpbW11dGFibGU6IHRydWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuYXBwLmFkZFN0b3JhZ2UoXG4gICAgICBTdG9yYWdlRmFjdG9yeS5idWlsZChgJHt0aGlzLnBhc2NhbE5hbWV9QXNzZXRzYCwgYXNzZXRzUHJvcHMpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQ2FjaGVCdWNrZXQoKTogUHJpdmF0ZVN0b3JhZ2Uge1xuICAgIGNvbnN0IGNhY2hlQ29uZmlnID0gdGhpcy5wcm9wcy5zdG9yYWdlPy5jYWNoZSA/PyB7fTtcbiAgICBjb25zdCBjYWNoZVByb3BzOiBQcml2YXRlUzNQcm9wcyA9IHtcbiAgICAgIGJ1Y2tldFR5cGU6IFwicHJpdmF0ZVwiLFxuICAgICAgdmVyc2lvbmVkOiBjYWNoZUNvbmZpZy52ZXJzaW9uZWQgPz8gZmFsc2UsXG4gICAgICBkZXBsb3ltZW50OiB7XG4gICAgICAgIHNvdXJjZTogYCR7UEFZTE9BRF9ERUZBVUxUUy5TT1VSQ0V9Ly5vcGVuLW5leHQvY2FjaGVgLFxuICAgICAgICBwcnVuZTogZmFsc2UgLy8gSVNSIGFkZHMgZmlsZXMgYXQgcnVudGltZVxuICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuYXBwLmFkZFN0b3JhZ2UoXG4gICAgICBTdG9yYWdlRmFjdG9yeS5idWlsZChgJHt0aGlzLnBhc2NhbE5hbWV9Q2FjaGVgLCBjYWNoZVByb3BzKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU1lZGlhQnVja2V0KCk6IFByaXZhdGVTdG9yYWdlIHtcbiAgICBjb25zdCBtZWRpYUNvbmZpZyA9IHRoaXMucHJvcHMuc3RvcmFnZT8ubWVkaWEgPz8ge307XG4gICAgY29uc3QgbWVkaWFQcm9wczogUHJpdmF0ZVMzUHJvcHMgPSB7XG4gICAgICBidWNrZXRUeXBlOiBcInByaXZhdGVcIixcbiAgICAgIHZlcnNpb25lZDogbWVkaWFDb25maWcudmVyc2lvbmVkID8/IGZhbHNlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5hcHAuYWRkU3RvcmFnZShcbiAgICAgIFN0b3JhZ2VGYWN0b3J5LmJ1aWxkKGAke3RoaXMucGFzY2FsTmFtZX1NZWRpYWAsIG1lZGlhUHJvcHMpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVGFnQ2FjaGUoKTogdm9pZCB7XG4gICAgY29uc3QgdGFnQ2FjaGVQcm9wczogRHluYW1vREJEYXRhYmFzZVByb3BzID0ge1xuICAgICAgdHlwZTogXCJEeW5hbW9EQlwiLFxuICAgICAgcGFydGl0aW9uS2V5OiB7IG5hbWU6IFwidGFnXCIsIHR5cGU6IFwiU1wiIH0sXG4gICAgICBzb3J0S2V5OiB7IG5hbWU6IFwicGF0aFwiLCB0eXBlOiBcIlNcIiB9LFxuICAgICAgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlczogW1xuICAgICAgICB7XG4gICAgICAgICAgaW5kZXhOYW1lOiBcInJldmFsaWRhdGVcIixcbiAgICAgICAgICBwYXJ0aXRpb25LZXk6IHsgbmFtZTogXCJwYXRoXCIsIHR5cGU6IFwiU1wiIH0sXG4gICAgICAgICAgc29ydEtleTogeyBuYW1lOiBcInJldmFsaWRhdGVkQXRcIiwgdHlwZTogXCJOXCIgfVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfTtcbiAgICB0aGlzLl90YWdDYWNoZSA9IHRoaXMuYXBwLmFkZERhdGFiYXNlKFxuICAgICAgRGF0YWJhc2VGYWN0b3J5LmJ1aWxkKGAke3RoaXMucGFzY2FsTmFtZX1UYWdDYWNoZWAsIHRhZ0NhY2hlUHJvcHMpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUmV2YWxpZGF0aW9uUXVldWUoKTogdm9pZCB7XG4gICAgY29uc3QgcXVldWVDb25maWcgPSB0aGlzLnByb3BzLm1lc3NhZ2luZz8ucmV2YWxpZGF0aW9uUXVldWUgPz8ge307XG4gICAgY29uc3QgcmV2YWxpZGF0aW9uVGltZW91dCA9XG4gICAgICB0aGlzLnByb3BzLmNvbXB1dGU/LnJldmFsaWRhdGlvbj8udGltZW91dCA/P1xuICAgICAgUEFZTE9BRF9ERUZBVUxUUy5DT01QVVRFLlJFVkFMSURBVElPTl9USU1FT1VUO1xuXG4gICAgLy8gUmVzb2x2ZSBkZWFkIGxldHRlciBxdWV1ZSBjb25maWdcbiAgICBsZXQgZGxxQ29uZmlnOiBJUXVldWVQcm9wc1tcImRlYWRMZXR0ZXJRdWV1ZVwiXTtcbiAgICBpZiAocXVldWVDb25maWcuZGVhZExldHRlclF1ZXVlID09PSBmYWxzZSkge1xuICAgICAgZGxxQ29uZmlnID0gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSBpZiAocXVldWVDb25maWcuZGVhZExldHRlclF1ZXVlKSB7XG4gICAgICBkbHFDb25maWcgPSB7XG4gICAgICAgIGVuYWJsZWQ6IHF1ZXVlQ29uZmlnLmRlYWRMZXR0ZXJRdWV1ZS5lbmFibGVkID8/IHRydWUsXG4gICAgICAgIG1heFJlY2VpdmVDb3VudDogcXVldWVDb25maWcuZGVhZExldHRlclF1ZXVlLm1heFJlY2VpdmVDb3VudCA/PyAzXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBkbHFDb25maWcgPSB7IGVuYWJsZWQ6IHRydWUsIG1heFJlY2VpdmVDb3VudDogMyB9O1xuICAgIH1cblxuICAgIGNvbnN0IHF1ZXVlUHJvcHM6IElRdWV1ZVByb3BzID0ge1xuICAgICAgdHlwZTogXCJxdWV1ZVwiLFxuICAgICAgcXVldWVUeXBlOiBcImZpZm9cIixcbiAgICAgIHZpc2liaWxpdHlUaW1lb3V0OiBxdWV1ZUNvbmZpZy52aXNpYmlsaXR5VGltZW91dCA/PyByZXZhbGlkYXRpb25UaW1lb3V0LFxuICAgICAgbWVzc2FnZVJldGVudGlvblBlcmlvZDogcXVldWVDb25maWcubWVzc2FnZVJldGVudGlvblBlcmlvZCxcbiAgICAgIG1heE1lc3NhZ2VTaXplOiBxdWV1ZUNvbmZpZy5tYXhNZXNzYWdlU2l6ZSxcbiAgICAgIGNvbnRlbnRCYXNlZERlZHVwbGljYXRpb246IHRydWUsXG4gICAgICBkZWFkTGV0dGVyUXVldWU6IGRscUNvbmZpZ1xuICAgIH07XG4gICAgdGhpcy5fcmV2YWxpZGF0aW9uUXVldWUgPSB0aGlzLmFwcC5hZGRNZXNzYWdpbmcoXG4gICAgICBNZXNzYWdpbmdGYWN0b3J5LmJ1aWxkKGAke3RoaXMucGFzY2FsTmFtZX1SZXZhbGlkYXRpb25gLCBxdWV1ZVByb3BzKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUxhbWJkYUZ1bmN0aW9ucygpOiB2b2lkIHtcbiAgICB0aGlzLl9zZXJ2ZXIgPSB0aGlzLmNyZWF0ZVNlcnZlckxhbWJkYSgpO1xuICAgIHRoaXMuX2ltYWdlT3B0aW1pc2F0aW9uID0gdGhpcy5jcmVhdGVJbWFnZUxhbWJkYSgpO1xuICAgIHRoaXMuX3JldmFsaWRhdGlvbiA9IHRoaXMuY3JlYXRlUmV2YWxpZGF0aW9uTGFtYmRhKCk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVNlcnZlckxhbWJkYSgpOiBMYW1iZGFDb21wdXRlIHtcbiAgICBjb25zdCB7IG1lbW9yeVNpemUsIHRpbWVvdXQsIGVwaGVtZXJhbFN0b3JhZ2VTaXplIH0gPSByZXNvbHZlTGFtYmRhQ29uZmlnKFxuICAgICAgdGhpcy5wcm9wcy5jb21wdXRlPy5zZXJ2ZXIsXG4gICAgICB7XG4gICAgICAgIG1lbW9yeTogUEFZTE9BRF9ERUZBVUxUUy5DT01QVVRFLlNFUlZFUl9NRU1PUlksXG4gICAgICAgIHRpbWVvdXQ6IFBBWUxPQURfREVGQVVMVFMuQ09NUFVURS5TRVJWRVJfVElNRU9VVFxuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCBzZXJ2ZXJQcm9wczogQ29kZUxhbWJkYVByb3BzID0ge1xuICAgICAgdHlwZTogXCJsYW1iZGFcIixcbiAgICAgIGRlcGxveW1lbnQ6IFwiY29kZVwiLFxuICAgICAgY29kZTogQ29kZS5mcm9tQXNzZXQoXG4gICAgICAgIGAke1BBWUxPQURfREVGQVVMVFMuU09VUkNFfS8ub3Blbi1uZXh0L3NlcnZlci1mdW5jdGlvbnMvZGVmYXVsdGBcbiAgICAgICksXG4gICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZS5BUk1fNjQsXG4gICAgICBtZW1vcnlTaXplLFxuICAgICAgdGltZW91dCxcbiAgICAgIGVwaGVtZXJhbFN0b3JhZ2VTaXplLFxuICAgICAgZnVuY3Rpb25Vcmw6IHtcbiAgICAgICAgYXV0aFR5cGU6IEZ1bmN0aW9uVXJsQXV0aFR5cGUuTk9ORSxcbiAgICAgICAgaW52b2tlTW9kZTogSW52b2tlTW9kZS5SRVNQT05TRV9TVFJFQU1cbiAgICAgIH0sXG4gICAgICBjb25uZWN0aW9uczogW3RoaXMuX2RhdGFiYXNlXSxcbiAgICAgIHNlY3JldHNJbXBvcnQ6IHtcbiAgICAgICAgREFUQUJBU0VfVVNFUk5BTUU6IHRoaXMuX2RhdGFiYXNlXG4gICAgICAgICAgLmdldENyZWRlbnRpYWxzKClcbiAgICAgICAgICAuZ2V0SW1wb3J0KFwidXNlcm5hbWVcIiksXG4gICAgICAgIERBVEFCQVNFX1BBU1NXT1JEOiB0aGlzLl9kYXRhYmFzZS5nZXRDcmVkZW50aWFscygpLmdldEltcG9ydChcInBhc3N3b3JkXCIpXG4gICAgICB9LFxuICAgICAgZW52aXJvbm1lbnQ6IHRoaXMuYnVpbGRTZXJ2ZXJFbnZpcm9ubWVudCgpXG4gICAgfTtcblxuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuYXBwLmFkZENvbXB1dGUoXG4gICAgICBDb21wdXRlRmFjdG9yeS5idWlsZChgJHt0aGlzLnBhc2NhbE5hbWV9U2VydmVyYCwgc2VydmVyUHJvcHMpXG4gICAgKTtcblxuICAgIHRoaXMuZ3JhbnRTZXJ2ZXJQZXJtaXNzaW9ucyhzZXJ2ZXIpO1xuICAgIHJldHVybiBzZXJ2ZXI7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkU2VydmVyRW52aXJvbm1lbnQoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gICAgY29uc3QgYmFzZUVudjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIERBVEFCQVNFX0hPU1Q6IHRoaXMuX2RhdGFiYXNlLmdldEhvc3RFbmRwb2ludCgpLFxuICAgICAgREFUQUJBU0VfUE9SVDogdGhpcy5fZGF0YWJhc2UuZ2V0SG9zdFBvcnQoKSxcbiAgICAgIERBVEFCQVNFX05BTUU6IHRoaXMuX2RhdGFiYXNlLmdldERhdGFiYXNlTmFtZSgpLFxuICAgICAgREFUQUJBU0VfU1NMOiBcInRydWVcIixcbiAgICAgIENBQ0hFX0JVQ0tFVF9OQU1FOiB0aGlzLl9jYWNoZUJ1Y2tldC5nZXRCdWNrZXROYW1lKCksXG4gICAgICBDQUNIRV9CVUNLRVRfUkVHSU9OOiB0aGlzLmFwcC5yZWdpb24gPz8gXCJ1cy1lYXN0LTFcIixcbiAgICAgIENBQ0hFX0RZTkFNT19UQUJMRTogdGhpcy5fdGFnQ2FjaGUuZ2V0VGFibGVOYW1lKCksXG4gICAgICBSRVZBTElEQVRJT05fUVVFVUVfVVJMOiB0aGlzLl9yZXZhbGlkYXRpb25RdWV1ZS5nZXRRdWV1ZVVybCgpLFxuICAgICAgUkVWQUxJREFUSU9OX1FVRVVFX1JFR0lPTjogdGhpcy5hcHAucmVnaW9uID8/IFwidXMtZWFzdC0xXCIsXG4gICAgICBNRURJQV9CVUNLRVRfTkFNRTogdGhpcy5fbWVkaWFCdWNrZXQuZ2V0QnVja2V0TmFtZSgpLFxuICAgICAgUEFZTE9BRF9TRUNSRVQ6IHRoaXMucGF5bG9hZFNlY3JldFxuICAgIH07XG5cbiAgICAvLyBMb2NrIGRvd24gQ09SUyB0byBjdXN0b20gZG9tYWluIHdoZW4gcHJvdmlkZWRcbiAgICBjb25zdCBjdXN0b21Eb21haW4gPSB0aGlzLnByb3BzLmNkbj8uZG9tYWluTmFtZXM/LlswXTtcbiAgICBpZiAoY3VzdG9tRG9tYWluKSB7XG4gICAgICBiYXNlRW52Lk5FWFRfUFVCTElDX1NFUlZFUl9VUkwgPSBgaHR0cHM6Ly8ke2N1c3RvbURvbWFpbn1gO1xuICAgIH1cblxuICAgIHJldHVybiB7IC4uLmJhc2VFbnYsIC4uLnRoaXMucHJvcHMuZW52aXJvbm1lbnQgfTtcbiAgfVxuXG4gIHByaXZhdGUgZ3JhbnRTZXJ2ZXJQZXJtaXNzaW9ucyhzZXJ2ZXI6IExhbWJkYUNvbXB1dGUpOiB2b2lkIHtcbiAgICBjb25zdCBzZXJ2ZXJGdW5jdGlvbiA9IHJlcXVpcmVGdW5jdGlvbihzZXJ2ZXIsIFwiU2VydmVyXCIpO1xuICAgIHRoaXMuX2NhY2hlQnVja2V0LmdyYW50UmVhZFdyaXRlKHNlcnZlckZ1bmN0aW9uKTtcbiAgICB0aGlzLl9tZWRpYUJ1Y2tldC5ncmFudFJlYWRXcml0ZShzZXJ2ZXJGdW5jdGlvbik7XG4gICAgdGhpcy5fdGFnQ2FjaGUuZ3JhbnRSZWFkV3JpdGVEYXRhKHNlcnZlckZ1bmN0aW9uKTtcbiAgICB0aGlzLl9yZXZhbGlkYXRpb25RdWV1ZS5ncmFudFNlbmRNZXNzYWdlcyhzZXJ2ZXJGdW5jdGlvbik7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUltYWdlTGFtYmRhKCk6IExhbWJkYUNvbXB1dGUge1xuICAgIGNvbnN0IHsgbWVtb3J5U2l6ZSwgdGltZW91dCwgZXBoZW1lcmFsU3RvcmFnZVNpemUgfSA9IHJlc29sdmVMYW1iZGFDb25maWcoXG4gICAgICB0aGlzLnByb3BzLmNvbXB1dGU/LmltYWdlT3B0aW1pc2F0aW9uLFxuICAgICAge1xuICAgICAgICBtZW1vcnk6IFBBWUxPQURfREVGQVVMVFMuQ09NUFVURS5JTUFHRV9NRU1PUlksXG4gICAgICAgIHRpbWVvdXQ6IFBBWUxPQURfREVGQVVMVFMuQ09NUFVURS5JTUFHRV9USU1FT1VUXG4gICAgICB9XG4gICAgKTtcblxuICAgIGNvbnN0IGltYWdlUHJvcHM6IENvZGVMYW1iZGFQcm9wcyA9IHtcbiAgICAgIHR5cGU6IFwibGFtYmRhXCIsXG4gICAgICBkZXBsb3ltZW50OiBcImNvZGVcIixcbiAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KFxuICAgICAgICBgJHtQQVlMT0FEX0RFRkFVTFRTLlNPVVJDRX0vLm9wZW4tbmV4dC9pbWFnZS1vcHRpbWl6YXRpb24tZnVuY3Rpb25gXG4gICAgICApLFxuICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgbWVtb3J5U2l6ZSxcbiAgICAgIHRpbWVvdXQsXG4gICAgICBlcGhlbWVyYWxTdG9yYWdlU2l6ZSxcbiAgICAgIGZ1bmN0aW9uVXJsOiB7IGF1dGhUeXBlOiBGdW5jdGlvblVybEF1dGhUeXBlLk5PTkUgfSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIEJVQ0tFVF9OQU1FOiB0aGlzLl9hc3NldHNCdWNrZXQuZ2V0QnVja2V0TmFtZSgpLFxuICAgICAgICBCVUNLRVRfS0VZX1BSRUZJWDogXCJfYXNzZXRzXCJcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgaW1hZ2UgPSB0aGlzLmFwcC5hZGRDb21wdXRlKFxuICAgICAgQ29tcHV0ZUZhY3RvcnkuYnVpbGQoYCR7dGhpcy5wYXNjYWxOYW1lfUltYWdlT3B0aW1pc2F0aW9uYCwgaW1hZ2VQcm9wcylcbiAgICApO1xuXG4gICAgY29uc3QgaW1hZ2VGdW5jdGlvbiA9IHJlcXVpcmVGdW5jdGlvbihpbWFnZSwgXCJJbWFnZU9wdGltaXNhdGlvblwiKTtcbiAgICB0aGlzLl9hc3NldHNCdWNrZXQuZ3JhbnRSZWFkKGltYWdlRnVuY3Rpb24pO1xuXG4gICAgcmV0dXJuIGltYWdlO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVSZXZhbGlkYXRpb25MYW1iZGEoKTogTGFtYmRhQ29tcHV0ZSB7XG4gICAgY29uc3QgeyBtZW1vcnlTaXplLCB0aW1lb3V0LCBlcGhlbWVyYWxTdG9yYWdlU2l6ZSB9ID0gcmVzb2x2ZUxhbWJkYUNvbmZpZyhcbiAgICAgIHRoaXMucHJvcHMuY29tcHV0ZT8ucmV2YWxpZGF0aW9uLFxuICAgICAge1xuICAgICAgICBtZW1vcnk6IFBBWUxPQURfREVGQVVMVFMuQ09NUFVURS5SRVZBTElEQVRJT05fTUVNT1JZLFxuICAgICAgICB0aW1lb3V0OiBQQVlMT0FEX0RFRkFVTFRTLkNPTVBVVEUuUkVWQUxJREFUSU9OX1RJTUVPVVRcbiAgICAgIH1cbiAgICApO1xuXG4gICAgY29uc3QgcmV2YWxpZGF0aW9uUHJvcHM6IENvZGVMYW1iZGFQcm9wcyA9IHtcbiAgICAgIHR5cGU6IFwibGFtYmRhXCIsXG4gICAgICBkZXBsb3ltZW50OiBcImNvZGVcIixcbiAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KFxuICAgICAgICBgJHtQQVlMT0FEX0RFRkFVTFRTLlNPVVJDRX0vLm9wZW4tbmV4dC9yZXZhbGlkYXRpb24tZnVuY3Rpb25gXG4gICAgICApLFxuICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgbWVtb3J5U2l6ZSxcbiAgICAgIHRpbWVvdXQsXG4gICAgICBlcGhlbWVyYWxTdG9yYWdlU2l6ZSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIENBQ0hFX0RZTkFNT19UQUJMRTogdGhpcy5fdGFnQ2FjaGUuZ2V0VGFibGVOYW1lKCksXG4gICAgICAgIENBQ0hFX0JVQ0tFVF9OQU1FOiB0aGlzLl9jYWNoZUJ1Y2tldC5nZXRCdWNrZXROYW1lKClcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgcmV2YWxpZGF0aW9uID0gdGhpcy5hcHAuYWRkQ29tcHV0ZShcbiAgICAgIENvbXB1dGVGYWN0b3J5LmJ1aWxkKGAke3RoaXMucGFzY2FsTmFtZX1SZXZhbGlkYXRpb25gLCByZXZhbGlkYXRpb25Qcm9wcylcbiAgICApO1xuXG4gICAgY29uc3QgcmV2YWxpZGF0aW9uTGFtYmRhID0gcmV2YWxpZGF0aW9uLmdldExhbWJkYUZ1bmN0aW9uKCk7XG4gICAgcmV2YWxpZGF0aW9uTGFtYmRhLmFkZFNxc0V2ZW50U291cmNlKHRoaXMuX3JldmFsaWRhdGlvblF1ZXVlLmdldFF1ZXVlKCksIHtcbiAgICAgIGJhdGNoU2l6ZTogNVxuICAgIH0pO1xuXG4gICAgY29uc3QgcmV2YWxpZGF0aW9uRnVuY3Rpb24gPSByZXF1aXJlRnVuY3Rpb24ocmV2YWxpZGF0aW9uLCBcIlJldmFsaWRhdGlvblwiKTtcbiAgICB0aGlzLl90YWdDYWNoZS5ncmFudFJlYWRXcml0ZURhdGEocmV2YWxpZGF0aW9uRnVuY3Rpb24pO1xuICAgIHRoaXMuX2NhY2hlQnVja2V0LmdyYW50UmVhZFdyaXRlKHJldmFsaWRhdGlvbkZ1bmN0aW9uKTtcbiAgICB0aGlzLl9yZXZhbGlkYXRpb25RdWV1ZS5ncmFudENvbnN1bWVNZXNzYWdlcyhyZXZhbGlkYXRpb25GdW5jdGlvbik7XG5cbiAgICByZXR1cm4gcmV2YWxpZGF0aW9uO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVDZG4oKTogdm9pZCB7XG4gICAgY29uc3QgeyBkb21haW5OYW1lcywgY2VydGlmaWNhdGUgfSA9IHRoaXMucmVzb2x2ZURvbWFpbkNvbmZpZygpO1xuXG4gICAgY29uc3QgY2RuUHJvcHM6IFNtYXJ0Q2RuUHJvcHMgPSB7XG4gICAgICBvcmlnaW5UeXBlOiBcImF1dG9cIixcbiAgICAgIG9yaWdpbjogdGhpcy5fc2VydmVyLFxuICAgICAgY2FjaGVQb2xpY3k6IFwiQ0FDSElOR19ESVNBQkxFRFwiLFxuICAgICAgZGVmYXVsdEFsbG93ZWRNZXRob2RzOiBcIkFMTFwiLFxuICAgICAgZm9yd2FyZEhvc3RIZWFkZXI6IHRydWUsXG4gICAgICBwcmljZUNsYXNzOiBcIlByaWNlQ2xhc3NfMTAwXCIsXG4gICAgICBkb21haW5OYW1lcyxcbiAgICAgIGNlcnRpZmljYXRlLFxuICAgICAgYmVoYXZpb3VyczogW1xuICAgICAgICB7XG4gICAgICAgICAgcGF0aFBhdHRlcm46IFBBWUxPQURfREVGQVVMVFMuUEFUSFMuU1RBVElDLFxuICAgICAgICAgIG9yaWdpbjogdGhpcy5fYXNzZXRzQnVja2V0LFxuICAgICAgICAgIGNhY2hlUG9saWN5OiBcIkNBQ0hJTkdfT1BUSU1JWkVEXCJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHBhdGhQYXR0ZXJuOiBQQVlMT0FEX0RFRkFVTFRTLlBBVEhTLklNQUdFLFxuICAgICAgICAgIG9yaWdpbjogdGhpcy5faW1hZ2VPcHRpbWlzYXRpb24sXG4gICAgICAgICAgY2FjaGVQb2xpY3k6IFwiQ0FDSElOR19PUFRJTUlaRURcIlxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgcGF0aFBhdHRlcm46IFBBWUxPQURfREVGQVVMVFMuUEFUSFMuQVBJLFxuICAgICAgICAgIG9yaWdpbjogdGhpcy5fc2VydmVyLFxuICAgICAgICAgIGNhY2hlUG9saWN5OiBcIkNBQ0hJTkdfRElTQUJMRURcIixcbiAgICAgICAgICBhbGxvd2VkTWV0aG9kczogXCJBTExcIlxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgcGF0aFBhdHRlcm46IFBBWUxPQURfREVGQVVMVFMuUEFUSFMuQURNSU4sXG4gICAgICAgICAgb3JpZ2luOiB0aGlzLl9zZXJ2ZXIsXG4gICAgICAgICAgY2FjaGVQb2xpY3k6IFwiQ0FDSElOR19ESVNBQkxFRFwiLFxuICAgICAgICAgIGFsbG93ZWRNZXRob2RzOiBcIkFMTFwiXG4gICAgICAgIH0sXG4gICAgICAgIC4uLih0aGlzLnByb3BzLmNkbj8uYmVoYXZpb3VycyA/PyBbXSlcbiAgICAgIF1cbiAgICB9O1xuXG4gICAgdGhpcy5fY2RuID0gdGhpcy5hcHAuYWRkQ2RuKFxuICAgICAgQ2RuRmFjdG9yeS5idWlsZChgJHt0aGlzLnBhc2NhbE5hbWV9Q2RuYCwgY2RuUHJvcHMpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZURvbWFpbkNvbmZpZygpOiB7XG4gICAgZG9tYWluTmFtZXM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICAgIGNlcnRpZmljYXRlOiBJQ2VydGlmaWNhdGUgfCB1bmRlZmluZWQ7XG4gICAgaG9zdGVkWm9uZTogUmV0dXJuVHlwZTx0eXBlb2YgSG9zdGVkWm9uZS5mcm9tTG9va3VwPiB8IHVuZGVmaW5lZDtcbiAgfSB7XG4gICAgaWYgKHRoaXMucHJvcHMuZG9tYWluKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHZlU2ltcGxlRG9tYWluKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucHJvcHMuY2RuPy5kb21haW5OYW1lcz8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHZlQWR2YW5jZWREb21haW4oKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZG9tYWluTmFtZXM6IHVuZGVmaW5lZCxcbiAgICAgIGNlcnRpZmljYXRlOiB1bmRlZmluZWQsXG4gICAgICBob3N0ZWRab25lOiB1bmRlZmluZWRcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlU2ltcGxlRG9tYWluKCk6IHtcbiAgICBkb21haW5OYW1lczogc3RyaW5nW107XG4gICAgY2VydGlmaWNhdGU6IElDZXJ0aWZpY2F0ZTtcbiAgICBob3N0ZWRab25lOiBSZXR1cm5UeXBlPHR5cGVvZiBIb3N0ZWRab25lLmZyb21Mb29rdXA+O1xuICB9IHtcbiAgICBjb25zdCBkb21haW4gPSB0aGlzLnByb3BzLmRvbWFpbiE7XG4gICAgY29uc3Qgcm9vdERvbWFpbiA9IGV4dHJhY3RSb290RG9tYWluKGRvbWFpbik7XG5cbiAgICBjb25zdCBob3N0ZWRab25lID0gSG9zdGVkWm9uZS5mcm9tTG9va3VwKFxuICAgICAgdGhpcyxcbiAgICAgIGAke3RoaXMucGFzY2FsTmFtZX1Ib3N0ZWRab25lYCxcbiAgICAgIHsgZG9tYWluTmFtZTogcm9vdERvbWFpbiB9XG4gICAgKTtcblxuICAgIGNvbnN0IGNlcnRpZmljYXRlID0gbmV3IENlcnRpZmljYXRlKHRoaXMsIGAke3RoaXMucGFzY2FsTmFtZX1DZXJ0aWZpY2F0ZWAsIHtcbiAgICAgIGRvbWFpbk5hbWU6IGRvbWFpbixcbiAgICAgIHZhbGlkYXRpb246IENlcnRpZmljYXRlVmFsaWRhdGlvbi5mcm9tRG5zKGhvc3RlZFpvbmUpXG4gICAgfSk7XG5cbiAgICByZXR1cm4geyBkb21haW5OYW1lczogW2RvbWFpbl0sIGNlcnRpZmljYXRlLCBob3N0ZWRab25lIH07XG4gIH1cblxuICBwcml2YXRlIHJlc29sdmVBZHZhbmNlZERvbWFpbigpOiB7XG4gICAgZG9tYWluTmFtZXM6IHN0cmluZ1tdO1xuICAgIGNlcnRpZmljYXRlOiBJQ2VydGlmaWNhdGUgfCB1bmRlZmluZWQ7XG4gICAgaG9zdGVkWm9uZTogdW5kZWZpbmVkO1xuICB9IHtcbiAgICBjb25zdCBjZG5Db25maWcgPSB0aGlzLnByb3BzLmNkbiE7XG4gICAgY29uc3QgY2VydGlmaWNhdGUgPVxuICAgICAgY2RuQ29uZmlnLmNlcnRpZmljYXRlID8/XG4gICAgICAoY2RuQ29uZmlnLmNlcnRpZmljYXRlQXJuXG4gICAgICAgID8gQ2VydGlmaWNhdGUuZnJvbUNlcnRpZmljYXRlQXJuKFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgIGAke3RoaXMucGFzY2FsTmFtZX1DZXJ0aWZpY2F0ZWAsXG4gICAgICAgICAgICBjZG5Db25maWcuY2VydGlmaWNhdGVBcm5cbiAgICAgICAgICApXG4gICAgICAgIDogdW5kZWZpbmVkKTtcblxuICAgIHJldHVybiB7XG4gICAgICBkb21haW5OYW1lczogY2RuQ29uZmlnLmRvbWFpbk5hbWVzISxcbiAgICAgIGNlcnRpZmljYXRlLFxuICAgICAgaG9zdGVkWm9uZTogdW5kZWZpbmVkXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRG5zUmVjb3JkKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5wcm9wcy5kb21haW4pIHJldHVybjtcblxuICAgIGNvbnN0IHsgaG9zdGVkWm9uZSB9ID0gdGhpcy5yZXNvbHZlRG9tYWluQ29uZmlnKCk7XG4gICAgaWYgKCFob3N0ZWRab25lKSByZXR1cm47XG5cbiAgICBuZXcgQVJlY29yZCh0aGlzLCBgJHt0aGlzLnBhc2NhbE5hbWV9QWxpYXNSZWNvcmRgLCB7XG4gICAgICB6b25lOiBob3N0ZWRab25lLFxuICAgICAgcmVjb3JkTmFtZTogdGhpcy5wcm9wcy5kb21haW4sXG4gICAgICB0YXJnZXQ6IFJlY29yZFRhcmdldC5mcm9tQWxpYXMoXG4gICAgICAgIG5ldyBDbG91ZEZyb250VGFyZ2V0KHRoaXMuX2Nkbi5nZXREaXN0cmlidXRpb24oKSlcbiAgICAgIClcbiAgICB9KTtcbiAgfVxuXG4gIGdldERhdGFiYXNlKCk6IFJlbGF0aW9uYWxEYXRhYmFzZSB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGFiYXNlO1xuICB9XG5cbiAgZ2V0U2VydmVyKCk6IExhbWJkYUNvbXB1dGUge1xuICAgIHJldHVybiB0aGlzLl9zZXJ2ZXI7XG4gIH1cblxuICBnZXRJbWFnZU9wdGltaXNhdGlvbigpOiBMYW1iZGFDb21wdXRlIHtcbiAgICByZXR1cm4gdGhpcy5faW1hZ2VPcHRpbWlzYXRpb247XG4gIH1cblxuICBnZXRSZXZhbGlkYXRpb24oKTogTGFtYmRhQ29tcHV0ZSB7XG4gICAgcmV0dXJuIHRoaXMuX3JldmFsaWRhdGlvbjtcbiAgfVxuXG4gIGdldEFzc2V0c0J1Y2tldCgpOiBQcml2YXRlU3RvcmFnZSB7XG4gICAgcmV0dXJuIHRoaXMuX2Fzc2V0c0J1Y2tldDtcbiAgfVxuXG4gIGdldENhY2hlQnVja2V0KCk6IFByaXZhdGVTdG9yYWdlIHtcbiAgICByZXR1cm4gdGhpcy5fY2FjaGVCdWNrZXQ7XG4gIH1cblxuICBnZXRNZWRpYUJ1Y2tldCgpOiBQcml2YXRlU3RvcmFnZSB7XG4gICAgcmV0dXJuIHRoaXMuX21lZGlhQnVja2V0O1xuICB9XG5cbiAgZ2V0VGFnQ2FjaGUoKTogRHluYW1vREJEYXRhYmFzZSB7XG4gICAgcmV0dXJuIHRoaXMuX3RhZ0NhY2hlO1xuICB9XG5cbiAgZ2V0UmV2YWxpZGF0aW9uUXVldWUoKTogUXVldWVNZXNzYWdpbmcge1xuICAgIHJldHVybiB0aGlzLl9yZXZhbGlkYXRpb25RdWV1ZTtcbiAgfVxuXG4gIGdldENkbigpOiBDZG4ge1xuICAgIHJldHVybiB0aGlzLl9jZG47XG4gIH1cbn1cbiJdfQ==
|