@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.
Files changed (112) hide show
  1. package/README.md +3 -3
  2. package/dist/lib/app.d.ts +166 -6
  3. package/dist/lib/app.js +212 -20
  4. package/dist/lib/aspects/resourceInventory.d.ts +4 -4
  5. package/dist/lib/aspects/resourceInventory.js +3 -3
  6. package/dist/lib/config/aws/backupGlobalSettings.js +1 -2
  7. package/dist/lib/config/aws/identityCenter.js +1 -5
  8. package/dist/lib/config/aws/organisation.js +1 -4
  9. package/dist/lib/index.d.ts +1 -0
  10. package/dist/lib/index.js +7 -1
  11. package/dist/lib/patterns/aws/buildkite.js +3 -2
  12. package/dist/lib/patterns/aws/cdn.d.ts +164 -0
  13. package/dist/lib/patterns/aws/cdn.js +264 -0
  14. package/dist/lib/patterns/aws/compute.d.ts +278 -59
  15. package/dist/lib/patterns/aws/compute.js +384 -188
  16. package/dist/lib/patterns/aws/connections.d.ts +46 -0
  17. package/dist/lib/patterns/aws/connections.js +159 -0
  18. package/dist/lib/patterns/aws/database.d.ts +124 -11
  19. package/dist/lib/patterns/aws/database.js +188 -66
  20. package/dist/lib/patterns/aws/hostedZone.js +1 -1
  21. package/dist/lib/patterns/aws/index.d.ts +3 -0
  22. package/dist/lib/patterns/aws/index.js +4 -1
  23. package/dist/lib/patterns/aws/interfaces/compute.d.ts +121 -0
  24. package/dist/lib/patterns/aws/interfaces/compute.js +48 -0
  25. package/dist/lib/patterns/aws/interfaces/connector.d.ts +183 -0
  26. package/dist/lib/patterns/aws/interfaces/connector.js +117 -0
  27. package/dist/lib/patterns/aws/interfaces/database.d.ts +136 -0
  28. package/dist/lib/patterns/aws/interfaces/database.js +65 -0
  29. package/dist/lib/patterns/aws/interfaces/index.d.ts +12 -0
  30. package/dist/lib/patterns/aws/interfaces/index.js +49 -0
  31. package/dist/lib/patterns/aws/interfaces/messaging.d.ts +146 -0
  32. package/dist/lib/patterns/aws/interfaces/messaging.js +56 -0
  33. package/dist/lib/patterns/aws/interfaces/pattern.d.ts +403 -0
  34. package/dist/lib/patterns/aws/interfaces/pattern.js +36 -0
  35. package/dist/lib/patterns/aws/interfaces/storage.d.ts +136 -0
  36. package/dist/lib/patterns/aws/interfaces/storage.js +48 -0
  37. package/dist/lib/patterns/aws/messaging.d.ts +183 -0
  38. package/dist/lib/patterns/aws/messaging.js +239 -0
  39. package/dist/lib/patterns/aws/network.js +4 -4
  40. package/dist/lib/patterns/aws/pattern.d.ts +67 -0
  41. package/dist/lib/patterns/aws/pattern.js +69 -0
  42. package/dist/lib/patterns/aws/payload.d.ts +87 -0
  43. package/dist/lib/patterns/aws/payload.js +526 -0
  44. package/dist/lib/patterns/aws/storage.d.ts +127 -15
  45. package/dist/lib/patterns/aws/storage.js +234 -38
  46. package/dist/lib/resources/aws/backup/backupPlan.js +1 -6
  47. package/dist/lib/resources/aws/backup/backupVault.js +1 -2
  48. package/dist/lib/resources/aws/base/awsStack.d.ts +0 -2
  49. package/dist/lib/resources/aws/base/awsStack.js +1 -7
  50. package/dist/lib/resources/aws/cdn/cloudFront.d.ts +71 -0
  51. package/dist/lib/resources/aws/cdn/cloudFront.js +176 -0
  52. package/dist/lib/resources/aws/cdn/index.d.ts +1 -0
  53. package/dist/lib/resources/aws/cdn/index.js +18 -0
  54. package/dist/lib/resources/aws/compute/ec2.d.ts +5 -0
  55. package/dist/lib/resources/aws/compute/ec2.js +33 -6
  56. package/dist/lib/resources/aws/compute/ecs.d.ts +32 -25
  57. package/dist/lib/resources/aws/compute/ecs.js +31 -115
  58. package/dist/lib/resources/aws/compute/lambda.d.ts +94 -5
  59. package/dist/lib/resources/aws/compute/lambda.js +209 -32
  60. package/dist/lib/resources/aws/database/database.js +1 -1
  61. package/dist/lib/resources/aws/database/dynamodb.d.ts +70 -0
  62. package/dist/lib/resources/aws/database/dynamodb.js +181 -0
  63. package/dist/lib/resources/aws/database/index.d.ts +1 -0
  64. package/dist/lib/resources/aws/database/index.js +2 -1
  65. package/dist/lib/resources/aws/database/migrationLambda.d.ts +80 -0
  66. package/dist/lib/resources/aws/database/migrationLambda.js +119 -0
  67. package/dist/lib/resources/aws/database/rdsAurora.d.ts +15 -0
  68. package/dist/lib/resources/aws/database/rdsAurora.js +41 -18
  69. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +12 -8
  70. package/dist/lib/resources/aws/database/rdsInstance.js +2 -2
  71. package/dist/lib/resources/aws/index.d.ts +2 -0
  72. package/dist/lib/resources/aws/index.js +3 -1
  73. package/dist/lib/resources/aws/messaging/eventbridge.d.ts +28 -0
  74. package/dist/lib/resources/aws/messaging/eventbridge.js +53 -0
  75. package/dist/lib/resources/aws/messaging/index.d.ts +3 -0
  76. package/dist/lib/resources/aws/messaging/index.js +20 -0
  77. package/dist/lib/resources/aws/messaging/sns.d.ts +35 -0
  78. package/dist/lib/resources/aws/messaging/sns.js +70 -0
  79. package/dist/lib/resources/aws/messaging/sqs.d.ts +105 -0
  80. package/dist/lib/resources/aws/messaging/sqs.js +231 -0
  81. package/dist/lib/resources/aws/messaging/utils.d.ts +3 -0
  82. package/dist/lib/resources/aws/messaging/utils.js +7 -0
  83. package/dist/lib/resources/aws/networking/ipam.js +1 -2
  84. package/dist/lib/resources/aws/networking/ipamPool.js +3 -2
  85. package/dist/lib/resources/aws/networking/vpc.js +1 -2
  86. package/dist/lib/resources/aws/storage/ecr.js +8 -5
  87. package/dist/lib/resources/aws/storage/s3.js +1 -2
  88. package/dist/lib/resources/aws/utilities/awsCustomResource.js +1 -1
  89. package/dist/lib/resources/aws/utilities/customResource.js +1 -1
  90. package/dist/lib/utils/getConfig.js +3 -2
  91. package/dist/lib/utils/index.d.ts +1 -0
  92. package/dist/lib/utils/index.js +2 -1
  93. package/dist/lib/utils/manifestWriter.d.ts +174 -0
  94. package/dist/lib/utils/manifestWriter.js +233 -0
  95. package/dist/lib/utils/standardTagsAspect.js +1 -8
  96. package/dist/lib/utils/validationLogger.d.ts +34 -0
  97. package/dist/lib/utils/validationLogger.js +83 -0
  98. package/package.json +3 -3
  99. package/dist/lib/__tests__/setup.d.ts +0 -48
  100. package/dist/lib/__tests__/setup.js +0 -1
  101. package/dist/lib/patterns/aws/cicdRole.d.ts +0 -67
  102. package/dist/lib/patterns/aws/cicdRole.js +0 -68
  103. package/dist/lib/resources/aws/cicd/cicdRole.d.ts +0 -65
  104. package/dist/lib/resources/aws/cicd/cicdRole.js +0 -191
  105. package/dist/lib/resources/aws/compute/ecsFreeTier.d.ts +0 -75
  106. package/dist/lib/resources/aws/compute/ecsFreeTier.js +0 -1
  107. package/dist/lib/resources/aws/compute/ecsSpot.d.ts +0 -75
  108. package/dist/lib/resources/aws/compute/ecsSpot.js +0 -1
  109. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +0 -20
  110. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +0 -1
  111. package/dist/lib/resources/aws/utilities/cfnOutput.d.ts +0 -5
  112. 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5bG9hZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9wYXR0ZXJucy9hd3MvcGF5bG9hZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7OztBQUVILDJDQUF1QztBQUN2QyxtQ0FBcUM7QUFDckMsdURBTWdDO0FBQ2hDLCtFQUk0QztBQUM1Qyx5REFBNEU7QUFDNUUseUVBQW1FO0FBS25FLCtDQU91QjtBQUN2Qiw2Q0FLc0I7QUFDdEIsNkNBSXNCO0FBQ3RCLGlEQUl3QjtBQUN4QixxQ0FBb0U7QUFDcEUseUVBQThEO0FBRTlELE1BQU0sZ0JBQWdCLEdBQUc7SUFDdkIscUZBQXFGO0lBQ3JGLE1BQU0sRUFBRSxPQUFPO0lBQ2YsUUFBUSxFQUFFO1FBQ1IsSUFBSSxFQUFFLFVBQW1CO1FBQ3pCLGdCQUFnQixFQUFFLENBQUM7UUFDbkIsbUJBQW1CLEVBQUUsSUFBSTtLQUMxQjtJQUNELE9BQU8sRUFBRTtRQUNQLGFBQWEsRUFBRSxJQUFJO1FBQ25CLGNBQWMsRUFBRSxFQUFFO1FBQ2xCLFlBQVksRUFBRSxJQUFJO1FBQ2xCLGFBQWEsRUFBRSxFQUFFO1FBQ2pCLG1CQUFtQixFQUFFLEdBQUc7UUFDeEIsb0JBQW9CLEVBQUUsR0FBRztLQUMxQjtJQUNELEtBQUssRUFBRTtRQUNMLGVBQWUsRUFBRSxRQUFRLENBQUMsU0FBUztLQUNwQztJQUNELEtBQUssRUFBRTtRQUNMLE1BQU0sRUFBRSxpQkFBaUI7UUFDekIsS0FBSyxFQUFFLGVBQWU7UUFDdEIsR0FBRyxFQUFFLFFBQVE7UUFDYixLQUFLLEVBQUUsVUFBVTtLQUNsQjtDQUNPLENBQUM7QUFFWDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsSUFBWTtJQUN2QyxPQUFPLElBQUk7U0FDUixXQUFXLEVBQUU7U0FDYixPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQztTQUNsQixPQUFPLENBQUMsYUFB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T0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxTQUFTO1FBQ1AsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztJQUVELGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDNUIsQ0FBQztJQUVELGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDNUIsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVELFdBQVc7UUFDVCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUVELG9CQUFvQjtRQUNsQixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQztJQUNqQyxDQUFDO0lBRUQsTUFBTTtRQUNKLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztJQUNuQixDQUFDO0NBQ0Y7QUEzaUJELDBCQTJpQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBheWxvYWQgQ01TIFBhdHRlcm4uXG4gKlxuICogQSBoaWdoLWxldmVsIHBhdHRlcm4gdGhhdCBjcmVhdGVzIGFsbCBpbmZyYXN0cnVjdHVyZSByZXF1aXJlZCBmb3IgYVxuICogUGF5bG9hZCBDTVMgZGVwbG95bWVudCB1c2luZyBPcGVuTmV4dC5cbiAqXG4gKiBSZXNvdXJjZXMgY3JlYXRlZDpcbiAqIC0gUkRTIFBvc3RncmVTUUwgZGF0YWJhc2UgKEF1cm9yYSBvciBJbnN0YW5jZSlcbiAqIC0gMyBTMyBidWNrZXRzIChhc3NldHMsIGNhY2hlLCBtZWRpYSlcbiAqIC0gRHluYW1vREIgdGFibGUgKHRhZyBjYWNoZSB3aXRoIEdTSSlcbiAqIC0gU1FTIEZJRk8gcXVldWUgKHJldmFsaWRhdGlvbilcbiAqIC0gMyBMYW1iZGEgZnVuY3Rpb25zIChzZXJ2ZXIsIGltYWdlIG9wdGltaXNhdGlvbiwgcmV2YWxpZGF0aW9uKVxuICogLSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvblxuICpcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBwYXlsb2FkID0gYXBwLmFkZFBhdHRlcm4oUGF0dGVybkZhY3RvcnkuYnVpbGQoXCJQYXlsb2FkQXBwXCIsIHtcbiAqICAgdHlwZTogXCJwYXlsb2FkXCIsXG4gKiAgIG5hbWU6IFwibXktY21zXCJcbiAqIH0pKTtcbiAqXG4gKiAvLyBFc2NhcGUgaGF0Y2hlc1xuICogcGF5bG9hZC5nZXREYXRhYmFzZSgpLmdyYW50Q29ubmVjdChvdGhlckxhbWJkYSk7XG4gKi9cblxuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IHtcbiAgQ29kZSxcbiAgUnVudGltZSxcbiAgQXJjaGl0ZWN0dXJlLFxuICBGdW5jdGlvblVybEF1dGhUeXBlLFxuICB0eXBlIElGdW5jdGlvblxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYVwiO1xuaW1wb3J0IHtcbiAgQ2VydGlmaWNhdGUsXG4gIENlcnRpZmljYXRlVmFsaWRhdGlvbixcbiAgdHlwZSBJQ2VydGlmaWNhdGVcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jZXJ0aWZpY2F0ZW1hbmFnZXJcIjtcbmltcG9ydCB7IEhvc3RlZFpvbmUsIEFSZWNvcmQsIFJlY29yZFRhcmdldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtcm91dGU1M1wiO1xuaW1wb3J0IHsgQ2xvdWRGcm9udFRhcmdldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtcm91dGU1My10YXJnZXRzXCI7XG5cbmltcG9ydCB0eXBlIEFwcCBmcm9tIFwiLi4vLi4vYXBwLmpzXCI7XG5pbXBvcnQgeyB0eXBlIElQYXlsb2FkUHJvcHMsIHR5cGUgSVBheWxvYWQgfSBmcm9tIFwiLi9pbnRlcmZhY2VzL3BhdHRlcm4uanNcIjtcbmltcG9ydCB7IHR5cGUgTWFuaWZlc3RQYXR0ZXJuIH0gZnJvbSBcIi4uLy4uL3V0aWxzL21hbmlmZXN0V3JpdGVyLmpzXCI7XG5pbXBvcnQge1xuICB0eXBlIFJlbGF0aW9uYWxEYXRhYmFzZSxcbiAgdHlwZSBEeW5hbW9EQkRhdGFiYXNlLFxuICBEYXRhYmFzZUZhY3RvcnksXG4gIHR5cGUgQXVyb3JhRGF0YWJhc2VQcm9wcyxcbiAgdHlwZSBJbnN0YW5jZURhdGFiYXNlUHJvcHMsXG4gIHR5cGUgRHluYW1vREJEYXRhYmFzZVByb3BzXG59IGZyb20gXCIuL2RhdGFiYXNlLmpzXCI7XG5pbXBvcnQge1xuICBDb21wdXRlRmFjdG9yeSxcbiAgdHlwZSBMYW1iZGFDb21wdXRlLFxuICBJbnZva2VNb2RlLFxuICB0eXBlIENvZGVMYW1iZGFQcm9wc1xufSBmcm9tIFwiLi9jb21wdXRlLmpzXCI7XG5pbXBvcnQge1xuICBTdG9yYWdlRmFjdG9yeSxcbiAgdHlwZSBQcml2YXRlU3RvcmFnZSxcbiAgdHlwZSBQcml2YXRlUzNQcm9wc1xufSBmcm9tIFwiLi9zdG9yYWdlLmpzXCI7XG5pbXBvcnQge1xuICBNZXNzYWdpbmdGYWN0b3J5LFxuICB0eXBlIFF1ZXVlTWVzc2FnaW5nLFxuICB0eXBlIElRdWV1ZVByb3BzXG59IGZyb20gXCIuL21lc3NhZ2luZy5qc1wiO1xuaW1wb3J0IHsgQ2RuRmFjdG9yeSwgdHlwZSBDZG4sIHR5cGUgU21hcnRDZG5Qcm9wcyB9IGZyb20gXCIuL2Nkbi5qc1wiO1xuaW1wb3J0IHsgRmphbGxMb2dnZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHMvdmFsaWRhdGlvbkxvZ2dlci5qc1wiO1xuXG5jb25zdCBQQVlMT0FEX0RFRkFVTFRTID0ge1xuICAvKiogUGF0aCB0byBPcGVuTmV4dCBvdXRwdXQgcmVsYXRpdmUgdG8gYXBwIGZvbGRlciAoQ0RLIHJ1bnMgZnJvbSBmamFsbC88YXBwbmFtZT4pICovXG4gIFNPVVJDRTogXCIuLi8uLlwiLFxuICBEQVRBQkFTRToge1xuICAgIFRZUEU6IFwiSW5zdGFuY2VcIiBhcyBjb25zdCxcbiAgICBCQUNLVVBfUkVURU5USU9OOiA3LFxuICAgIERFTEVUSU9OX1BST1RFQ1RJT046IHRydWVcbiAgfSxcbiAgQ09NUFVURToge1xuICAgIFNFUlZFUl9NRU1PUlk6IDE1MzYsXG4gICAgU0VSVkVSX1RJTUVPVVQ6IDMwLFxuICAgIElNQUdFX01FTU9SWTogMTUzNixcbiAgICBJTUFHRV9USU1FT1VUOiAzMCxcbiAgICBSRVZBTElEQVRJT05fTUVNT1JZOiA3NjgsXG4gICAgUkVWQUxJREFUSU9OX1RJTUVPVVQ6IDMwMFxuICB9LFxuICBDQUNIRToge1xuICAgIE1BWF9BR0VfU0VDT05EUzogMzE1MzYwMDAgLy8gMSB5ZWFyXG4gIH0sXG4gIFBBVEhTOiB7XG4gICAgU1RBVElDOiBcIi9fbmV4dC9zdGF0aWMvKlwiLFxuICAgIElNQUdFOiBcIi9fbmV4dC9pbWFnZSpcIixcbiAgICBBUEk6IFwiL2FwaS8qXCIsXG4gICAgQURNSU46IFwiL2FkbWluLypcIlxuICB9XG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIENvbnZlcnQgYSBuYW1lIHRvIGEgdmFsaWQgZGF0YWJhc2UgbmFtZSAoc25ha2VfY2FzZSwgYWxwaGFudW1lcmljIG9ubHkpLlxuICovXG5mdW5jdGlvbiB0b1ZhbGlkRGF0YWJhc2VOYW1lKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuYW1lXG4gICAgLnRvTG93ZXJDYXNlKClcbiAgICAucmVwbGFjZSgvLS9nLCBcIl9cIilcbiAgICAucmVwbGFjZSgvW15hLXowLTlfXS9nLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgbmFtZSB0byBQYXNjYWxDYXNlIGZvciBjb25zdHJ1Y3QgSURzLlxuICovXG5mdW5jdGlvbiB0b1Bhc2NhbENhc2UobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5hbWVcbiAgICAucmVwbGFjZSgvWy1fXSguKS9nLCAoXywgYykgPT4gYy50b1VwcGVyQ2FzZSgpKVxuICAgIC5yZXBsYWNlKC9eLi8sIChjKSA9PiBjLnRvVXBwZXJDYXNlKCkpO1xufVxuXG4vKipcbiAqIEV4dHJhY3Qgcm9vdCBkb21haW4gZnJvbSBhIGZ1bGwgZG9tYWluIG5hbWUuXG4gKiBlLmcuLCBcImNtcy5leGFtcGxlLmNvbVwiIC0+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==