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