cdk-nextjs 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/.jsii +2467 -2714
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1725 -1909
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +687 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1548 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +852 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +861 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  88. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  92. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  93. package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
  94. package/lib/lambdas/post-deploy/prune-s3.js +54 -15
  95. package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
  96. package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  103. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  104. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  105. package/lib/nextjs-api.d.ts +107 -18
  106. package/lib/nextjs-api.js +349 -39
  107. package/lib/nextjs-api.test.js +582 -1
  108. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  109. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  110. package/lib/nextjs-build/nextjs-build.js +684 -327
  111. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  112. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  113. package/lib/nextjs-build/patch-fetch.js +1 -1
  114. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  115. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  116. package/lib/nextjs-cache.d.ts +82 -4
  117. package/lib/nextjs-cache.js +186 -10
  118. package/lib/nextjs-cache.test.js +176 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  120. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  121. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  122. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  123. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  124. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  125. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  126. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  127. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  128. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  129. package/lib/nextjs-distribution.d.ts +194 -23
  130. package/lib/nextjs-distribution.js +535 -62
  131. package/lib/nextjs-distribution.test.d.ts +1 -0
  132. package/lib/nextjs-distribution.test.js +697 -0
  133. package/lib/nextjs-post-deploy.d.ts +23 -3
  134. package/lib/nextjs-post-deploy.js +14 -10
  135. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  136. package/lib/nextjs-post-deploy.test.js +34 -0
  137. package/lib/nextjs-static-assets.d.ts +23 -4
  138. package/lib/nextjs-static-assets.js +29 -6
  139. package/lib/nextjs-static-assets.test.js +20 -1
  140. package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
  141. package/lib/root-constructs/nextjs-base-construct.js +144 -34
  142. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  143. package/lib/root-constructs/nextjs-global-containers.js +20 -70
  144. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  145. package/lib/root-constructs/nextjs-global-functions.js +52 -69
  146. package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
  147. package/lib/root-constructs/nextjs-regional-containers.js +17 -15
  148. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  149. package/lib/root-constructs/nextjs-regional-functions.js +8 -25
  150. package/lib/runtime/api-gateway-path.d.ts +34 -0
  151. package/lib/runtime/api-gateway-path.js +71 -0
  152. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  153. package/lib/runtime/api-gateway-path.test.js +65 -0
  154. package/lib/runtime/case-redirect.d.ts +22 -0
  155. package/lib/runtime/case-redirect.js +63 -0
  156. package/lib/runtime/case-redirect.test.d.ts +1 -0
  157. package/lib/runtime/case-redirect.test.js +32 -0
  158. package/lib/runtime/core.d.ts +234 -0
  159. package/lib/runtime/core.js +1213 -0
  160. package/lib/runtime/core.test.d.ts +1 -0
  161. package/lib/runtime/core.test.js +1678 -0
  162. package/lib/runtime/deployment-root.d.ts +13 -0
  163. package/lib/runtime/deployment-root.js +29 -0
  164. package/lib/runtime/dispatch.d.ts +331 -0
  165. package/lib/runtime/dispatch.js +751 -0
  166. package/lib/runtime/dispatch.test.d.ts +1 -0
  167. package/lib/runtime/dispatch.test.js +853 -0
  168. package/lib/runtime/entrypoints.d.ts +57 -0
  169. package/lib/runtime/entrypoints.js +115 -0
  170. package/lib/runtime/http/abort-signal.d.ts +6 -0
  171. package/lib/runtime/http/abort-signal.js +19 -0
  172. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  173. package/lib/runtime/http/abort-signal.test.js +49 -0
  174. package/lib/runtime/http/node-server.d.ts +38 -0
  175. package/lib/runtime/http/node-server.js +99 -0
  176. package/lib/runtime/http/node-server.test.d.ts +1 -0
  177. package/lib/runtime/http/node-server.test.js +96 -0
  178. package/lib/runtime/http/node-sink.d.ts +16 -0
  179. package/lib/runtime/http/node-sink.js +48 -0
  180. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  181. package/lib/runtime/http/node-sink.test.js +66 -0
  182. package/lib/runtime/http/request.d.ts +62 -0
  183. package/lib/runtime/http/request.js +134 -0
  184. package/lib/runtime/http/request.test.d.ts +1 -0
  185. package/lib/runtime/http/request.test.js +103 -0
  186. package/lib/runtime/http/response.d.ts +77 -0
  187. package/lib/runtime/http/response.js +229 -0
  188. package/lib/runtime/http/response.test.d.ts +1 -0
  189. package/lib/runtime/http/response.test.js +178 -0
  190. package/lib/runtime/http/sink.d.ts +73 -0
  191. package/lib/runtime/http/sink.js +188 -0
  192. package/lib/runtime/http/sink.test.d.ts +1 -0
  193. package/lib/runtime/http/sink.test.js +257 -0
  194. package/lib/runtime/image-utils.d.ts +78 -0
  195. package/lib/runtime/image-utils.js +129 -0
  196. package/lib/runtime/image-utils.test.d.ts +1 -0
  197. package/lib/runtime/image-utils.test.js +237 -0
  198. package/lib/runtime/image.d.ts +76 -0
  199. package/lib/runtime/image.js +296 -0
  200. package/lib/runtime/image.test.d.ts +1 -0
  201. package/lib/runtime/image.test.js +405 -0
  202. package/lib/runtime/lambda-event.d.ts +4 -0
  203. package/lib/runtime/lambda-event.js +113 -0
  204. package/lib/runtime/lambda-event.test.d.ts +1 -0
  205. package/lib/runtime/lambda-event.test.js +119 -0
  206. package/lib/runtime/lambda.mjs +41595 -0
  207. package/lib/runtime/load-module.d.ts +8 -0
  208. package/lib/runtime/load-module.js +35 -0
  209. package/lib/runtime/manifest.d.ts +215 -0
  210. package/lib/runtime/manifest.js +118 -0
  211. package/lib/runtime/middleware.d.ts +43 -0
  212. package/lib/runtime/middleware.js +113 -0
  213. package/lib/runtime/middleware.test.d.ts +1 -0
  214. package/lib/runtime/middleware.test.js +259 -0
  215. package/lib/runtime/next-modules.d.ts +55 -0
  216. package/lib/runtime/next-modules.js +124 -0
  217. package/lib/runtime/next-modules.test.d.ts +1 -0
  218. package/lib/runtime/next-modules.test.js +34 -0
  219. package/lib/runtime/public-files.d.ts +32 -0
  220. package/lib/runtime/public-files.js +117 -0
  221. package/lib/runtime/public-files.test.d.ts +1 -0
  222. package/lib/runtime/public-files.test.js +97 -0
  223. package/lib/runtime/server.mjs +41588 -0
  224. package/lib/runtime/static-files.d.ts +50 -0
  225. package/lib/runtime/static-files.js +266 -0
  226. package/lib/runtime/static-files.test.d.ts +1 -0
  227. package/lib/runtime/static-files.test.js +118 -0
  228. package/lib/runtime/util.d.ts +28 -0
  229. package/lib/runtime/util.js +79 -0
  230. package/lib/utils/base-path.d.ts +123 -11
  231. package/lib/utils/base-path.js +276 -39
  232. package/lib/utils/base-path.test.js +275 -50
  233. package/lib/utils/get-architecture.d.ts +7 -8
  234. package/lib/utils/get-architecture.js +12 -13
  235. package/lib/utils/zip-directory.d.ts +14 -0
  236. package/lib/utils/zip-directory.js +121 -0
  237. package/lib/utils/zip-directory.test.d.ts +1 -0
  238. package/lib/utils/zip-directory.test.js +99 -0
  239. package/package.json +22 -3
  240. package/scripts/capture-adapter-fixture.mjs +325 -0
  241. package/scripts/e2e-deploy.sh +398 -0
  242. package/scripts/e2e-harness/README.md +707 -0
  243. package/scripts/e2e-harness/app.js +370 -0
  244. package/scripts/e2e-harness/common.sh +249 -0
  245. package/scripts/e2e-harness/screen.mjs +302 -0
  246. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  247. package/scripts/e2e-harness/type-filters.mjs +47 -0
  248. package/scripts/e2e-logs.sh +75 -0
  249. package/scripts/e2e-offline.sh +91 -0
  250. package/scripts/e2e-sweep.sh +370 -0
  251. package/scripts/e2e-warm.sh +114 -0
  252. package/scripts/zero-config-build.mjs +418 -0
  253. package/docs/1k-concurrent-users-executions.png +0 -0
  254. package/docs/plans/adapter-runtime-release.md +0 -362
  255. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  256. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  257. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  258. package/lib/image-optimization/handler-utils.d.ts +0 -34
  259. package/lib/image-optimization/handler-utils.js +0 -83
  260. package/lib/image-optimization/handler-utils.test.js +0 -178
  261. package/lib/nextjs-build/functions.Dockerfile +0 -31
  262. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  263. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  264. package/lib/utils/experimental-flags.d.ts +0 -24
  265. package/lib/utils/experimental-flags.js +0 -30
  266. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
package/lib/nextjs-api.js CHANGED
@@ -2,16 +2,27 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NextjsApi = void 0;
4
4
  const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
5
+ const node_path_1 = require("node:path");
5
6
  const aws_cdk_lib_1 = require("aws-cdk-lib");
6
7
  const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
8
+ const aws_events_1 = require("aws-cdk-lib/aws-events");
9
+ const aws_events_targets_1 = require("aws-cdk-lib/aws-events-targets");
7
10
  const aws_iam_1 = require("aws-cdk-lib/aws-iam");
11
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
8
12
  const constructs_1 = require("constructs");
13
+ const constants_1 = require("./constants");
14
+ const nextjs_static_assets_1 = require("./nextjs-static-assets");
9
15
  const base_path_1 = require("./utils/base-path");
16
+ /**
17
+ * What API Gateway accepts as a resource path part, per CDK's own check in
18
+ * `Resource`: `[a-zA-Z0-9:._-$]`, plus an optional trailing `+`.
19
+ */
20
+ const API_PATH_PART = /^[a-zA-Z0-9:._\-$]+$/;
10
21
  /**
11
22
  * Creates an API Gateway REST API for Next.js applications
12
23
  */
13
24
  class NextjsApi extends constructs_1.Construct {
14
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsApi", version: "0.6.1" };
25
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsApi", version: "0.7.0" };
15
26
  /**
16
27
  * The API Gateway REST API
17
28
  */
@@ -40,8 +51,26 @@ class NextjsApi extends constructs_1.Construct {
40
51
  ];
41
52
  return (0, base_path_1.joinPath)(origin, prefix, this.props.basePath);
42
53
  }
54
+ /**
55
+ * Deploys the stage again after each stack update.
56
+ * @see NextjsApiProps.redeployAfterUpdate
57
+ */
58
+ redeployFunction;
59
+ /**
60
+ * Matches this stack's `UPDATE_COMPLETE` and `UPDATE_ROLLBACK_COMPLETE` and
61
+ * invokes {@link redeployFunction}.
62
+ */
63
+ redeployRule;
43
64
  baseResource;
44
65
  nextResource;
66
+ /**
67
+ * Resources created only as parents of a group route, and their paths. API
68
+ * Gateway answers a request for a resource with no method itself — 403
69
+ * "Missing Authentication Token" — rather than falling back to a `{proxy+}`
70
+ * higher up, so each needs one. Without it a `/api/reports/**` group turned
71
+ * `/api/reports` and `/api` into 403s.
72
+ */
73
+ groupParentResources = new Map();
45
74
  props;
46
75
  staticIntegrationRole;
47
76
  constructor(scope, id, props) {
@@ -54,16 +83,77 @@ class NextjsApi extends constructs_1.Construct {
54
83
  this.staticIntegrationRole = this.createStaticIntegrationRole();
55
84
  this.createStaticIntegrations();
56
85
  if (props.serverFunction) {
57
- // Without a dedicated image function, `_next/image` falls through to the
58
- // `{proxy+}` catch-all on the server function.
59
- if (props.imageFunction) {
60
- this.createImageIntegration(props.imageFunction);
61
- }
86
+ // Group resources before the catch-all, so `addResource` sees a clean tree
87
+ // and a group can claim a path the catch-all would otherwise serve.
88
+ this.createFunctionGroupIntegrations();
89
+ // `_next/image` has no resource of its own: it falls through to the
90
+ // `{proxy+}` catch-all, and the server function optimizes in-process.
62
91
  this.createDynamicIntegration(props.serverFunction);
63
92
  }
64
93
  else if (props.vpc) {
65
94
  // [Future] create integration with ECS via VPC Link and ECS Service Discovery
66
95
  }
96
+ if (props.redeployAfterUpdate !== false &&
97
+ props.overrides?.restApiProps?.deploy !== false) {
98
+ [this.redeployFunction, this.redeployRule] = this.createRedeploy();
99
+ }
100
+ }
101
+ /** @see NextjsApiProps.redeployAfterUpdate */
102
+ createRedeploy() {
103
+ const stack = aws_cdk_lib_1.Stack.of(this);
104
+ const { restApiId } = this.api;
105
+ const { stageName } = this.api.deploymentStage;
106
+ const fn = new aws_lambda_1.Function(this, "RedeployFn", {
107
+ // Plain bundled JS with no native dependencies: always arm64.
108
+ architecture: aws_lambda_1.Architecture.ARM_64,
109
+ code: aws_lambda_1.Code.fromAsset((0, node_path_1.join)(__dirname, "../assets/lambdas/redeploy-stage/redeploy-stage.lambda")),
110
+ handler: "index.handler",
111
+ memorySize: 256,
112
+ runtime: new aws_lambda_1.Runtime("nodejs24.x", aws_lambda_1.RuntimeFamily.NODEJS),
113
+ timeout: aws_cdk_lib_1.Duration.minutes(1),
114
+ ...this.props.overrides?.redeployFunctionProps,
115
+ environment: {
116
+ ...this.props.overrides?.redeployFunctionProps?.environment,
117
+ REST_API_ID: restApiId,
118
+ STAGE_NAME: stageName,
119
+ },
120
+ });
121
+ // API Gateway authorizes its management API by HTTP verb on the resource
122
+ // path; these are the four calls `redeployStage` makes, on this API only.
123
+ const restApi = `arn:${stack.partition}:apigateway:${stack.region}::/restapis/${restApiId}`;
124
+ fn.addToRolePolicy(new aws_iam_1.PolicyStatement({
125
+ actions: ["apigateway:POST"],
126
+ resources: [`${restApi}/deployments`],
127
+ }));
128
+ fn.addToRolePolicy(new aws_iam_1.PolicyStatement({
129
+ actions: ["apigateway:GET"],
130
+ resources: [`${restApi}/deployments`, `${restApi}/stages`],
131
+ }));
132
+ fn.addToRolePolicy(new aws_iam_1.PolicyStatement({
133
+ actions: ["apigateway:DELETE"],
134
+ resources: [`${restApi}/deployments/*`],
135
+ }));
136
+ // CloudFormation sends every stack status change to the default event bus
137
+ // ("Monitoring CloudFormation ... events with EventBridge" in the
138
+ // CloudFormation User Guide). `UPDATE_COMPLETE` comes after
139
+ // `UPDATE_COMPLETE_CLEANUP_IN_PROGRESS`, so removed resources are gone by
140
+ // then. A rollback restores the stage to the pre-update deployment, which
141
+ // can carry the same staleness from an earlier update, so it redeploys too.
142
+ const rule = new aws_events_1.Rule(this, "RedeployRule", {
143
+ description: `Redeploys ${stack.stackName}'s REST API stage after a stack update`,
144
+ eventPattern: {
145
+ source: ["aws.cloudformation"],
146
+ detailType: ["CloudFormation Stack Status Change"],
147
+ detail: {
148
+ "stack-id": [stack.stackId],
149
+ "status-details": {
150
+ status: ["UPDATE_COMPLETE", "UPDATE_ROLLBACK_COMPLETE"],
151
+ },
152
+ },
153
+ },
154
+ targets: [new aws_events_targets_1.LambdaFunction(fn, { retryAttempts: 2 })],
155
+ });
156
+ return [fn, rule];
67
157
  }
68
158
  validateProps(props) {
69
159
  if (!props.serverFunction && !props.vpc) {
@@ -75,30 +165,53 @@ class NextjsApi extends constructs_1.Construct {
75
165
  binaryMediaTypes: ["*/*"],
76
166
  description: `cdk-nextjs REST API for ${aws_cdk_lib_1.Stack.of(this).stackName}`,
77
167
  endpointTypes: [aws_apigateway_1.EndpointType.REGIONAL],
78
- minCompressionSize: aws_cdk_lib_1.Size.bytes(0), // compress all responses for better perf
168
+ // Inert for the dynamic routes: API Gateway does not compress a response it
169
+ // streams (`ResponseTransferMode.STREAM`), which every Lambda integration
170
+ // here uses, so the runtime gzips those itself. Kept because it still
171
+ // applies to the buffered S3 static integrations, and because a consumer
172
+ // who overrides an integration to BUFFERED gets compression back.
173
+ minCompressionSize: aws_cdk_lib_1.Size.bytes(0),
79
174
  ...this.props.overrides?.restApiProps,
80
175
  });
81
176
  }
82
177
  /**
83
178
  * Create base resource path if needed. Important if `basePath` is set.
179
+ *
180
+ * A nested `basePath` ("/team/app") has to become one resource per segment:
181
+ * API Gateway path parts can't contain "/", so passing the whole thing to a
182
+ * single `addResource` fails validation at synth. `resolveBasePath` accepts
183
+ * nested values, so this is reachable.
84
184
  */
85
185
  createBaseResource(basePath) {
86
186
  // Create base resource path if needed
87
187
  const normalized = (0, base_path_1.normalizeBasePath)(basePath);
88
- return normalized ? this.api.root.addResource(normalized) : this.api.root;
188
+ if (!normalized) {
189
+ return this.api.root;
190
+ }
191
+ return normalized
192
+ .split("/")
193
+ .reduce((parent, segment) => parent.addResource(segment), this.api.root);
89
194
  }
90
195
  createStaticIntegrationRole() {
91
196
  // Create S3 integration role
92
197
  const staticIntegrationRole = new aws_iam_1.Role(this, "StaticIntegrationRole", {
93
198
  assumedBy: new aws_iam_1.ServicePrincipal("apigateway.amazonaws.com"),
94
199
  });
200
+ // Only this app's own objects: a shared bucket holds other apps' assets
201
+ // under their own prefixes. `s3:ListBucket` makes a missing key a 404 (the
202
+ // only error the integration maps) rather than a 403. It stays unconditioned:
203
+ // S3 checks it during a GetObject, where no `s3:prefix` is present, so a
204
+ // prefix condition would turn every missing key back into a 403.
95
205
  staticIntegrationRole.addToPolicy(new aws_iam_1.PolicyStatement({
96
- actions: ["s3:GetObject", "s3:ListBucket"],
206
+ actions: ["s3:GetObject"],
97
207
  resources: [
98
- this.props.staticAssetsBucket.bucketArn,
99
- `${this.props.staticAssetsBucket.bucketArn}/*`,
208
+ `${this.props.staticAssetsBucket.bucketArn}/${(0, nextjs_static_assets_1.staticAssetsObjectsPattern)(this.props.staticAssetsKeyPrefix)}`,
100
209
  ],
101
210
  }));
211
+ staticIntegrationRole.addToPolicy(new aws_iam_1.PolicyStatement({
212
+ actions: ["s3:ListBucket"],
213
+ resources: [this.props.staticAssetsBucket.bucketArn],
214
+ }));
102
215
  return staticIntegrationRole;
103
216
  }
104
217
  createStaticIntegrations() {
@@ -107,7 +220,17 @@ class NextjsApi extends constructs_1.Construct {
107
220
  .addResource("{proxy+}")
108
221
  .addMethod("GET", this.createS3Integration({ key: this.s3Key("_next/static/{key}") }), this.getStaticMethodOptions({ proxy: true }));
109
222
  // add public directory files/directories that exist at top level but need to go to S3.
223
+ const unroutable = [];
110
224
  for (const publicDirEntry of this.props.publicDirEntries) {
225
+ // A space or a non-ASCII character is legal in `public/` and illegal in an
226
+ // API Gateway resource path part, and `addResource` throws — which took the
227
+ // whole synth down for an app that deploys fine on the Global types
228
+ // (`next-image-legacy/unicode`, whose `public/` holds "hello world.jpg").
229
+ // Warn and skip the one entry instead: that asset 404s, the app deploys.
230
+ if (!API_PATH_PART.test(publicDirEntry.name)) {
231
+ unroutable.push(`"${publicDirEntry.name}"`);
232
+ continue;
233
+ }
111
234
  if (publicDirEntry.isDirectory) {
112
235
  this.baseResource
113
236
  .addResource(publicDirEntry.name)
@@ -122,6 +245,15 @@ class NextjsApi extends constructs_1.Construct {
122
245
  .addMethod("GET", this.createS3Integration({ key: this.s3Key(publicDirEntry.name) }), this.getStaticMethodOptions());
123
246
  }
124
247
  }
248
+ if (unroutable.length > 0) {
249
+ aws_cdk_lib_1.Annotations.of(this).addWarning(`${constants_1.LOG_PREFIX} An API Gateway resource path part only allows ` +
250
+ "[a-zA-Z0-9:._-$], so these top-level public/ entries get no resource of " +
251
+ "their own; their requests reach the server function, which reads them " +
252
+ `from S3 instead: ${unroutable.join(", ")}. To serve them directly, rename them, move them into a ` +
253
+ "public/ subdirectory whose own name is expressible, or use " +
254
+ "NextjsGlobalFunctions or NextjsGlobalContainers, whose CloudFront " +
255
+ "behaviors can match them.");
256
+ }
125
257
  }
126
258
  /**
127
259
  * Prefixes a request path with the key prefix the assets were uploaded under,
@@ -143,11 +275,18 @@ class NextjsApi extends constructs_1.Construct {
143
275
  options: {
144
276
  credentialsRole: this.staticIntegrationRole,
145
277
  passthroughBehavior: aws_apigateway_1.PassthroughBehavior.WHEN_NO_TEMPLATES, // recommended
146
- requestParameters: key.includes("{key}")
147
- ? {
148
- "integration.request.path.key": "method.request.path.proxy",
149
- }
150
- : undefined,
278
+ requestParameters: {
279
+ // Without this S3 never sees the conditional request, so every
280
+ // revalidation of an immutable `_next/static` chunk re-downloads it
281
+ // with a 200 instead of getting a 304.
282
+ "integration.request.header.If-None-Match": "method.request.header.If-None-Match",
283
+ "integration.request.header.If-Modified-Since": "method.request.header.If-Modified-Since",
284
+ ...(key.includes("{key}")
285
+ ? {
286
+ "integration.request.path.key": "method.request.path.proxy",
287
+ }
288
+ : {}),
289
+ },
151
290
  integrationResponses: [
152
291
  {
153
292
  statusCode: "200",
@@ -159,6 +298,17 @@ class NextjsApi extends constructs_1.Construct {
159
298
  "method.response.header.Last-Modified": "integration.response.header.Last-Modified",
160
299
  },
161
300
  },
301
+ {
302
+ // A 304 carries no body, and `ETag` is the header a client needs
303
+ // back to keep revalidating.
304
+ statusCode: "304",
305
+ selectionPattern: "304",
306
+ responseParameters: {
307
+ "method.response.header.Cache-Control": "integration.response.header.Cache-Control",
308
+ "method.response.header.ETag": "integration.response.header.ETag",
309
+ "method.response.header.Last-Modified": "integration.response.header.Last-Modified",
310
+ },
311
+ },
162
312
  {
163
313
  statusCode: "404",
164
314
  selectionPattern: "404",
@@ -171,11 +321,13 @@ class NextjsApi extends constructs_1.Construct {
171
321
  }
172
322
  getStaticMethodOptions({ proxy } = { proxy: false }) {
173
323
  return {
174
- requestParameters: proxy
175
- ? {
176
- "method.request.path.proxy": true,
177
- }
178
- : undefined,
324
+ requestParameters: {
325
+ // Declared optional (`false`): a plain GET carries neither, and
326
+ // requiring them would 400 it.
327
+ "method.request.header.If-None-Match": false,
328
+ "method.request.header.If-Modified-Since": false,
329
+ ...(proxy ? { "method.request.path.proxy": true } : {}),
330
+ },
179
331
  methodResponses: [
180
332
  {
181
333
  statusCode: "200",
@@ -187,6 +339,14 @@ class NextjsApi extends constructs_1.Construct {
187
339
  "method.response.header.Last-Modified": true,
188
340
  },
189
341
  },
342
+ {
343
+ statusCode: "304",
344
+ responseParameters: {
345
+ "method.response.header.Cache-Control": true,
346
+ "method.response.header.ETag": true,
347
+ "method.response.header.Last-Modified": true,
348
+ },
349
+ },
190
350
  {
191
351
  statusCode: "404",
192
352
  },
@@ -195,38 +355,188 @@ class NextjsApi extends constructs_1.Construct {
195
355
  };
196
356
  }
197
357
  /**
198
- * Create Lambda Proxy integration for the `_next/image` route.
358
+ * One resource subtree per function group pattern.
359
+ *
360
+ * Unlike CloudFront this needs no ordering: API Gateway matches on a resource
361
+ * *tree*, so `/api/reports/{proxy+}` beats `/api/{proxy+}` beats `/{proxy+}`
362
+ * structurally, and "longest pattern wins" comes for free. What does need care
363
+ * is not creating the same path twice — two groups under `/api` share the `api`
364
+ * resource — so every segment goes through {@link resourceFor}.
199
365
  */
200
- createImageIntegration(imageFunction) {
201
- // imageFunction is assumed to be the dedicated, streaming-capable image
202
- // Lambda (see its doc comment); override responseTransferMode via
203
- // imageIntegrationProps if that assumption doesn't hold for a custom
204
- // imageFunction, otherwise API Gateway returns a 502. Deliberately
205
- // doesn't inherit dynamicIntegrationProps: that's for serverFunction,
206
- // a different Lambda with different (and possibly conflicting, e.g.
207
- // BUFFERED for a non-streaming Lambda Web Adapter setup) streaming
208
- // requirements than the always-streaming dedicated image Lambda.
209
- const imageIntegration = new aws_apigateway_1.LambdaIntegration(imageFunction, {
210
- responseTransferMode: aws_apigateway_1.ResponseTransferMode.STREAM,
211
- ...this.props.overrides?.imageIntegrationProps,
212
- });
213
- const imageResource = this.nextResource.addResource("image");
214
- imageResource.addMethod("ANY", imageIntegration);
366
+ createFunctionGroupIntegrations() {
367
+ const groups = this.props.functionGroups ?? [];
368
+ const behaviors = this.props.functionGroupBehaviors ?? [];
369
+ const unknown = behaviors.find((behavior) => !groups.some((group) => group.name === behavior.group));
370
+ if (unknown) {
371
+ throw new Error(`${constants_1.LOG_PREFIX} \`functionGroupBehaviors\` routes to function group ` +
372
+ `"${unknown.group}", which is not in \`functionGroups\`.`);
373
+ }
374
+ const routeResources = new Set();
375
+ /** Each subtree's base path and the integration its `{proxy+}` got. */
376
+ const subtrees = [];
377
+ for (const group of groups) {
378
+ const integration = new aws_apigateway_1.LambdaIntegration(group.function, {
379
+ responseTransferMode: aws_apigateway_1.ResponseTransferMode.STREAM,
380
+ // One API-wide permission per function; see `createDynamicIntegration`.
381
+ scopePermissionToMethod: false,
382
+ ...this.props.overrides?.dynamicIntegrationProps,
383
+ });
384
+ // The CloudFront patterns are for the edge; a resource path per route
385
+ // covers what they do here, a `trailingSlash` form included, since API
386
+ // Gateway matches `/pricing/` on the `pricing` resource.
387
+ const own = behaviors.filter((behavior) => behavior.group === group.name);
388
+ const hasDataRoutes = own.some(({ pattern }) => pattern.startsWith("_next/data/"));
389
+ for (const route of new Set(own.map((behavior) => behavior.route))) {
390
+ this.assertRoutable(route, group.name);
391
+ this.assertNoPublicCollision(route, group.name);
392
+ for (const path of this.resourcePathsFor(route, hasDataRoutes)) {
393
+ const resource = this.resourceFor(path);
394
+ resource.addMethod("ANY", integration);
395
+ routeResources.add(resource);
396
+ if (path[path.length - 1] === "{proxy+}") {
397
+ subtrees.push([path.slice(0, -1), integration]);
398
+ }
399
+ }
400
+ }
401
+ }
402
+ // A parent under another group's subtree belongs to that group, as it does
403
+ // at the edge and in `assignRoutesToGroups`: with `/api/**` and
404
+ // `/api/reports/**`, `/api/reports` is the `api` group's. The deepest
405
+ // covering subtree wins; the rest are left to the default function.
406
+ for (const [resource, path] of this.groupParentResources) {
407
+ if (routeResources.has(resource)) {
408
+ this.groupParentResources.delete(resource);
409
+ continue;
410
+ }
411
+ const owner = subtrees
412
+ .filter(([base]) => base.length < path.length &&
413
+ base.every((segment, i) => segment === path[i]))
414
+ .sort(([a], [b]) => b.length - a.length)[0];
415
+ if (owner) {
416
+ resource.addMethod("ANY", owner[1]);
417
+ this.groupParentResources.delete(resource);
418
+ }
419
+ }
420
+ }
421
+ /**
422
+ * The group pattern validation accepts every character a CloudFront path
423
+ * pattern can hold, and API Gateway's path parts hold fewer: `~`, `@`, `+`,
424
+ * `&` and quotes pass it and then fail `addResource` with an error that names
425
+ * neither the group nor the pattern. Say which, and what to do instead.
426
+ */
427
+ assertRoutable(route, groupName) {
428
+ const segments = (route.endsWith("/**") ? route.slice(0, -3) : route)
429
+ .split("/")
430
+ .filter(Boolean);
431
+ const invalid = segments.find((segment) => !API_PATH_PART.test(segment));
432
+ if (invalid === undefined) {
433
+ return;
434
+ }
435
+ throw new Error(`${constants_1.LOG_PREFIX} functionGroups pattern "${route}" (group "${groupName}") ` +
436
+ `has a segment, "${invalid}", that an API Gateway resource path part ` +
437
+ "cannot hold: only [a-zA-Z0-9:._-$] are allowed. Route that path from " +
438
+ "a pattern higher up the tree (e.g. its parent directory with `/**`), " +
439
+ "or use NextjsGlobalFunctions, whose CloudFront behaviors allow it.");
440
+ }
441
+ /**
442
+ * Refuse a group route that shares a resource with a `public/` entry.
443
+ *
444
+ * A public directory `docs` is `docs/{proxy+}` with a `GET` to S3. `/docs/**`
445
+ * adds `ANY` to that same resource, and API Gateway prefers the `GET`, so
446
+ * every page load under the group went to S3; `/docs/guide/**` is a more
447
+ * specific resource instead, and takes `/docs/guide/…` away from the public
448
+ * files. A public file `pricing` and an exact `/pricing` are the same
449
+ * resource the same way. `NextjsDistribution` rejects the CloudFront
450
+ * equivalents.
451
+ */
452
+ assertNoPublicCollision(route, groupName) {
453
+ const isSubtree = route.endsWith("/**");
454
+ const segments = (isSubtree ? route.slice(0, -3) : route)
455
+ .split("/")
456
+ .filter(Boolean);
457
+ const entry = this.props.publicDirEntries.find((it) => it.isDirectory
458
+ ? it.name === segments[0] && (isSubtree || segments.length > 1)
459
+ : !isSubtree && segments.length === 1 && it.name === segments[0]);
460
+ if (!entry) {
461
+ return;
462
+ }
463
+ throw new Error(`${constants_1.LOG_PREFIX} functionGroups pattern "${route}" (group "${groupName}") ` +
464
+ `overlaps the top-level public/ ${entry.isDirectory ? "directory" : "file"} ` +
465
+ `"${entry.name}", which API Gateway serves from S3 on the same ` +
466
+ `resource path, so one of the two would never be reached. Move those ` +
467
+ `public/ files under a directory no route uses, or group a different ` +
468
+ `path.`);
469
+ }
470
+ /**
471
+ * Resource paths, as segment arrays, for one group pattern.
472
+ *
473
+ * A subtree gets `{proxy+}` as its last segment and so owns everything *under*
474
+ * the path but not the path itself, matching both the CloudFront translation and
475
+ * `assignRoutesToGroups`. An exact path gets no proxy segment, which leaves its
476
+ * children falling through to the root `{proxy+}` — also the CloudFront result.
477
+ */
478
+ resourcePathsFor(route, hasDataRoutes) {
479
+ const isSubtree = route.endsWith("/**");
480
+ const base = (isSubtree ? route.slice(0, -3) : route)
481
+ .split("/")
482
+ .filter(Boolean);
483
+ const paths = [isSubtree ? [...base, "{proxy+}"] : base];
484
+ if (hasDataRoutes) {
485
+ // `<buildId>` changes every build, so it is a path parameter rather than a
486
+ // literal — the integration ignores it, the runtime reads it off the URL.
487
+ // Unlike CloudFront's `*`, which `NextjsDistribution` had to replace with
488
+ // the literal ID, a path parameter is exactly one segment, so
489
+ // `/_next/data/{buildId}/blog/{proxy+}` cannot capture another group's
490
+ // `/_next/data/<id>/docs/blog/…`. A request for an old build ID reaches
491
+ // the group, which 404s it just as the default function would.
492
+ const dataPrefix = ["_next", "data", "{buildId}"];
493
+ paths.push(isSubtree
494
+ ? [...dataPrefix, ...base, "{proxy+}"]
495
+ : [
496
+ ...dataPrefix,
497
+ ...base.slice(0, -1),
498
+ `${base[base.length - 1]}.json`,
499
+ ]);
500
+ }
501
+ return paths;
502
+ }
503
+ /** Walk or create a resource path, reusing whatever already exists. */
504
+ resourceFor(segments) {
505
+ let resource = this.baseResource;
506
+ for (const [index, segment] of segments.entries()) {
507
+ const existing = resource.getResource(segment);
508
+ resource = existing ?? resource.addResource(segment);
509
+ if (!existing && index < segments.length - 1) {
510
+ this.groupParentResources.set(resource, segments.slice(0, index + 1));
511
+ }
512
+ }
513
+ return resource;
215
514
  }
216
515
  /**
217
516
  * Create Lambda Proxy integration for all other routes
218
517
  */
219
518
  createDynamicIntegration(serverFunction) {
220
- // All other routes use streaming for better performance
519
+ // All other routes use streaming for better performance.
520
+ //
521
+ // `scopePermissionToMethod: false` grants the function one permission for
522
+ // this API's execute-api ARN (`<api>/*/*/*`) instead of two per method (the
523
+ // method and its console test-invoke). Every group adds resources that the
524
+ // default function still answers for its parents and data routes, and at
525
+ // ~350 bytes a statement the per-method policy outgrows Lambda's 20 KB
526
+ // resource-policy cap after a few dozen `ANY` methods, failing the deploy.
221
527
  const streamingIntegration = new aws_apigateway_1.LambdaIntegration(serverFunction, {
222
528
  responseTransferMode: aws_apigateway_1.ResponseTransferMode.STREAM,
529
+ scopePermissionToMethod: false,
223
530
  ...this.props.overrides?.dynamicIntegrationProps,
224
531
  });
225
532
  // Add catch-all routes with streaming integration for server-side rendering
226
533
  this.baseResource.addMethod("ANY", streamingIntegration);
534
+ for (const resource of this.groupParentResources.keys()) {
535
+ resource.addMethod("ANY", streamingIntegration);
536
+ }
227
537
  const proxyResource = this.baseResource.addResource("{proxy+}");
228
538
  proxyResource.addMethod("ANY", streamingIntegration);
229
539
  }
230
540
  }
231
541
  exports.NextjsApi = NextjsApi;
232
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9uZXh0anMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSw2Q0FBMEM7QUFDMUMsK0RBWW9DO0FBRXBDLGlEQUs2QjtBQUc3QiwyQ0FBdUM7QUFFdkMsaURBQWdFO0FBOERoRTs7R0FFRztBQUNILE1BQWEsU0FBVSxTQUFRLHNCQUFTOztJQUN0Qzs7T0FFRztJQUNhLEdBQUcsQ0FBVTtJQUU3Qjs7Ozs7Ozs7T0FRRztJQUNILElBQUksR0FBRztRQUNMLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1FBQ3pDLHdFQUF3RTtRQUN4RSxvRUFBb0U7UUFDcEUsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxZQUFZO1lBQ25DLENBQUMsQ0FBQztnQkFDRSxXQUFXLFlBQVksQ0FBQyxVQUFVLEVBQUU7Z0JBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsUUFBUTthQUN6RDtZQUNILENBQUMsQ0FBQztnQkFDRSxXQUFXLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxnQkFBZ0IsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxnQkFBZ0I7Z0JBQ2xGLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLFNBQVM7YUFDbkMsQ0FBQztRQUNOLE9BQU8sSUFBQSxvQkFBUSxFQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRWdCLFlBQVksQ0FBWTtJQUN4QixZQUFZLENBQVk7SUFDeEIsS0FBSyxDQUFpQjtJQUMvQixxQkFBcUIsQ0FBUTtJQUVyQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXFCO1FBQzdELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFB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QUNLLHdCQUF3QixDQUFDLGNBQXlCO1FBQ3hELHdEQUF3RDtRQUN4RCxNQUFNLG9CQUFvQixHQUFHLElBQUksa0NBQWlCLENBQUMsY0FBYyxFQUFFO1lBQ2pFLG9CQUFvQixFQUFFLHFDQUFvQixDQUFDLE1BQU07WUFDakQsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSx1QkFBdUI7U0FDakQsQ0FBQyxDQUFDO1FBRUgsNEVBQTRFO1FBQzVFLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2hFLGFBQWEsQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLG9CQUFvQixDQUFDLENBQUM7SUFDdkQsQ0FBQzs7QUF2UEgsOEJBd1BDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU2l6ZSwgU3RhY2sgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG4gIFJlc3RBcGksXG4gIExhbWJkYUludGVncmF0aW9uLFxuICBBd3NJbnRlZ3JhdGlvbixcbiAgTWV0aG9kT3B0aW9ucyxcbiAgSVJlc291cmNlLFxuICBFbmRwb2ludFR5cGUsXG4gIFJlc3RBcGlQcm9wcyxcbiAgQXdzSW50ZWdyYXRpb25Qcm9wcyxcbiAgTGFtYmRhSW50ZWdyYXRpb25PcHRpb25zLFxuICBQYXNzdGhyb3VnaEJlaGF2aW9yLFxuICBSZXNwb25zZVRyYW5zZmVyTW9kZSxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1hcGlnYXRld2F5XCI7XG5pbXBvcnQgeyBJVnBjIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1lYzJcIjtcbmltcG9ydCB7XG4gIFJvbGUsXG4gIFNlcnZpY2VQcmluY2lwYWwsXG4gIFBvbGljeVN0YXRlbWVudCxcbiAgSVJvbGUsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgeyBJRnVuY3Rpb24gfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYVwiO1xuaW1wb3J0IHsgSUJ1Y2tldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBQdWJsaWNEaXJFbnRyeSB9IGZyb20gXCIuL25leHRqcy1idWlsZC9uZXh0anMtYnVpbGRcIjtcbmltcG9ydCB7IGpvaW5QYXRoLCBub3JtYWxpemVCYXNlUGF0aCB9IGZyb20gXCIuL3V0aWxzL2Jhc2UtcGF0aFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE5leHRqc0FwaU92ZXJyaWRlcyB7XG4gIHJlYWRvbmx5IHJlc3RBcGlQcm9wcz86IFJlc3RBcGlQcm9wcztcbiAgcmVhZG9ubHkgc3RhdGljSW50ZWdyYXRpb25Qcm9wcz86IEF3c0ludGVncmF0aW9uUHJvcHM7XG4gIHJlYWRvbmx5IHMzTWV0aG9kT3B0aW9ucz86IE1ldGhvZE9wdGlvbnM7XG4gIHJlYWRvbmx5IGR5bmFtaWNJbnRlZ3JhdGlvblByb3BzPzogTGFtYmRhSW50ZWdyYXRpb25PcHRpb25zO1xuICByZWFkb25seSBpbWFnZUludGVncmF0aW9uUHJvcHM/OiBMYW1iZGFJbnRlZ3JhdGlvbk9wdGlvbnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzQXBpUHJvcHMge1xuICAvKipcbiAgICogT3B0aW9uYWwgYmFzZSBwYXRoIGZvciB0aGUgYXBwbGljYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGJhc2VQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogT3ZlcnJpZGUgcHJvcHMgZm9yIGV2ZXJ5IGNvbnN0cnVjdC5cbiAgICovXG4gIHJlYWRvbmx5IG92ZXJyaWRlcz86IE5leHRqc0FwaU92ZXJyaWRlcztcbiAgLyoqXG4gICAqIFBhdGggdG8gZGlyZWN0b3J5IG9mIE5leHQuanMgYXBwJ3MgcHVibGljIGRpcmVjdG9yeS4gVXNlZCB0byBhZGQgcmVzb3VyY2VzXG4gICAqIHRvIEFQSSBHYXRld2F5IFJFU1QgQVBJIGZvciBwdWJsaWMgZGlyZWN0b3J5IHRvIGdvIGRpcmVjdGx5IHRvIFMzLlxuICAgKi9cbiAgcmVhZG9ubHkgcHVibGljRGlyRW50cmllczogUHVibGljRGlyRW50cnlbXTtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNSZWdpb25hbEZ1bmN0aW9uc2AuIFRoZSBMYW1iZGEgZnVuY3Rpb24gZm9yIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xuICAgKi9cbiAgcmVhZG9ubHkgc2VydmVyRnVuY3Rpb24/OiBJRnVuY3Rpb247XG4gIC8qKlxuICAgKiBEZWRpY2F0ZWQgaW1hZ2Ugb3B0aW1pemF0aW9uIExhbWJkYSBmb3IgdGhlIGBfbmV4dC9pbWFnZWAgcm91dGUuIFdoZW5cbiAgICogb21pdHRlZCwgbm8gYF9uZXh0L2ltYWdlYCByZXNvdXJjZSBpcyBjcmVhdGVkIGFuZCB0aG9zZSByZXF1ZXN0cyBmYWxsXG4gICAqIHRocm91Z2ggdG8gYHNlcnZlckZ1bmN0aW9uYCB2aWEgdGhlIGB7cHJveHkrfWAgY2F0Y2gtYWxsLlxuICAgKlxuICAgKiBXaGVuIHByb3ZpZGVkLCBpdCBpcyBhc3N1bWVkIHRvIHN1cHBvcnQgTGFtYmRhIHJlc3BvbnNlIHN0cmVhbWluZyAoYXMgdGhlXG4gICAqIGRlZGljYXRlZCBpbWFnZSBMYW1iZGEgdGhpcyBwYWNrYWdlIGJ1aWxkcyBkb2VzKSBhbmQgaXMgaW52b2tlZCB3aXRoXG4gICAqIGBSZXNwb25zZVRyYW5zZmVyTW9kZS5TVFJFQU1gIGFjY29yZGluZ2x5LiBJZiB5b3Ugc3VwcGx5IGEgY3VzdG9tXG4gICAqIGBpbWFnZUZ1bmN0aW9uYCB0aGF0IGRvZXNuJ3Qgc3VwcG9ydCBzdHJlYW1pbmcsIG92ZXJyaWRlXG4gICAqIGByZXNwb25zZVRyYW5zZmVyTW9kZWAgdG8gYEJVRkZFUkVEYCB2aWEgYG92ZXJyaWRlcy5pbWFnZUludGVncmF0aW9uUHJvcHNgLFxuICAgKiBvdGhlcndpc2UgQVBJIEdhdGV3YXkgcmV0dXJucyBhIDUwMi5cbiAgICovXG4gIHJlYWRvbmx5IGltYWdlRnVuY3Rpb24/OiBJRnVuY3Rpb247XG4gIC8qKlxuICAgKiBUaGUgUzMgYnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0c1xuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzQnVja2V0OiBJQnVja2V0O1xuICAvKipcbiAgICogUzMga2V5IHByZWZpeCB0aGUgc3RhdGljIGFzc2V0cyB3ZXJlIHVwbG9hZGVkIHVuZGVyLCBpLmUuXG4gICAqIGBOZXh0anNTdGF0aWNBc3NldHMua2V5UHJlZml4YCwgd2hpY2ggbmFtZXNwYWNlcyBhIHNoYXJlZCBidWNrZXQuXG4gICAqXG4gICAqIEluZGVwZW5kZW50IG9mIGBiYXNlUGF0aGAgYWJvdmU6IHRoYXQgb25lIGlzIHRoZSBVUkwgcHJlZml4IHRoZSBSRVNUIEFQSVxuICAgKiBzZXJ2ZXMgdGhlIGFwcCBhdCAoY29tbW9ubHkgdGhlIEFQSSBHYXRld2F5IHN0YWdlKSwgd2hpbGUgdGhpcyBvbmUgaXMgd2hlcmVcbiAgICogdGhlIG9iamVjdHMgbGl2ZSBpbiB0aGUgYnVja2V0LiBgX25leHQvc3RhdGljYCBhbmQgcHVibGljIGRpcmVjdG9yeVxuICAgKiByZXF1ZXN0cyBhcmUgbWFwcGVkIHRvIFMzIGtleXMgZGlyZWN0bHksIHNvIHRoZXkgNDA0IHVubGVzcyB0aGlzIHByZWZpeCBpc1xuICAgKiBhcHBsaWVkLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzS2V5UHJlZml4Pzogc3RyaW5nO1xuICAvKipcbiAgICogW0Z1dHVyZV0gUmVxdWlyZWQgaWYgYE5leHRqc1JlZ2lvbmFsQ29udGFpbmVyc2AuIFZQQyB0byBjcmVhdGUgVlBDIExpbmsgYW5kIEVDUyBTZXJ2aWNlIERpc2NvdmVyeVxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogSVZwYztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIEFQSSBHYXRld2F5IFJFU1QgQVBJIGZvciBOZXh0LmpzIGFwcGxpY2F0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgTmV4dGpzQXBpIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFRoZSBBUEkgR2F0ZXdheSBSRVNUIEFQSVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFwaTogUmVzdEFwaTtcblxuICAvKipcbiAgICogUHVibGljIFVSTCBvZiB0aGUgYXBwLCBpbmNsdWRpbmcgZXZlcnkgcGF0aCBzZWdtZW50IHRoZSBBUEkgbmVzdHMgaXQgdW5kZXIuXG4gICAqIFByZWZlcnMgYSBjdXN0b20gZG9tYWluIGNvbmZpZ3VyZWQgdGhyb3VnaCBgb3ZlcnJpZGVzLnJlc3RBcGlQcm9wcy5kb21haW5OYW1lYFxuICAgKiBvdmVyIHRoZSBleGVjdXRlLWFwaSBlbmRwb2ludC5cbiAgICpcbiAgICogQSBkb21haW4gYXR0YWNoZWQgYWZ0ZXIgdGhpcyBjb25zdHJ1Y3QgaXMgY3JlYXRlZCAoYGFwaS5hZGREb21haW5OYW1lKClgKSBpc1xuICAgKiBzdGlsbCB1c2VkIGZvciB0aGUgaG9zdCwgYnV0IENESyBrZWVwcyBpdHMgYmFzZSBwYXRoIG1hcHBpbmdzIHByaXZhdGUsIHNvIGFcbiAgICogbWFwcGluZyBhZGRlZCB0aGF0IHdheSB3b24ndCBzaG93IHVwIGhlcmUuXG4gICAqL1xuICBnZXQgdXJsKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY3VzdG9tRG9tYWluID0gdGhpcy5hcGkuZG9tYWluTmFtZTtcbiAgICAvLyBBIGN1c3RvbSBkb21haW4gcmVhY2hlcyB0aGUgc3RhZ2UgdGhyb3VnaCBhIGJhc2UgcGF0aCBtYXBwaW5nLCBzbyB0aGVcbiAgICAvLyBzdGFnZSBuYW1lIGlzbid0IGluIHRoZSBwYXRoIHRoZXJlOyB0aGUgbWFwcGluZyBtYXkgYmUsIHdoZW4gc2V0LlxuICAgIGNvbnN0IFtvcmlnaW4sIHByZWZpeF0gPSBjdXN0b21Eb21haW5cbiAgICAgID8gW1xuICAgICAgICAgIGBodHRwczovLyR7Y3VzdG9tRG9tYWluLmRvbWFpbk5hbWV9YCxcbiAgICAgICAgICB0aGlzLnByb3BzLm92ZXJyaWRlcz8ucmVzdEFwaVByb3BzPy5kb21haW5OYW1lPy5iYXNlUGF0aCxcbiAgICAgICAgXVxuICAgICAgOiBbXG4gICAgICAgICAgYGh0dHBzOi8vJHt0aGlzLmFwaS5yZXN0QXBpSWR9LmV4ZWN1dGUtYXBpLiR7U3RhY2sub2YodGhpcykucmVnaW9ufS5hbWF6b25hd3MuY29tYCxcbiAgICAgICAgICB0aGlzLmFwaS5kZXBsb3ltZW50U3RhZ2Uuc3RhZ2VOYW1lLFxuICAgICAgICBdO1xuICAgIHJldHVybiBqb2luUGF0aChvcmlnaW4sIHByZWZpeCwgdGhpcy5wcm9wcy5iYXNlUGF0aCk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IGJhc2VSZXNvdXJjZTogSVJlc291cmNlO1xuICBwcml2YXRlIHJlYWRvbmx5IG5leHRSZXNvdXJjZTogSVJlc291cmNlO1xuICBwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBOZXh0anNBcGlQcm9wcztcbiAgcHJpdmF0ZSBzdGF0aWNJbnRlZ3JhdGlvblJvbGU6IElSb2xlO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBOZXh0anNBcGlQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuXG4gICAgdGhpcy52YWxpZGF0ZVByb3BzKHByb3BzKTtcbiAgICB0aGlzLmFwaSA9IHRoaXMuY3JlYXRlUmVzdEFwaSgpO1xuICAgIHRoaXMuYmFzZVJlc291cmNlID0gdGhpcy5jcmVhdGVCYXNlUmVzb3VyY2UocHJvcHMuYmFzZVBhdGgpO1xuICAgIHRoaXMubmV4dFJlc291cmNlID0gdGhpcy5iYXNlUmVzb3VyY2UuYWRkUmVzb3VyY2UoXCJfbmV4dFwiKTtcbiAgICB0aGlzLnN0YXRpY0ludGVncmF0aW9uUm9sZSA9IHRoaXMuY3JlYXRlU3RhdGljSW50ZWdyYXRpb25Sb2xlKCk7XG4gICAgdGhpcy5jcmVhdGVTdGF0aWNJbnRlZ3JhdGlvbnMoKTtcbiAgICBpZiAocHJvcHMuc2VydmVyRnVuY3Rpb24pIHtcbiAgICAgIC8vIFdpdGhvdXQgYSBkZWRpY2F0ZWQgaW1hZ2UgZnVuY3Rpb24sIGBfbmV4dC9pbWFnZWAgZmFsbHMgdGhyb3VnaCB0byB0aGVcbiAgICAgIC8vIGB7cHJveHkrfWAgY2F0Y2gtYWxsIG9uIHRoZSBzZXJ2ZXIgZnVuY3Rpb24uXG4gICAgICBpZiAocHJvcHMuaW1hZ2VGdW5jdGlvbikge1xuICAgICAgICB0aGlzLmNyZWF0ZUltYWdlSW50ZWdyYXRpb24ocHJvcHMuaW1hZ2VGdW5jdGlvbik7XG4gICAgICB9XG4gICAgICB0aGlzLmNyZWF0ZUR5bmFtaWNJbnRlZ3JhdGlvbihwcm9wcy5zZXJ2ZXJGdW5jdGlvbik7XG4gICAgfSBlbHNlIGlmIChwcm9wcy52cGMpIHtcbiAgICAgIC8vIFtGdXR1cmVdIGNyZWF0ZSBpbnRlZ3JhdGlvbiB3aXRoIEVDUyB2aWEgVlBDIExpbmsgYW5kIEVDUyBTZXJ2aWNlIERpc2NvdmVyeVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVQcm9wcyhwcm9wczogTmV4dGpzQXBpUHJvcHMpIHtcbiAgICBpZiAoIXByb3BzLnNlcnZlckZ1bmN0aW9uICYmICFwcm9wcy52cGMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInNlcnZlckZ1bmN0aW9uIG9yIHZwYyBtdXN0IGJlIHNldCBpbiBOZXh0anNBcGlQcm9wc1wiKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVJlc3RBcGkoKTogUmVzdEFwaSB7XG4gICAgcmV0dXJuIG5ldyBSZXN0QXBpKHRoaXMsIFwiUmVzdEFwaVwiLCB7XG4gICAgICBiaW5hcnlNZWRpYVR5cGVzOiBbXCIqLypcIl0sXG4gICAgICBkZXNjcmlwdGlvbjogYGNkay1uZXh0anMgUkVTVCBBUEkgZm9yICR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfWAsXG4gICAgICBlbmRwb2ludFR5cGVzOiBbRW5kcG9pbnRUeXBlLlJFR0lPTkFMXSxcbiAgICAgIG1pbkNvbXByZXNzaW9uU2l6ZTogU2l6ZS5ieXRlcygwKSwgLy8gY29tcHJlc3MgYWxsIHJlc3BvbnNlcyBmb3IgYmV0dGVyIHBlcmZcbiAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5yZXN0QXBpUHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGJhc2UgcmVzb3VyY2UgcGF0aCBpZiBuZWVkZWQuIEltcG9ydGFudCBpZiBgYmFzZVBhdGhgIGlzIHNldC5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQmFzZVJlc291cmNlKGJhc2VQYXRoPzogc3RyaW5nKTogSVJlc291cmNlIHtcbiAgICAvLyBDcmVhdGUgYmFzZSByZXNvdXJjZSBwYXRoIGlmIG5lZWRlZFxuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVCYXNlUGF0aChiYXNlUGF0aCk7XG4gICAgcmV0dXJuIG5vcm1hbGl6ZWQgPyB0aGlzLmFwaS5yb290LmFkZFJlc291cmNlKG5vcm1hbGl6ZWQpIDogdGhpcy5hcGkucm9vdDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU3RhdGljSW50ZWdyYXRpb25Sb2xlKCkge1xuICAgIC8vIENyZWF0ZSBTMyBpbnRlZ3JhdGlvbiByb2xlXG4gICAgY29uc3Qgc3RhdGljSW50ZWdyYXRpb25Sb2xlID0gbmV3IFJvbGUodGhpcywgXCJTdGF0aWNJbnRlZ3JhdGlvblJvbGVcIiwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbChcImFwaWdhdGV3YXkuYW1hem9uYXdzLmNvbVwiKSxcbiAgICB9KTtcblxuICAgIHN0YXRpY0ludGVncmF0aW9uUm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbXCJzMzpHZXRPYmplY3RcIiwgXCJzMzpMaXN0QnVja2V0XCJdLFxuICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICB0aGlzLnByb3BzLnN0YXRpY0Fzc2V0c0J1Y2tldC5idWNrZXRBcm4sXG4gICAgICAgICAgYCR7dGhpcy5wcm9wcy5zdGF0aWNBc3NldHNCdWNrZXQuYnVja2V0QXJufS8qYCxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIHN0YXRpY0ludGVncmF0aW9uUm9sZTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU3RhdGljSW50ZWdyYXRpb25zKCkge1xuICAgIHRoaXMubmV4dFJlc291cmNlXG4gICAgICAuYWRkUmVzb3VyY2UoXCJzdGF0aWNcIilcbiAgICAgIC5hZGRSZXNvdXJjZShcIntwcm94eSt9XCIpXG4gICAgICAuYWRkTWV0aG9kKFxuICAgICAgICBcIkdFVFwiLFxuICAgICAgICB0aGlzLmNyZWF0ZVMzSW50ZWdyYXRpb24oeyBrZXk6IHRoaXMuczNLZXkoXCJfbmV4dC9zdGF0aWMve2tleX1cIikgfSksXG4gICAgICAgIHRoaXMuZ2V0U3RhdGljTWV0aG9kT3B0aW9ucyh7IHByb3h5OiB0cnVlIH0pLFxuICAgICAgKTtcbiAgICAvLyBhZGQgcHVibGljIGRpcmVjdG9yeSBmaWxlcy9kaXJlY3RvcmllcyB0aGF0IGV4aXN0IGF0IHRvcCBsZXZlbCBidXQgbmVlZCB0byBnbyB0byBTMy5cbiAgICBmb3IgKGNvbnN0IHB1YmxpY0RpckVudHJ5IG9mIHRoaXMucHJvcHMucHVibGljRGlyRW50cmllcykge1xuICAgICAgaWYgKHB1YmxpY0RpckVudHJ5LmlzRGlyZWN0b3J5KSB7XG4gICAgICAgIHRoaXMuYmFzZVJlc291cmNlXG4gICAgICAgICAgLmFkZFJlc291cmNlKHB1YmxpY0RpckVudHJ5Lm5hbWUpXG4gICAgICAgICAgLmFkZFJlc291cmNlKFwie3Byb3h5K31cIilcbiAgICAgICAgICAuYWRkTWV0aG9kKFxuICAgICAgICAgICAgXCJHRVRcIixcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUzNJbnRlZ3JhdGlvbih7XG4gICAgICAgICAgICAgIGtleTogdGhpcy5zM0tleShgJHtwdWJsaWNEaXJFbnRyeS5uYW1lfS97a2V5fWApLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0aGlzLmdldFN0YXRpY01ldGhvZE9wdGlvbnMoeyBwcm94eTogdHJ1ZSB9KSxcbiAgICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5iYXNlUmVzb3VyY2VcbiAgICAgICAgICAuYWRkUmVzb3VyY2UocHVibGljRGlyRW50cnkubmFtZSlcbiAgICAgICAgICAuYWRkTWV0aG9kKFxuICAgICAgICAgICAgXCJHRVRcIixcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUzNJbnRlZ3JhdGlvbih7IGtleTogdGhpcy5zM0tleShwdWJsaWNEaXJFbnRyeS5uYW1lKSB9KSxcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdGljTWV0aG9kT3B0aW9ucygpLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZWZpeGVzIGEgcmVxdWVzdCBwYXRoIHdpdGggdGhlIGtleSBwcmVmaXggdGhlIGFzc2V0cyB3ZXJlIHVwbG9hZGVkIHVuZGVyLFxuICAgKiBzaW5jZSB0aGUgUzMgaW50ZWdyYXRpb25zIGFkZHJlc3Mgb2JqZWN0cyBieSBrZXkgcmF0aGVyIHRoYW4gYnkgVVJMLlxuICAgKi9cbiAgcHJpdmF0ZSBzM0tleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGpvaW5QYXRoKHRoaXMucHJvcHMuc3RhdGljQXNzZXRzS2V5UHJlZml4LCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcHMgQVBJIHJlcXVlc3QgdG8gUzMgcmVxdWVzdC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvcmVzdC1hcGktcGFyYW1ldGVyLW1hcHBpbmctc291cmNlcy5odG1sXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2ludGVncmF0aW5nLWFwaS13aXRoLWF3cy1zZXJ2aWNlcy1zMy5odG1sI2FwaS1pdGVtcy1pbi1mb2xkZXItYXMtczMtb2JqZWN0cy1pbi1idWNrZXRcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlUzNJbnRlZ3JhdGlvbih7IGtleSB9OiB7IGtleTogc3RyaW5nIH0pIHtcbiAgICBjb25zdCBzM0ludGVncmF0aW9uID0gbmV3IEF3c0ludGVncmF0aW9uKHtcbiAgICAgIHNlcnZpY2U6IFwiczNcIixcbiAgICAgIGludGVncmF0aW9uSHR0cE1ldGhvZDogXCJHRVRcIixcbiAgICAgIHBhdGg6IGAke3RoaXMucHJvcHMuc3RhdGljQXNzZXRzQnVja2V0LmJ1Y2tldE5hbWV9LyR7a2V5fWAsXG4gICAgICBvcHRpb25zOiB7XG4gICAgICAgIGNyZWRlbnRpYWxzUm9sZTogdGhpcy5zdGF0aWNJbnRlZ3JhdGlvblJvbGUsXG4gICAgICAgIHBhc3N0aHJvdWdoQmVoYXZpb3I6IFBhc3N0aHJvdWdoQmVoYXZpb3IuV0hFTl9OT19URU1QTEFURVMsIC8vIHJlY29tbWVuZGVkXG4gICAgICAgIHJlcXVlc3RQYXJhbWV0ZXJzOiBrZXkuaW5jbHVkZXMoXCJ7a2V5fVwiKVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBcImludGVncmF0aW9uLnJlcXVlc3QucGF0aC5rZXlcIjogXCJtZXRob2QucmVxdWVzdC5wYXRoLnByb3h5XCIsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIGludGVncmF0aW9uUmVzcG9uc2VzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgc3RhdHVzQ29kZTogXCIyMDBcIixcbiAgICAgICAgICAgIHJlc3BvbnNlUGFyYW1ldGVyczoge1xuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuQ29udGVudC1UeXBlXCI6XG4gICAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuQ29udGVudC1UeXBlXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LUxlbmd0aFwiOlxuICAgICAgICAgICAgICAgIFwiaW50ZWdyYXRpb24ucmVzcG9uc2UuaGVhZGVyLkNvbnRlbnQtTGVuZ3RoXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5DYWNoZS1Db250cm9sXCI6XG4gICAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuQ2FjaGUtQ29udHJvbFwiLFxuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuRVRhZ1wiOiBcImludGVncmF0aW9uLnJlc3BvbnNlLmhlYWRlci5FVGFnXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5MYXN0LU1vZGlmaWVkXCI6XG4gICAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuTGFzdC1Nb2RpZmllZFwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHN0YXR1c0NvZGU6IFwiNDA0XCIsXG4gICAgICAgICAgICBzZWxlY3Rpb25QYXR0ZXJuOiBcIjQwNFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LnN0YXRpY0ludGVncmF0aW9uUHJvcHMsXG4gICAgfSk7XG4gICAgcmV0dXJuIHMzSW50ZWdyYXRpb247XG4gIH1cblxuICBwcml2YXRlIGdldFN0YXRpY01ldGhvZE9wdGlvbnMoeyBwcm94eSB9ID0geyBwcm94eTogZmFsc2UgfSk6IE1ldGhvZE9wdGlvbnMge1xuICAgIHJldHVybiB7XG4gICAgICByZXF1ZXN0UGFyYW1ldGVyczogcHJveHlcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBcIm1ldGhvZC5yZXF1ZXN0LnBhdGgucHJveHlcIjogdHJ1ZSxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgbWV0aG9kUmVzcG9uc2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiBcIjIwMFwiLFxuICAgICAgICAgIHJlc3BvbnNlUGFyYW1ldGVyczoge1xuICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNvbnRlbnQtVHlwZVwiOiB0cnVlLFxuICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNvbnRlbnQtTGVuZ3RoXCI6IHRydWUsXG4gICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuQ2FjaGUtQ29udHJvbFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkVUYWdcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5MYXN0LU1vZGlmaWVkXCI6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHN0YXR1c0NvZGU6IFwiNDA0XCIsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LnMzTWV0aG9kT3B0aW9ucyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBMYW1iZGEgUHJveHkgaW50ZWdyYXRpb24gZm9yIHRoZSBgX25leHQvaW1hZ2VgIHJvdXRlLlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVJbWFnZUludGVncmF0aW9uKGltYWdlRnVuY3Rpb246IElGdW5jdGlvbikge1xuICAgIC8vIGltYWdlRnVuY3Rpb24gaXMgYXNzdW1lZCB0byBiZSB0aGUgZGVkaWNhdGVkLCBzdHJlYW1pbmctY2FwYWJsZSBpbWFnZVxuICAgIC8vIExhbWJkYSAoc2VlIGl0cyBkb2MgY29tbWVudCk7IG92ZXJyaWRlIHJlc3BvbnNlVHJhbnNmZXJNb2RlIHZpYVxuICAgIC8vIGltYWdlSW50ZWdyYXRpb25Qcm9wcyBpZiB0aGF0IGFzc3VtcHRpb24gZG9lc24ndCBob2xkIGZvciBhIGN1c3RvbVxuICAgIC8vIGltYWdlRnVuY3Rpb24sIG90aGVyd2lzZSBBUEkgR2F0ZXdheSByZXR1cm5zIGEgNTAyLiBEZWxpYmVyYXRlbHlcbiAgICAvLyBkb2Vzbid0IGluaGVyaXQgZHluYW1pY0ludGVncmF0aW9uUHJvcHM6IHRoYXQncyBmb3Igc2VydmVyRnVuY3Rpb24sXG4gICAgLy8gYSBkaWZmZXJlbnQgTGFtYmRhIHdpdGggZGlmZmVyZW50IChhbmQgcG9zc2libHkgY29uZmxpY3RpbmcsIGUuZy5cbiAgICAvLyBCVUZGRVJFRCBmb3IgYSBub24tc3RyZWFtaW5nIExhbWJkYSBXZWIgQWRhcHRlciBzZXR1cCkgc3RyZWFtaW5nXG4gICAgLy8gcmVxdWlyZW1lbnRzIHRoYW4gdGhlIGFsd2F5cy1zdHJlYW1pbmcgZGVkaWNhdGVkIGltYWdlIExhbWJkYS5cbiAgICBjb25zdCBpbWFnZUludGVncmF0aW9uID0gbmV3IExhbWJkYUludGVncmF0aW9uKGltYWdlRnVuY3Rpb24sIHtcbiAgICAgIHJlc3BvbnNlVHJhbnNmZXJNb2RlOiBSZXNwb25zZVRyYW5zZmVyTW9kZS5TVFJFQU0sXG4gICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8uaW1hZ2VJbnRlZ3JhdGlvblByb3BzLFxuICAgIH0pO1xuICAgIGNvbnN0IGltYWdlUmVzb3VyY2UgPSB0aGlzLm5leHRSZXNvdXJjZS5hZGRSZXNvdXJjZShcImltYWdlXCIpO1xuICAgIGltYWdlUmVzb3VyY2UuYWRkTWV0aG9kKFwiQU5ZXCIsIGltYWdlSW50ZWdyYXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBMYW1iZGEgUHJveHkgaW50ZWdyYXRpb24gZm9yIGFsbCBvdGhlciByb3V0ZXNcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY0ludGVncmF0aW9uKHNlcnZlckZ1bmN0aW9uOiBJRnVuY3Rpb24pIHtcbiAgICAvLyBBbGwgb3RoZXIgcm91dGVzIHVzZSBzdHJlYW1pbmcgZm9yIGJldHRlciBwZXJmb3JtYW5jZVxuICAgIGNvbnN0IHN0cmVhbWluZ0ludGVncmF0aW9uID0gbmV3IExhbWJkYUludGVncmF0aW9uKHNlcnZlckZ1bmN0aW9uLCB7XG4gICAgICByZXNwb25zZVRyYW5zZmVyTW9kZTogUmVzcG9uc2VUcmFuc2Zlck1vZGUuU1RSRUFNLFxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmR5bmFtaWNJbnRlZ3JhdGlvblByb3BzLFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIGNhdGNoLWFsbCByb3V0ZXMgd2l0aCBzdHJlYW1pbmcgaW50ZWdyYXRpb24gZm9yIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xuICAgIHRoaXMuYmFzZVJlc291cmNlLmFkZE1ldGhvZChcIkFOWVwiLCBzdHJlYW1pbmdJbnRlZ3JhdGlvbik7XG4gICAgY29uc3QgcHJveHlSZXNvdXJjZSA9IHRoaXMuYmFzZVJlc291cmNlLmFkZFJlc291cmNlKFwie3Byb3h5K31cIik7XG4gICAgcHJveHlSZXNvdXJjZS5hZGRNZXRob2QoXCJBTllcIiwgc3RyZWFtaW5nSW50ZWdyYXRpb24pO1xuICB9XG59XG4iXX0=
542
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9uZXh0anMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSx5Q0FBaUM7QUFDakMsNkNBQWlFO0FBQ2pFLCtEQVlvQztBQUVwQyx1REFBOEM7QUFDOUMsdUVBQXdGO0FBQ3hGLGlEQUs2QjtBQUM3Qix1REFPZ0M7QUFFaEMsMkNBQXVDO0FBQ3ZDLDJDQUF5QztBQU16QyxpRUFBb0U7QUFDcEUsaURBQWdFO0FBRWhFOzs7R0FHRztBQUNILE1BQU0sYUFBYSxHQUFHLHNCQUFzQixDQUFDO0FBeUY3Qzs7R0FFRztBQUNILE1BQWEsU0FBVSxTQUFRLHNCQUFTOztJQUN0Qzs7T0FFRztJQUNhLEdBQUcsQ0FBVTtJQUU3Qjs7Ozs7Ozs7T0FRRztJQUNILElBQUksR0FBRztRQUNMLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1FBQ3pDLHdFQUF3RTtRQUN4RSxvRUFBb0U7UUFDcEUsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxZQUFZO1lBQ25DLENBQUMsQ0FBQztnQkFDRSxXQUFXLFlBQVksQ0FBQyxVQUFVLEVBQUU7Z0JBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsUUFBUTthQUN6RDtZQUNILENBQUMsQ0FBQztnQkFDRSxXQUFXLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxnQkFBZ0IsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxnQkFBZ0I7Z0JBQ2xGLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLFNBQVM7YUFDbkMsQ0FBQztRQUNOLE9BQU8sSUFBQSxvQkFBUSxFQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRUQ7OztPQUdH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QztRQUNsRCxDQUFDO1FBQ0QsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEUsYUFBYSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztJQUN2RCxDQUFDOztBQWpsQkgsOEJBa2xCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucywgRHVyYXRpb24sIFNpemUsIFN0YWNrIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQge1xuICBSZXN0QXBpLFxuICBMYW1iZGFJbnRlZ3JhdGlvbixcbiAgQXdzSW50ZWdyYXRpb24sXG4gIE1ldGhvZE9wdGlvbnMsXG4gIElSZXNvdXJjZSxcbiAgRW5kcG9pbnRUeXBlLFxuICBSZXN0QXBpUHJvcHMsXG4gIEF3c0ludGVncmF0aW9uUHJvcHMsXG4gIExhbWJkYUludGVncmF0aW9uT3B0aW9ucyxcbiAgUGFzc3Rocm91Z2hCZWhhdmlvcixcbiAgUmVzcG9uc2VUcmFuc2Zlck1vZGUsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXBpZ2F0ZXdheVwiO1xuaW1wb3J0IHsgSVZwYyB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCI7XG5pbXBvcnQgeyBSdWxlIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1ldmVudHNcIjtcbmltcG9ydCB7IExhbWJkYUZ1bmN0aW9uIGFzIExhbWJkYUZ1bmN0aW9uVGFyZ2V0IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1ldmVudHMtdGFyZ2V0c1wiO1xuaW1wb3J0IHtcbiAgUm9sZSxcbiAgU2VydmljZVByaW5jaXBhbCxcbiAgUG9saWN5U3RhdGVtZW50LFxuICBJUm9sZSxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7XG4gIEFyY2hpdGVjdHVyZSxcbiAgQ29kZSxcbiAgRnVuY3Rpb24gYXMgTGFtYmRhRnVuY3Rpb24sXG4gIElGdW5jdGlvbixcbiAgUnVudGltZSxcbiAgUnVudGltZUZhbWlseSxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIjtcbmltcG9ydCB7IElCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgTE9HX1BSRUZJWCB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT3B0aW9uYWxGdW5jdGlvblByb3BzIH0gZnJvbSBcIi4vZ2VuZXJhdGVkLXN0cnVjdHMvT3B0aW9uYWxGdW5jdGlvblByb3BzXCI7XG5pbXBvcnQge1xuICBOZXh0anNGdW5jdGlvbkdyb3VwQmVoYXZpb3IsXG4gIFB1YmxpY0RpckVudHJ5LFxufSBmcm9tIFwiLi9uZXh0anMtYnVpbGQvbmV4dGpzLWJ1aWxkXCI7XG5pbXBvcnQgeyBzdGF0aWNBc3NldHNPYmplY3RzUGF0dGVybiB9IGZyb20gXCIuL25leHRqcy1zdGF0aWMtYXNzZXRzXCI7XG5pbXBvcnQgeyBqb2luUGF0aCwgbm9ybWFsaXplQmFzZVBhdGggfSBmcm9tIFwiLi91dGlscy9iYXNlLXBhdGhcIjtcblxuLyoqXG4gKiBXaGF0IEFQSSBHYXRld2F5IGFjY2VwdHMgYXMgYSByZXNvdXJjZSBwYXRoIHBhcnQsIHBlciBDREsncyBvd24gY2hlY2sgaW5cbiAqIGBSZXNvdXJjZWA6IGBbYS16QS1aMC05Oi5fLSRdYCwgcGx1cyBhbiBvcHRpb25hbCB0cmFpbGluZyBgK2AuXG4gKi9cbmNvbnN0IEFQSV9QQVRIX1BBUlQgPSAvXlthLXpBLVowLTk6Ll9cXC0kXSskLztcblxuZXhwb3J0IGludGVyZmFjZSBOZXh0anNBcGlPdmVycmlkZXMge1xuICByZWFkb25seSByZXN0QXBpUHJvcHM/OiBSZXN0QXBpUHJvcHM7XG4gIHJlYWRvbmx5IHN0YXRpY0ludGVncmF0aW9uUHJvcHM/OiBBd3NJbnRlZ3JhdGlvblByb3BzO1xuICByZWFkb25seSBzM01ldGhvZE9wdGlvbnM/OiBNZXRob2RPcHRpb25zO1xuICByZWFkb25seSBkeW5hbWljSW50ZWdyYXRpb25Qcm9wcz86IExhbWJkYUludGVncmF0aW9uT3B0aW9ucztcbiAgLyoqXG4gICAqIFByb3BzIGZvciB0aGUgZnVuY3Rpb24gdGhhdCBkZXBsb3lzIHRoZSBzdGFnZSBhZ2FpbiBhZnRlciBlYWNoIHN0YWNrXG4gICAqIHVwZGF0ZS5cbiAgICogQHNlZSBOZXh0anNBcGlQcm9wcy5yZWRlcGxveUFmdGVyVXBkYXRlXG4gICAqL1xuICByZWFkb25seSByZWRlcGxveUZ1bmN0aW9uUHJvcHM/OiBPcHRpb25hbEZ1bmN0aW9uUHJvcHM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzQXBpUHJvcHMge1xuICAvKipcbiAgICogT3B0aW9uYWwgYmFzZSBwYXRoIGZvciB0aGUgYXBwbGljYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGJhc2VQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogT3ZlcnJpZGUgcHJvcHMgZm9yIGV2ZXJ5IGNvbnN0cnVjdC5cbiAgICovXG4gIHJlYWRvbmx5IG92ZXJyaWRlcz86IE5leHRqc0FwaU92ZXJyaWRlcztcbiAgLyoqXG4gICAqIFBhdGggdG8gZGlyZWN0b3J5IG9mIE5leHQuanMgYXBwJ3MgcHVibGljIGRpcmVjdG9yeS4gVXNlZCB0byBhZGQgcmVzb3VyY2VzXG4gICAqIHRvIEFQSSBHYXRld2F5IFJFU1QgQVBJIGZvciBwdWJsaWMgZGlyZWN0b3J5IHRvIGdvIGRpcmVjdGx5IHRvIFMzLlxuICAgKi9cbiAgcmVhZG9ubHkgcHVibGljRGlyRW50cmllczogUHVibGljRGlyRW50cnlbXTtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNSZWdpb25hbEZ1bmN0aW9uc2AuIFRoZSBMYW1iZGEgZnVuY3Rpb24gZm9yIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xuICAgKi9cbiAgcmVhZG9ubHkgc2VydmVyRnVuY3Rpb24/OiBJRnVuY3Rpb247XG4gIC8qKlxuICAgKiBUaGUgUzMgYnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0c1xuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzQnVja2V0OiBJQnVja2V0O1xuICAvKipcbiAgICogUzMga2V5IHByZWZpeCB0aGUgc3RhdGljIGFzc2V0cyB3ZXJlIHVwbG9hZGVkIHVuZGVyLCBpLmUuXG4gICAqIGBOZXh0anNTdGF0aWNBc3NldHMua2V5UHJlZml4YCwgd2hpY2ggbmFtZXNwYWNlcyBhIHNoYXJlZCBidWNrZXQuXG4gICAqXG4gICAqIEluZGVwZW5kZW50IG9mIGBiYXNlUGF0aGAgYWJvdmU6IHRoYXQgb25lIGlzIHRoZSBVUkwgcHJlZml4IHRoZSBSRVNUIEFQSVxuICAgKiBzZXJ2ZXMgdGhlIGFwcCBhdCAoY29tbW9ubHkgdGhlIEFQSSBHYXRld2F5IHN0YWdlKSwgd2hpbGUgdGhpcyBvbmUgaXMgd2hlcmVcbiAgICogdGhlIG9iamVjdHMgbGl2ZSBpbiB0aGUgYnVja2V0LiBgX25leHQvc3RhdGljYCBhbmQgcHVibGljIGRpcmVjdG9yeVxuICAgKiByZXF1ZXN0cyBhcmUgbWFwcGVkIHRvIFMzIGtleXMgZGlyZWN0bHksIHNvIHRoZXkgNDA0IHVubGVzcyB0aGlzIHByZWZpeCBpc1xuICAgKiBhcHBsaWVkLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzS2V5UHJlZml4Pzogc3RyaW5nO1xuICAvKipcbiAgICogW0Z1dHVyZV0gUmVxdWlyZWQgaWYgYE5leHRqc1JlZ2lvbmFsQ29udGFpbmVyc2AuIFZQQyB0byBjcmVhdGUgVlBDIExpbmsgYW5kIEVDUyBTZXJ2aWNlIERpc2NvdmVyeVxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogSVZwYztcbiAgLyoqXG4gICAqIFRoZSBub24tYGRlZmF1bHRgIGZ1bmN0aW9uIGdyb3VwcywgdGhlIExhbWJkYXNcbiAgICoge0BsaW5rIGZ1bmN0aW9uR3JvdXBCZWhhdmlvcnN9IHJvdXRlIHRvLlxuICAgKiBAZGVmYXVsdCAtIG5vIHNwbGl0dGluZzsgYHtwcm94eSt9YCBzZXJ2ZXMgZXZlcnkgZHluYW1pYyByb3V0ZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Hcm91cHM/OiBOZXh0anNBcGlGdW5jdGlvbkdyb3VwW107XG4gIC8qKlxuICAgKiBgTmV4dGpzQnVpbGQuZnVuY3Rpb25Hcm91cEJlaGF2aW9yc2A6IGVhY2ggZGlzdGluY3QgYHJvdXRlYCBiZWNvbWVzIGFcbiAgICogcmVzb3VyY2Ugc3VidHJlZSBpbnRlZ3JhdGVkIHdpdGggaXRzIGdyb3VwLCBzbyB0aGUgcm91dGVzIGVhY2ggZ3JvdXAgd2FzXG4gICAqIHBhY2thZ2VkIHdpdGggcmVhY2ggaXQgcmF0aGVyIHRoYW4ge0BsaW5rIHNlcnZlckZ1bmN0aW9ufS5cbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbkdyb3VwQmVoYXZpb3JzPzogTmV4dGpzRnVuY3Rpb25Hcm91cEJlaGF2aW9yW107XG4gIC8qKlxuICAgKiBEZXBsb3kgdGhlIHN0YWdlIGFnYWluIG9uY2UgZWFjaCBzdGFjayB1cGRhdGUgaGFzIGZpbmlzaGVkLCBzbyBpdCBzZXJ2ZXNcbiAgICogdGhlIEFQSSBhcyBpdCBpcyBhZnRlciB0aGUgdXBkYXRlLlxuICAgKlxuICAgKiBDbG91ZEZvcm1hdGlvbiBzbmFwc2hvdHMgdGhlIEFQSSBpbnRvIGEgbmV3IGRlcGxveW1lbnQgd2hpbGUgcmVzb3VyY2VzXG4gICAqIHJlbW92ZWQgZnJvbSB0aGUgdGVtcGxhdGUgc3RpbGwgZXhpc3Qg4oCUIGl0IGRlbGV0ZXMgdGhlbSBvbmx5IGR1cmluZ1xuICAgKiBjbGVhbnVwIOKAlCBzbyB0aGUgc3RhZ2Uga2VlcHMgc2VydmluZyB0aGVtLiBBZnRlciByZW1vdmluZyBhIGZ1bmN0aW9uXG4gICAqIGdyb3VwLCBpdHMgcm91dGVzIHRoZW4gcG9pbnQgYXQgYSBkZWxldGVkIExhbWJkYSBhbmQgYW5zd2VyIDUwMCB1bnRpbCB0aGVcbiAgICogbmV4dCBkZXBsb3ltZW50LiBBbiBFdmVudEJyaWRnZSBydWxlIG9uIHRoaXMgc3RhY2sncyBgVVBEQVRFX0NPTVBMRVRFYFxuICAgKiAoYW5kIGBVUERBVEVfUk9MTEJBQ0tfQ09NUExFVEVgKSBpbnZva2VzIGEgc21hbGwgZnVuY3Rpb24gdGhhdCBkZXBsb3lzIHRoZVxuICAgKiBzdGFnZSBmcm9tIHRoZSBsaXZlIEFQSSBhbmQgZGVsZXRlcyB0aGUgZGVwbG95bWVudHMgaXRzIGVhcmxpZXIgcnVucyBtYWRlLlxuICAgKlxuICAgKiBJZ25vcmVkIHdoZW4gYG92ZXJyaWRlcy5yZXN0QXBpUHJvcHMuZGVwbG95YCBpcyBgZmFsc2VgOiB0aGVyZSBpcyBubyBzdGFnZS5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVkZXBsb3lBZnRlclVwZGF0ZT86IGJvb2xlYW47XG59XG5cbi8qKiBBIG5vbi1kZWZhdWx0IGZ1bmN0aW9uIGdyb3VwIGFuZCB0aGUgTGFtYmRhIGl0cyByb3V0ZXMgbXVzdCByZWFjaC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzQXBpRnVuY3Rpb25Hcm91cCB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZnVuY3Rpb246IElGdW5jdGlvbjtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIEFQSSBHYXRld2F5IFJFU1QgQVBJIGZvciBOZXh0LmpzIGFwcGxpY2F0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgTmV4dGpzQXBpIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFRoZSBBUEkgR2F0ZXdheSBSRVNUIEFQSVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFwaTogUmVzdEFwaTtcblxuICAvKipcbiAgICogUHVibGljIFVSTCBvZiB0aGUgYXBwLCBpbmNsdWRpbmcgZXZlcnkgcGF0aCBzZWdtZW50IHRoZSBBUEkgbmVzdHMgaXQgdW5kZXIuXG4gICAqIFByZWZlcnMgYSBjdXN0b20gZG9tYWluIGNvbmZpZ3VyZWQgdGhyb3VnaCBgb3ZlcnJpZGVzLnJlc3RBcGlQcm9wcy5kb21haW5OYW1lYFxuICAgKiBvdmVyIHRoZSBleGVjdXRlLWFwaSBlbmRwb2ludC5cbiAgICpcbiAgICogQSBkb21haW4gYXR0YWNoZWQgYWZ0ZXIgdGhpcyBjb25zdHJ1Y3QgaXMgY3JlYXRlZCAoYGFwaS5hZGREb21haW5OYW1lKClgKSBpc1xuICAgKiBzdGlsbCB1c2VkIGZvciB0aGUgaG9zdCwgYnV0IENESyBrZWVwcyBpdHMgYmFzZSBwYXRoIG1hcHBpbmdzIHByaXZhdGUsIHNvIGFcbiAgICogbWFwcGluZyBhZGRlZCB0aGF0IHdheSB3b24ndCBzaG93IHVwIGhlcmUuXG4gICAqL1xuICBnZXQgdXJsKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY3VzdG9tRG9tYWluID0gdGhpcy5hcGkuZG9tYWluTmFtZTtcbiAgICAvLyBBIGN1c3RvbSBkb21haW4gcmVhY2hlcyB0aGUgc3RhZ2UgdGhyb3VnaCBhIGJhc2UgcGF0aCBtYXBwaW5nLCBzbyB0aGVcbiAgICAvLyBzdGFnZSBuYW1lIGlzbid0IGluIHRoZSBwYXRoIHRoZXJlOyB0aGUgbWFwcGluZyBtYXkgYmUsIHdoZW4gc2V0LlxuICAgIGNvbnN0IFtvcmlnaW4sIHByZWZpeF0gPSBjdXN0b21Eb21haW5cbiAgICAgID8gW1xuICAgICAgICAgIGBodHRwczovLyR7Y3VzdG9tRG9tYWluLmRvbWFpbk5hbWV9YCxcbiAgICAgICAgICB0aGlzLnByb3BzLm92ZXJyaWRlcz8ucmVzdEFwaVByb3BzPy5kb21haW5OYW1lPy5iYXNlUGF0aCxcbiAgICAgICAgXVxuICAgICAgOiBbXG4gICAgICAgICAgYGh0dHBzOi8vJHt0aGlzLmFwaS5yZXN0QXBpSWR9LmV4ZWN1dGUtYXBpLiR7U3RhY2sub2YodGhpcykucmVnaW9ufS5hbWF6b25hd3MuY29tYCxcbiAgICAgICAgICB0aGlzLmFwaS5kZXBsb3ltZW50U3RhZ2Uuc3RhZ2VOYW1lLFxuICAgICAgICBdO1xuICAgIHJldHVybiBqb2luUGF0aChvcmlnaW4sIHByZWZpeCwgdGhpcy5wcm9wcy5iYXNlUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogRGVwbG95cyB0aGUgc3RhZ2UgYWdhaW4gYWZ0ZXIgZWFjaCBzdGFjayB1cGRhdGUuXG4gICAqIEBzZWUgTmV4dGpzQXBpUHJvcHMucmVkZXBsb3lBZnRlclVwZGF0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJlZGVwbG95RnVuY3Rpb24/OiBMYW1iZGFGdW5jdGlvbjtcbiAgLyoqXG4gICAqIE1hdGNoZXMgdGhpcyBzdGFjaydzIGBVUERBVEVfQ09NUExFVEVgIGFuZCBgVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFYCBhbmRcbiAgICogaW52b2tlcyB7QGxpbmsgcmVkZXBsb3lGdW5jdGlvbn0uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcmVkZXBsb3lSdWxlPzogUnVsZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGJhc2VSZXNvdXJjZTogSVJlc291cmNlO1xuICBwcml2YXRlIHJlYWRvbmx5IG5leHRSZXNvdXJjZTogSVJlc291cmNlO1xuICAvKipcbiAgICogUmVzb3VyY2VzIGNyZWF0ZWQgb25seSBhcyBwYXJlbnRzIG9mIGEgZ3JvdXAgcm91dGUsIGFuZCB0aGVpciBwYXRocy4gQVBJXG4gICAqIEdhdGV3YXkgYW5zd2VycyBhIHJlcXVlc3QgZm9yIGEgcmVzb3VyY2Ugd2l0aCBubyBtZXRob2QgaXRzZWxmIOKAlCA0MDNcbiAgICogXCJNaXNzaW5nIEF1dGhlbnRpY2F0aW9uIFRva2VuXCIg4oCUIHJhdGhlciB0aGFuIGZhbGxpbmcgYmFjayB0byBhIGB7cHJveHkrfWBcbiAgICogaGlnaGVyIHVwLCBzbyBlYWNoIG5lZWRzIG9uZS4gV2l0aG91dCBpdCBhIGAvYXBpL3JlcG9ydHMvKipgIGdyb3VwIHR1cm5lZFxuICAgKiBgL2FwaS9yZXBvcnRzYCBhbmQgYC9hcGlgIGludG8gNDAzcy5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgZ3JvdXBQYXJlbnRSZXNvdXJjZXMgPSBuZXcgTWFwPElSZXNvdXJjZSwgc3RyaW5nW10+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IE5leHRqc0FwaVByb3BzO1xuICBwcml2YXRlIHN0YXRpY0ludGVncmF0aW9uUm9sZTogSVJvbGU7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE5leHRqc0FwaVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICB0aGlzLnByb3BzID0gcHJvcHM7XG5cbiAgICB0aGlzLnZhbGlkYXRlUHJvcHMocHJvcHMpO1xuICAgIHRoaXMuYXBpID0gdGhpcy5jcmVhdGVSZXN0QXBpKCk7XG4gICAgdGhpcy5iYXNlUmVzb3VyY2UgPSB0aGlzLmNyZWF0ZUJhc2VSZXNvdXJjZShwcm9wcy5iYXNlUGF0aCk7XG4gICAgdGhpcy5uZXh0UmVzb3VyY2UgPSB0aGlzLmJhc2VSZXNvdXJjZS5hZGRSZXNvdXJjZShcIl9uZXh0XCIpO1xuICAgIHRoaXMuc3RhdGljSW50ZWdyYXRpb25Sb2xlID0gdGhpcy5jcmVhdGVTdGF0aWNJbnRlZ3JhdGlvblJvbGUoKTtcbiAgICB0aGlzLmNyZWF0ZVN0YXRpY0ludGVncmF0aW9ucygpO1xuICAgIGlmIChwcm9wcy5zZXJ2ZXJGdW5jdGlvbikge1xuICAgICAgLy8gR3JvdXAgcmVzb3VyY2VzIGJlZm9yZSB0aGUgY2F0Y2gtYWxsLCBzbyBgYWRkUmVzb3VyY2VgIHNlZXMgYSBjbGVhbiB0cmVlXG4gICAgICAvLyBhbmQgYSBncm91cCBjYW4gY2xhaW0gYSBwYXRoIHRoZSBjYXRjaC1hbGwgd291bGQgb3RoZXJ3aXNlIHNlcnZlLlxuICAgICAgdGhpcy5jcmVhdGVGdW5jdGlvbkdyb3VwSW50ZWdyYXRpb25zKCk7XG4gICAgICAvLyBgX25leHQvaW1hZ2VgIGhhcyBubyByZXNvdXJjZSBvZiBpdHMgb3duOiBpdCBmYWxscyB0aHJvdWdoIHRvIHRoZVxuICAgICAgLy8gYHtwcm94eSt9YCBjYXRjaC1hbGwsIGFuZCB0aGUgc2VydmVyIGZ1bmN0aW9uIG9wdGltaXplcyBpbi1wcm9jZXNzLlxuICAgICAgdGhpcy5jcmVhdGVEeW5hbWljSW50ZWdyYXRpb24ocHJvcHMuc2VydmVyRnVuY3Rpb24pO1xuICAgIH0gZWxzZSBpZiAocHJvcHMudnBjKSB7XG4gICAgICAvLyBbRnV0dXJlXSBjcmVhdGUgaW50ZWdyYXRpb24gd2l0aCBFQ1MgdmlhIFZQQyBMaW5rIGFuZCBFQ1MgU2VydmljZSBEaXNjb3ZlcnlcbiAgICB9XG4gICAgaWYgKFxuICAgICAgcHJvcHMucmVkZXBsb3lBZnRlclVwZGF0ZSAhPT0gZmFsc2UgJiZcbiAgICAgIHByb3BzLm92ZXJyaWRlcz8ucmVzdEFwaVByb3BzPy5kZXBsb3kgIT09IGZhbHNlXG4gICAgKSB7XG4gICAgICBbdGhpcy5yZWRlcGxveUZ1bmN0aW9uLCB0aGlzLnJlZGVwbG95UnVsZV0gPSB0aGlzLmNyZWF0ZVJlZGVwbG95KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBzZWUgTmV4dGpzQXBpUHJvcHMucmVkZXBsb3lBZnRlclVwZGF0ZSAqL1xuICBwcml2YXRlIGNyZWF0ZVJlZGVwbG95KCk6IFtMYW1iZGFGdW5jdGlvbiwgUnVsZV0ge1xuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2YodGhpcyk7XG4gICAgY29uc3QgeyByZXN0QXBpSWQgfSA9IHRoaXMuYXBpO1xuICAgIGNvbnN0IHsgc3RhZ2VOYW1lIH0gPSB0aGlzLmFwaS5kZXBsb3ltZW50U3RhZ2U7XG4gICAgY29uc3QgZm4gPSBuZXcgTGFtYmRhRnVuY3Rpb24odGhpcywgXCJSZWRlcGxveUZuXCIsIHtcbiAgICAgIC8vIFBsYWluIGJ1bmRsZWQgSlMgd2l0aCBubyBuYXRpdmUgZGVwZW5kZW5jaWVzOiBhbHdheXMgYXJtNjQuXG4gICAgICBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZS5BUk1fNjQsXG4gICAgICBjb2RlOiBDb2RlLmZyb21Bc3NldChcbiAgICAgICAgam9pbihcbiAgICAgICAgICBfX2Rpcm5hbWUsXG4gICAgICAgICAgXCIuLi9hc3NldHMvbGFtYmRhcy9yZWRlcGxveS1zdGFnZS9yZWRlcGxveS1zdGFnZS5sYW1iZGFcIixcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgIG1lbW9yeVNpemU6IDI1NixcbiAgICAgIHJ1bnRpbWU6IG5ldyBSdW50aW1lKFwibm9kZWpzMjQueFwiLCBSdW50aW1lRmFtaWx5Lk5PREVKUyksXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5taW51dGVzKDEpLFxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LnJlZGVwbG95RnVuY3Rpb25Qcm9wcyxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5yZWRlcGxveUZ1bmN0aW9uUHJvcHM/LmVudmlyb25tZW50LFxuICAgICAgICBSRVNUX0FQSV9JRDogcmVzdEFwaUlkLFxuICAgICAgICBTVEFHRV9OQU1FOiBzdGFnZU5hbWUsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIC8vIEFQSSBHYXRld2F5IGF1dGhvcml6ZXMgaXRzIG1hbmFnZW1lbnQgQVBJIGJ5IEhUVFAgdmVyYiBvbiB0aGUgcmVzb3VyY2VcbiAgICAvLyBwYXRoOyB0aGVzZSBhcmUgdGhlIGZvdXIgY2FsbHMgYHJlZGVwbG95U3RhZ2VgIG1ha2VzLCBvbiB0aGlzIEFQSSBvbmx5LlxuICAgIGNvbnN0IHJlc3RBcGkgPSBgYXJuOiR7c3RhY2sucGFydGl0aW9ufTphcGlnYXRld2F5OiR7c3RhY2sucmVnaW9ufTo6L3Jlc3RhcGlzLyR7cmVzdEFwaUlkfWA7XG4gICAgZm4uYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFtcImFwaWdhdGV3YXk6UE9TVFwiXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbYCR7cmVzdEFwaX0vZGVwbG95bWVudHNgXSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgZm4uYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFtcImFwaWdhdGV3YXk6R0VUXCJdLFxuICAgICAgICByZXNvdXJjZXM6IFtgJHtyZXN0QXBpfS9kZXBsb3ltZW50c2AsIGAke3Jlc3RBcGl9L3N0YWdlc2BdLFxuICAgICAgfSksXG4gICAgKTtcbiAgICBmbi5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogW1wiYXBpZ2F0ZXdheTpERUxFVEVcIl0sXG4gICAgICAgIHJlc291cmNlczogW2Ake3Jlc3RBcGl9L2RlcGxveW1lbnRzLypgXSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgLy8gQ2xvdWRGb3JtYXRpb24gc2VuZHMgZXZlcnkgc3RhY2sgc3RhdHVzIGNoYW5nZSB0byB0aGUgZGVmYXVsdCBldmVudCBidXNcbiAgICAvLyAoXCJNb25pdG9yaW5nIENsb3VkRm9ybWF0aW9uIC4uLiBldmVudHMgd2l0aCBFdmVudEJyaWRnZVwiIGluIHRoZVxuICAgIC8vIENsb3VkRm9ybWF0aW9uIFVzZXIgR3VpZGUpLiBgVVBEQVRFX0NPTVBMRVRFYCBjb21lcyBhZnRlclxuICAgIC8vIGBVUERBVEVfQ09NUExFVEVfQ0xFQU5VUF9JTl9QUk9HUkVTU2AsIHNvIHJlbW92ZWQgcmVzb3VyY2VzIGFyZSBnb25lIGJ5XG4gICAgLy8gdGhlbi4gQSByb2xsYmFjayByZXN0b3JlcyB0aGUgc3RhZ2UgdG8gdGhlIHByZS11cGRhdGUgZGVwbG95bWVudCwgd2hpY2hcbiAgICAvLyBjYW4gY2FycnkgdGhlIHNhbWUgc3RhbGVuZXNzIGZyb20gYW4gZWFybGllciB1cGRhdGUsIHNvIGl0IHJlZGVwbG95cyB0b28uXG4gICAgY29uc3QgcnVsZSA9IG5ldyBSdWxlKHRoaXMsIFwiUmVkZXBsb3lSdWxlXCIsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBgUmVkZXBsb3lzICR7c3RhY2suc3RhY2tOYW1lfSdzIFJFU1QgQVBJIHN0YWdlIGFmdGVyIGEgc3RhY2sgdXBkYXRlYCxcbiAgICAgIGV2ZW50UGF0dGVybjoge1xuICAgICAgICBzb3VyY2U6IFtcImF3cy5jbG91ZGZvcm1hdGlvblwiXSxcbiAgICAgICAgZGV0YWlsVHlwZTogW1wiQ2xvdWRGb3JtYXRpb24gU3RhY2sgU3RhdHVzIENoYW5nZVwiXSxcbiAgICAgICAgZGV0YWlsOiB7XG4gICAgICAgICAgXCJzdGFjay1pZFwiOiBbc3RhY2suc3RhY2tJZF0sXG4gICAgICAgICAgXCJzdGF0dXMtZGV0YWlsc1wiOiB7XG4gICAgICAgICAgICBzdGF0dXM6IFtcIlVQREFURV9DT01QTEVURVwiLCBcIlVQREFURV9ST0xMQkFDS19DT01QTEVURVwiXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHRhcmdldHM6IFtuZXcgTGFtYmRhRnVuY3Rpb25UYXJnZXQoZm4sIHsgcmV0cnlBdHRlbXB0czogMiB9KV0sXG4gICAgfSk7XG4gICAgcmV0dXJuIFtmbiwgcnVsZV07XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUHJvcHMocHJvcHM6IE5leHRqc0FwaVByb3BzKSB7XG4gICAgaWYgKCFwcm9wcy5zZXJ2ZXJGdW5jdGlvbiAmJiAhcHJvcHMudnBjKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZXJ2ZXJGdW5jdGlvbiBvciB2cGMgbXVzdCBiZSBzZXQgaW4gTmV4dGpzQXBpUHJvcHNcIik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVSZXN0QXBpKCk6IFJlc3RBcGkge1xuICAgIHJldHVybiBuZXcgUmVzdEFwaSh0aGlzLCBcIlJlc3RBcGlcIiwge1xuICAgICAgYmluYXJ5TWVkaWFUeXBlczogW1wiKi8qXCJdLFxuICAgICAgZGVzY3JpcHRpb246IGBjZGstbmV4dGpzIFJFU1QgQVBJIGZvciAke1N0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZX1gLFxuICAgICAgZW5kcG9pbnRUeXBlczogW0VuZHBvaW50VHlwZS5SRUdJT05BTF0sXG4gICAgICAvLyBJbmVydCBmb3IgdGhlIGR5bmFtaWMgcm91dGVzOiBBUEkgR2F0ZXdheSBkb2VzIG5vdCBjb21wcmVzcyBhIHJlc3BvbnNlIGl0XG4gICAgICAvLyBzdHJlYW1zIChgUmVzcG9uc2VUcmFuc2Zlck1vZGUuU1RSRUFNYCksIHdoaWNoIGV2ZXJ5IExhbWJkYSBpbnRlZ3JhdGlvblxuICAgICAgLy8gaGVyZSB1c2VzLCBzbyB0aGUgcnVudGltZSBnemlwcyB0aG9zZSBpdHNlbGYuIEtlcHQgYmVjYXVzZSBpdCBzdGlsbFxuICAgICAgLy8gYXBwbGllcyB0byB0aGUgYnVmZmVyZWQgUzMgc3RhdGljIGludGVncmF0aW9ucywgYW5kIGJlY2F1c2UgYSBjb25zdW1lclxuICAgICAgLy8gd2hvIG92ZXJyaWRlcyBhbiBpbnRlZ3JhdGlvbiB0byBCVUZGRVJFRCBnZXRzIGNvbXByZXNzaW9uIGJhY2suXG4gICAgICBtaW5Db21wcmVzc2lvblNpemU6IFNpemUuYnl0ZXMoMCksXG4gICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8ucmVzdEFwaVByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBiYXNlIHJlc291cmNlIHBhdGggaWYgbmVlZGVkLiBJbXBvcnRhbnQgaWYgYGJhc2VQYXRoYCBpcyBzZXQuXG4gICAqXG4gICAqIEEgbmVzdGVkIGBiYXNlUGF0aGAgKFwiL3RlYW0vYXBwXCIpIGhhcyB0byBiZWNvbWUgb25lIHJlc291cmNlIHBlciBzZWdtZW50OlxuICAgKiBBUEkgR2F0ZXdheSBwYXRoIHBhcnRzIGNhbid0IGNvbnRhaW4gXCIvXCIsIHNvIHBhc3NpbmcgdGhlIHdob2xlIHRoaW5nIHRvIGFcbiAgICogc2luZ2xlIGBhZGRSZXNvdXJjZWAgZmFpbHMgdmFsaWRhdGlvbiBhdCBzeW50aC4gYHJlc29sdmVCYXNlUGF0aGAgYWNjZXB0c1xuICAgKiBuZXN0ZWQgdmFsdWVzLCBzbyB0aGlzIGlzIHJlYWNoYWJsZS5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQmFzZVJlc291cmNlKGJhc2VQYXRoPzogc3RyaW5nKTogSVJlc291cmNlIHtcbiAgICAvLyBDcmVhdGUgYmFzZSByZXNvdXJjZSBwYXRoIGlmIG5lZWRlZFxuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVCYXNlUGF0aChiYXNlUGF0aCk7XG4gICAgaWYgKCFub3JtYWxpemVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5hcGkucm9vdDtcbiAgICB9XG4gICAgcmV0dXJuIG5vcm1hbGl6ZWRcbiAgICAgIC5zcGxpdChcIi9cIilcbiAgICAgIC5yZWR1Y2U8SVJlc291cmNlPihcbiAgICAgICAgKHBhcmVudCwgc2VnbWVudCkgPT4gcGFyZW50LmFkZFJlc291cmNlKHNlZ21lbnQpLFxuICAgICAgICB0aGlzLmFwaS5yb290LFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU3RhdGljSW50ZWdyYXRpb25Sb2xlKCkge1xuICAgIC8vIENyZWF0ZSBTMyBpbnRlZ3JhdGlvbiByb2xlXG4gICAgY29uc3Qgc3RhdGljSW50ZWdyYXRpb25Sb2xlID0gbmV3IFJvbGUodGhpcywgXCJTdGF0aWNJbnRlZ3JhdGlvblJvbGVcIiwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbChcImFwaWdhdGV3YXkuYW1hem9uYXdzLmNvbVwiKSxcbiAgICB9KTtcblxuICAgIC8vIE9ubHkgdGhpcyBhcHAncyBvd24gb2JqZWN0czogYSBzaGFyZWQgYnVja2V0IGhvbGRzIG90aGVyIGFwcHMnIGFzc2V0c1xuICAgIC8vIHVuZGVyIHRoZWlyIG93biBwcmVmaXhlcy4gYHMzOkxpc3RCdWNrZXRgIG1ha2VzIGEgbWlzc2luZyBrZXkgYSA0MDQgKHRoZVxuICAgIC8vIG9ubHkgZXJyb3IgdGhlIGludGVncmF0aW9uIG1hcHMpIHJhdGhlciB0aGFuIGEgNDAzLiBJdCBzdGF5cyB1bmNvbmRpdGlvbmVkOlxuICAgIC8vIFMzIGNoZWNrcyBpdCBkdXJpbmcgYSBHZXRPYmplY3QsIHdoZXJlIG5vIGBzMzpwcmVmaXhgIGlzIHByZXNlbnQsIHNvIGFcbiAgICAvLyBwcmVmaXggY29uZGl0aW9uIHdvdWxkIHR1cm4gZXZlcnkgbWlzc2luZyBrZXkgYmFjayBpbnRvIGEgNDAzLlxuICAgIHN0YXRpY0ludGVncmF0aW9uUm9sZS5hZGRUb1BvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbXCJzMzpHZXRPYmplY3RcIl0sXG4gICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgIGAke3RoaXMucHJvcHMuc3RhdGljQXNzZXRzQnVja2V0LmJ1Y2tldEFybn0vJHtzdGF0aWNBc3NldHNPYmplY3RzUGF0dGVybih0aGlzLnByb3BzLnN0YXRpY0Fzc2V0c0tleVByZWZpeCl9YCxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgc3RhdGljSW50ZWdyYXRpb25Sb2xlLmFkZFRvUG9saWN5KFxuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFtcInMzOkxpc3RCdWNrZXRcIl0sXG4gICAgICAgIHJlc291cmNlczogW3RoaXMucHJvcHMuc3RhdGljQXNzZXRzQnVja2V0LmJ1Y2tldEFybl0sXG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiBzdGF0aWNJbnRlZ3JhdGlvblJvbGU7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN0YXRpY0ludGVncmF0aW9ucygpIHtcbiAgICB0aGlzLm5leHRSZXNvdXJjZVxuICAgICAgLmFkZFJlc291cmNlKFwic3RhdGljXCIpXG4gICAgICAuYWRkUmVzb3VyY2UoXCJ7cHJveHkrfVwiKVxuICAgICAgLmFkZE1ldGhvZChcbiAgICAgICAgXCJHRVRcIixcbiAgICAgICAgdGhpcy5jcmVhdGVTM0ludGVncmF0aW9uKHsga2V5OiB0aGlzLnMzS2V5KFwiX25leHQvc3RhdGljL3trZXl9XCIpIH0pLFxuICAgICAgICB0aGlzLmdldFN0YXRpY01ldGhvZE9wdGlvbnMoeyBwcm94eTogdHJ1ZSB9KSxcbiAgICAgICk7XG4gICAgLy8gYWRkIHB1YmxpYyBkaXJlY3RvcnkgZmlsZXMvZGlyZWN0b3JpZXMgdGhhdCBleGlzdCBhdCB0b3AgbGV2ZWwgYnV0IG5lZWQgdG8gZ28gdG8gUzMuXG4gICAgY29uc3QgdW5yb3V0YWJsZTogc3RyaW5nW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHB1YmxpY0RpckVudHJ5IG9mIHRoaXMucHJvcHMucHVibGljRGlyRW50cmllcykge1xuICAgICAgLy8gQSBzcGFjZSBvciBhIG5vbi1BU0NJSSBjaGFyYWN0ZXIgaXMgbGVnYWwgaW4gYHB1YmxpYy9gIGFuZCBpbGxlZ2FsIGluIGFuXG4gICAgICAvLyBBUEkgR2F0ZXdheSByZXNvdXJjZSBwYXRoIHBhcnQsIGFuZCBgYWRkUmVzb3VyY2VgIHRocm93cyDigJQgd2hpY2ggdG9vayB0aGVcbiAgICAgIC8vIHdob2xlIHN5bnRoIGRvd24gZm9yIGFuIGFwcCB0aGF0IGRlcGxveXMgZmluZSBvbiB0aGUgR2xvYmFsIHR5cGVzXG4gICAgICAvLyAoYG5leHQtaW1hZ2UtbGVnYWN5L3VuaWNvZGVgLCB3aG9zZSBgcHVibGljL2AgaG9sZHMgXCJoZWxsbyB3b3JsZC5qcGdcIikuXG4gICAgICAvLyBXYXJuIGFuZCBza2lwIHRoZSBvbmUgZW50cnkgaW5zdGVhZDogdGhhdCBhc3NldCA0MDRzLCB0aGUgYXBwIGRlcGxveXMuXG4gICAgICBpZiAoIUFQSV9QQVRIX1BBUlQudGVzdChwdWJsaWNEaXJFbnRyeS5uYW1lKSkge1xuICAgICAgICB1bnJvdXRhYmxlLnB1c2goYFwiJHtwdWJsaWNEaXJFbnRyeS5uYW1lfVwiYCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKHB1YmxpY0RpckVudHJ5LmlzRGlyZWN0b3J5KSB7XG4gICAgICAgIHRoaXMuYmFzZVJlc291cmNlXG4gICAgICAgICAgLmFkZFJlc291cmNlKHB1YmxpY0RpckVudHJ5Lm5hbWUpXG4gICAgICAgICAgLmFkZFJlc291cmNlKFwie3Byb3h5K31cIilcbiAgICAgICAgICAuYWRkTWV0aG9kKFxuICAgICAgICAgICAgXCJHRVRcIixcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUzNJbnRlZ3JhdGlvbih7XG4gICAgICAgICAgICAgIGtleTogdGhpcy5zM0tleShgJHtwdWJsaWNEaXJFbnRyeS5uYW1lfS97a2V5fWApLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0aGlzLmdldFN0YXRpY01ldGhvZE9wdGlvbnMoeyBwcm94eTogdHJ1ZSB9KSxcbiAgICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5iYXNlUmVzb3VyY2VcbiAgICAgICAgICAuYWRkUmVzb3VyY2UocHVibGljRGlyRW50cnkubmFtZSlcbiAgICAgICAgICAuYWRkTWV0aG9kKFxuICAgICAgICAgICAgXCJHRVRcIixcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUzNJbnRlZ3JhdGlvbih7IGtleTogdGhpcy5zM0tleShwdWJsaWNEaXJFbnRyeS5uYW1lKSB9KSxcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdGljTWV0aG9kT3B0aW9ucygpLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh1bnJvdXRhYmxlLmxlbmd0aCA+IDApIHtcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmcoXG4gICAgICAgIGAke0xPR19QUkVGSVh9IEFuIEFQSSBHYXRld2F5IHJlc291cmNlIHBhdGggcGFydCBvbmx5IGFsbG93cyBgICtcbiAgICAgICAgICBcIlthLXpBLVowLTk6Ll8tJF0sIHNvIHRoZXNlIHRvcC1sZXZlbCBwdWJsaWMvIGVudHJpZXMgZ2V0IG5vIHJlc291cmNlIG9mIFwiICtcbiAgICAgICAgICBcInRoZWlyIG93bjsgdGhlaXIgcmVxdWVzdHMgcmVhY2ggdGhlIHNlcnZlciBmdW5jdGlvbiwgd2hpY2ggcmVhZHMgdGhlbSBcIiArXG4gICAgICAgICAgYGZyb20gUzMgaW5zdGVhZDogJHt1bnJvdXRhYmxlLmpvaW4oXCIsIFwiKX0uIFRvIHNlcnZlIHRoZW0gZGlyZWN0bHksIHJlbmFtZSB0aGVtLCBtb3ZlIHRoZW0gaW50byBhIGAgK1xuICAgICAgICAgIFwicHVibGljLyBzdWJkaXJlY3Rvcnkgd2hvc2Ugb3duIG5hbWUgaXMgZXhwcmVzc2libGUsIG9yIHVzZSBcIiArXG4gICAgICAgICAgXCJOZXh0anNHbG9iYWxGdW5jdGlvbnMgb3IgTmV4dGpzR2xvYmFsQ29udGFpbmVycywgd2hvc2UgQ2xvdWRGcm9udCBcIiArXG4gICAgICAgICAgXCJiZWhhdmlvcnMgY2FuIG1hdGNoIHRoZW0uXCIsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVmaXhlcyBhIHJlcXVlc3QgcGF0aCB3aXRoIHRoZSBrZXkgcHJlZml4IHRoZSBhc3NldHMgd2VyZSB1cGxvYWRlZCB1bmRlcixcbiAgICogc2luY2UgdGhlIFMzIGludGVncmF0aW9ucyBhZGRyZXNzIG9iamVjdHMgYnkga2V5IHJhdGhlciB0aGFuIGJ5IFVSTC5cbiAgICovXG4gIHByaXZhdGUgczNLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBqb2luUGF0aCh0aGlzLnByb3BzLnN0YXRpY0Fzc2V0c0tleVByZWZpeCwga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIEFQSSByZXF1ZXN0IHRvIFMzIHJlcXVlc3QuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL3Jlc3QtYXBpLXBhcmFtZXRlci1tYXBwaW5nLXNvdXJjZXMuaHRtbFxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcGlnYXRld2F5L2xhdGVzdC9kZXZlbG9wZXJndWlkZS9pbnRlZ3JhdGluZy1hcGktd2l0aC1hd3Mtc2VydmljZXMtczMuaHRtbCNhcGktaXRlbXMtaW4tZm9sZGVyLWFzLXMzLW9iamVjdHMtaW4tYnVja2V0XG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZVMzSW50ZWdyYXRpb24oeyBrZXkgfTogeyBrZXk6IHN0cmluZyB9KSB7XG4gICAgY29uc3QgczNJbnRlZ3JhdGlvbiA9IG5ldyBBd3NJbnRlZ3JhdGlvbih7XG4gICAgICBzZXJ2aWNlOiBcInMzXCIsXG4gICAgICBpbnRlZ3JhdGlvbkh0dHBNZXRob2Q6IFwiR0VUXCIsXG4gICAgICBwYXRoOiBgJHt0aGlzLnByb3BzLnN0YXRpY0Fzc2V0c0J1Y2tldC5idWNrZXROYW1lfS8ke2tleX1gLFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICBjcmVkZW50aWFsc1JvbGU6IHRoaXMuc3RhdGljSW50ZWdyYXRpb25Sb2xlLFxuICAgICAgICBwYXNzdGhyb3VnaEJlaGF2aW9yOiBQYXNzdGhyb3VnaEJlaGF2aW9yLldIRU5fTk9fVEVNUExBVEVTLCAvLyByZWNvbW1lbmRlZFxuICAgICAgICByZXF1ZXN0UGFyYW1ldGVyczoge1xuICAgICAgICAgIC8vIFdpdGhvdXQgdGhpcyBTMyBuZXZlciBzZWVzIHRoZSBjb25kaXRpb25hbCByZXF1ZXN0LCBzbyBldmVyeVxuICAgICAgICAgIC8vIHJldmFsaWRhdGlvbiBvZiBhbiBpbW11dGFibGUgYF9uZXh0L3N0YXRpY2AgY2h1bmsgcmUtZG93bmxvYWRzIGl0XG4gICAgICAgICAgLy8gd2l0aCBhIDIwMCBpbnN0ZWFkIG9mIGdldHRpbmcgYSAzMDQuXG4gICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXF1ZXN0LmhlYWRlci5JZi1Ob25lLU1hdGNoXCI6XG4gICAgICAgICAgICBcIm1ldGhvZC5yZXF1ZXN0LmhlYWRlci5JZi1Ob25lLU1hdGNoXCIsXG4gICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXF1ZXN0LmhlYWRlci5JZi1Nb2RpZmllZC1TaW5jZVwiOlxuICAgICAgICAgICAgXCJtZXRob2QucmVxdWVzdC5oZWFkZXIuSWYtTW9kaWZpZWQtU2luY2VcIixcbiAgICAgICAgICAuLi4oa2V5LmluY2x1ZGVzKFwie2tleX1cIilcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIFwiaW50ZWdyYXRpb24ucmVxdWVzdC5wYXRoLmtleVwiOiBcIm1ldGhvZC5yZXF1ZXN0LnBhdGgucHJveHlcIixcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0sXG4gICAgICAgIGludGVncmF0aW9uUmVzcG9uc2VzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgc3RhdHVzQ29kZTogXCIyMDBcIixcbiAgICAgICAgICAgIHJlc3BvbnNlUGFyYW1ldGVyczoge1xuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuQ29udGVudC1UeXBlXCI6XG4gICAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuQ29udGVudC1UeXBlXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LUxlbmd0aFwiOlxuICAgICAgICAgICAgICAgIFwiaW50ZWdyYXRpb24ucmVzcG9uc2UuaGVhZGVyLkNvbnRlbnQtTGVuZ3RoXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5DYWNoZS1Db250cm9sXCI6XG4gICAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuQ2FjaGUtQ29udHJvbFwiLFxuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuRVRhZ1wiOiBcImludGVncmF0aW9uLnJlc3BvbnNlLmhlYWRlci5FVGFnXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5MYXN0LU1vZGlmaWVkXCI6XG4gICAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuTGFzdC1Nb2RpZmllZFwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIC8vIEEgMzA0IGNhcnJpZXMgbm8gYm9keSwgYW5kIGBFVGFnYCBpcyB0aGUgaGVhZGVyIGEgY2xpZW50IG5lZWRzXG4gICAgICAgICAgICAvLyBiYWNrIHRvIGtlZXAgcmV2YWxpZGF0aW5nLlxuICAgICAgICAgICAgc3RhdHVzQ29kZTogXCIzMDRcIixcbiAgICAgICAgICAgIHNlbGVjdGlvblBhdHRlcm46IFwiMzA0XCIsXG4gICAgICAgICAgICByZXNwb25zZVBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNhY2hlLUNvbnRyb2xcIjpcbiAgICAgICAgICAgICAgICBcImludGVncmF0aW9uLnJlc3BvbnNlLmhlYWRlci5DYWNoZS1Db250cm9sXCIsXG4gICAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5FVGFnXCI6IFwiaW50ZWdyYXRpb24ucmVzcG9uc2UuaGVhZGVyLkVUYWdcIixcbiAgICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkxhc3QtTW9kaWZpZWRcIjpcbiAgICAgICAgICAgICAgICBcImludGVncmF0aW9uLnJlc3BvbnNlLmhlYWRlci5MYXN0LU1vZGlmaWVkXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgc3RhdHVzQ29kZTogXCI0MDRcIixcbiAgICAgICAgICAgIHNlbGVjdGlvblBhdHRlcm46IFwiNDA0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8uc3RhdGljSW50ZWdyYXRpb25Qcm9wcyxcbiAgICB9KTtcbiAgICByZXR1cm4gczNJbnRlZ3JhdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0U3RhdGljTWV0aG9kT3B0aW9ucyh7IHByb3h5IH0gPSB7IHByb3h5OiBmYWxzZSB9KTogTWV0aG9kT3B0aW9ucyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlcXVlc3RQYXJhbWV0ZXJzOiB7XG4gICAgICAgIC8vIERlY2xhcmVkIG9wdGlvbmFsIChgZmFsc2VgKTogYSBwbGFpbiBHRVQgY2FycmllcyBuZWl0aGVyLCBhbmRcbiAgICAgICAgLy8gcmVxdWlyaW5nIHRoZW0gd291bGQgNDAwIGl0LlxuICAgICAgICBcIm1ldGhvZC5yZXF1ZXN0LmhlYWRlci5JZi1Ob25lLU1hdGNoXCI6IGZhbHNlLFxuICAgICAgICBcIm1ldGhvZC5yZXF1ZXN0LmhlYWRlci5JZi1Nb2RpZmllZC1TaW5jZVwiOiBmYWxzZSxcbiAgICAgICAgLi4uKHByb3h5ID8geyBcIm1ldGhvZC5yZXF1ZXN0LnBhdGgucHJveHlcIjogdHJ1ZSB9IDoge30pLFxuICAgICAgfSxcbiAgICAgIG1ldGhvZFJlc3BvbnNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgc3RhdHVzQ29kZTogXCIyMDBcIixcbiAgICAgICAgICByZXNwb25zZVBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LVR5cGVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LUxlbmd0aFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNhY2hlLUNvbnRyb2xcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5FVGFnXCI6IHRydWUsXG4gICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuTGFzdC1Nb2RpZmllZFwiOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiBcIjMwNFwiLFxuICAgICAgICAgIHJlc3BvbnNlUGFyYW1ldGVyczoge1xuICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNhY2hlLUNvbnRyb2xcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5FVGFnXCI6IHRydWUsXG4gICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuTGFzdC1Nb2RpZmllZFwiOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiBcIjQwNFwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5zM01ldGhvZE9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbmUgcmVzb3VyY2Ugc3VidHJlZSBwZXIgZnVuY3Rpb24gZ3JvdXAgcGF0dGVybi5cbiAgICpcbiAgICogVW5saWtlIENsb3VkRnJvbnQgdGhpcyBuZWVkcyBubyBvcmRlcmluZzogQVBJIEdhdGV3YXkgbWF0Y2hlcyBvbiBhIHJlc291cmNlXG4gICAqICp0cmVlKiwgc28gYC9hcGkvcmVwb3J0cy97cHJveHkrfWAgYmVhdHMgYC9hcGkve3Byb3h5K31gIGJlYXRzIGAve3Byb3h5K31gXG4gICAqIHN0cnVjdHVyYWxseSwgYW5kIFwibG9uZ2VzdCBwYXR0ZXJuIHdpbnNcIiBjb21lcyBmb3IgZnJlZS4gV2hhdCBkb2VzIG5lZWQgY2FyZVxuICAgKiBpcyBub3QgY3JlYXRpbmcgdGhlIHNhbWUgcGF0aCB0d2ljZSDigJQgdHdvIGdyb3VwcyB1bmRlciBgL2FwaWAgc2hhcmUgdGhlIGBhcGlgXG4gICAqIHJlc291cmNlIOKAlCBzbyBldmVyeSBzZWdtZW50IGdvZXMgdGhyb3VnaCB7QGxpbmsgcmVzb3VyY2VGb3J9LlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVGdW5jdGlvbkdyb3VwSW50ZWdyYXRpb25zKCkge1xuICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMucHJvcHMuZnVuY3Rpb25Hcm91cHMgPz8gW107XG4gICAgY29uc3QgYmVoYXZpb3JzID0gdGhpcy5wcm9wcy5mdW5jdGlvbkdyb3VwQmVoYXZpb3JzID8/IFtdO1xuICAgIGNvbnN0IHVua25vd24gPSBiZWhhdmlvcnMuZmluZChcbiAgICAgIChiZWhhdmlvcikgPT4gIWdyb3Vwcy5zb21lKChncm91cCkgPT4gZ3JvdXAubmFtZSA9PT0gYmVoYXZpb3IuZ3JvdXApLFxuICAgICk7XG4gICAgaWYgKHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7TE9HX1BSRUZJWH0gXFxgZnVuY3Rpb25Hcm91cEJlaGF2aW9yc1xcYCByb3V0ZXMgdG8gZnVuY3Rpb24gZ3JvdXAgYCArXG4gICAgICAgICAgYFwiJHt1bmtub3duLmdyb3VwfVwiLCB3aGljaCBpcyBub3QgaW4gXFxgZnVuY3Rpb25Hcm91cHNcXGAuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IHJvdXRlUmVzb3VyY2VzID0gbmV3IFNldDxJUmVzb3VyY2U+KCk7XG4gICAgLyoqIEVhY2ggc3VidHJlZSdzIGJhc2UgcGF0aCBhbmQgdGhlIGludGVncmF0aW9uIGl0cyBge3Byb3h5K31gIGdvdC4gKi9cbiAgICBjb25zdCBzdWJ0cmVlczogW3N0cmluZ1tdLCBMYW1iZGFJbnRlZ3JhdGlvbl1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgZ3JvdXBzKSB7XG4gICAgICBjb25zdCBpbnRlZ3JhdGlvbiA9IG5ldyBMYW1iZGFJbnRlZ3JhdGlvbihncm91cC5mdW5jdGlvbiwge1xuICAgICAgICByZXNwb25zZVRyYW5zZmVyTW9kZTogUmVzcG9uc2VUcmFuc2Zlck1vZGUuU1RSRUFNLFxuICAgICAgICAvLyBPbmUgQVBJLXdpZGUgcGVybWlzc2lvbiBwZXIgZnVuY3Rpb247IHNlZSBgY3JlYXRlRHluYW1pY0ludGVncmF0aW9uYC5cbiAgICAgICAgc2NvcGVQZXJtaXNzaW9uVG9NZXRob2Q6IGZhbHNlLFxuICAgICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8uZHluYW1pY0ludGVncmF0aW9uUHJvcHMsXG4gICAgICB9KTtcbiAgICAgIC8vIFRoZSBDbG91ZEZyb250IHBhdHRlcm5zIGFyZSBmb3IgdGhlIGVkZ2U7IGEgcmVzb3VyY2UgcGF0aCBwZXIgcm91dGVcbiAgICAgIC8vIGNvdmVycyB3aGF0IHRoZXkgZG8gaGVyZSwgYSBgdHJhaWxpbmdTbGFzaGAgZm9ybSBpbmNsdWRlZCwgc2luY2UgQVBJXG4gICAgICAvLyBHYXRld2F5IG1hdGNoZXMgYC9wcmljaW5nL2Agb24gdGhlIGBwcmljaW5nYCByZXNvdXJjZS5cbiAgICAgIGNvbnN0IG93biA9IGJlaGF2aW9ycy5maWx0ZXIoKGJlaGF2aW9yKSA9PiBiZWhhdmlvci5ncm91cCA9PT0gZ3JvdXAubmFtZSk7XG4gICAgICBjb25zdCBoYXNEYXRhUm91dGVzID0gb3duLnNvbWUoKHsgcGF0dGVybiB9KSA9PlxuICAgICAgICBwYXR0ZXJuLnN0YXJ0c1dpdGgoXCJfbmV4dC9kYXRhL1wiKSxcbiAgICAgICk7XG4gICAgICBmb3IgKGNvbnN0IHJvdXRlIG9mIG5ldyBTZXQob3duLm1hcCgoYmVoYXZpb3IpID0+IGJlaGF2aW9yLnJvdXRlKSkpIHtcbiAgICAgICAgdGhpcy5hc3NlcnRSb3V0YWJsZShyb3V0ZSwgZ3JvdXAubmFtZSk7XG4gICAgICAgIHRoaXMuYXNzZXJ0Tm9QdWJsaWNDb2xsaXNpb24ocm91dGUsIGdyb3VwLm5hbWUpO1xuICAgICAgICBmb3IgKGNvbnN0IHBhdGggb2YgdGhpcy5yZXNvdXJjZVBhdGhzRm9yKHJvdXRlLCBoYXNEYXRhUm91dGVzKSkge1xuICAgICAgICAgIGNvbnN0IHJlc291cmNlID0gdGhpcy5yZXNvdXJjZUZvcihwYXRoKTtcbiAgICAgICAgICByZXNvdXJjZS5hZGRNZXRob2QoXCJBTllcIiwgaW50ZWdyYXRpb24pO1xuICAgICAgICAgIHJvdXRlUmVzb3VyY2VzLmFkZChyZXNvdXJjZSk7XG4gICAgICAgICAgaWYgKHBhdGhbcGF0aC5sZW5ndGggLSAxXSA9PT0gXCJ7cHJveHkrfVwiKSB7XG4gICAgICAgICAgICBzdWJ0cmVlcy5wdXNoKFtwYXRoLnNsaWNlKDAsIC0xKSwgaW50ZWdyYXRpb25dKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQSBwYXJlbnQgdW5kZXIgYW5vdGhlciBncm91cCdzIHN1YnRyZWUgYmVsb25ncyB0byB0aGF0IGdyb3VwLCBhcyBpdCBkb2VzXG4gICAgLy8gYXQgdGhlIGVkZ2UgYW5kIGluIGBhc3NpZ25Sb3V0ZXNUb0dyb3Vwc2A6IHdpdGggYC9hcGkvKipgIGFuZFxuICAgIC8vIGAvYXBpL3JlcG9ydHMvKipgLCBgL2FwaS9yZXBvcnRzYCBpcyB0aGUgYGFwaWAgZ3JvdXAncy4gVGhlIGRlZXBlc3RcbiAgICAvLyBjb3ZlcmluZyBzdWJ0cmVlIHdpbnM7IHRoZSByZXN0IGFyZSBsZWZ0IHRvIHRoZSBkZWZhdWx0IGZ1bmN0aW9uLlxuICAgIGZvciAoY29uc3QgW3Jlc291cmNlLCBwYXRoXSBvZiB0aGlzLmdyb3VwUGFyZW50UmVzb3VyY2VzKSB7XG4gICAgICBpZiAocm91dGVSZXNvdXJjZXMuaGFzKHJlc291cmNlKSkge1xuICAgICAgICB0aGlzLmdyb3VwUGFyZW50UmVzb3VyY2VzLmRlbGV0ZShyZXNvdXJjZSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3Qgb3duZXIgPSBzdWJ0cmVlc1xuICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgIChbYmFzZV0pID0+XG4gICAgICAgICAgICBiYXNlLmxlbmd0aCA8IHBhdGgubGVuZ3RoICYmXG4gICAgICAgICAgICBiYXNlLmV2ZXJ5KChzZWdtZW50LCBpKSA9PiBzZWdtZW50ID09PSBwYXRoW2ldKSxcbiAgICAgICAgKVxuICAgICAgICAuc29ydCgoW2FdLCBbYl0pID0+IGIubGVuZ3RoIC0gYS5sZW5ndGgpWzBdO1xuICAgICAgaWYgKG93bmVyKSB7XG4gICAgICAgIHJlc291cmNlLmFkZE1ldGhvZChcIkFOWVwiLCBvd25lclsxXSk7XG4gICAgICAgIHRoaXMuZ3JvdXBQYXJlbnRSZXNvdXJjZXMuZGVsZXRlKHJlc291cmNlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIGdyb3VwIHBhdHRlcm4gdmFsaWRhdGlvbiBhY2NlcHRzIGV2ZXJ5IGNoYXJhY3RlciBhIENsb3VkRnJvbnQgcGF0aFxuICAgKiBwYXR0ZXJuIGNhbiBob2xkLCBhbmQgQVBJIEdhdGV3YXkncyBwYXRoIHBhcnRzIGhvbGQgZmV3ZXI6IGB+YCwgYEBgLCBgK2AsXG4gICAqIGAmYCBhbmQgcXVvdGVzIHBhc3MgaXQgYW5kIHRoZW4gZmFpbCBgYWRkUmVzb3VyY2VgIHdpdGggYW4gZXJyb3IgdGhhdCBuYW1lc1xuICAgKiBuZWl0aGVyIHRoZSBncm91cCBub3IgdGhlIHBhdHRlcm4uIFNheSB3aGljaCwgYW5kIHdoYXQgdG8gZG8gaW5zdGVhZC5cbiAgICovXG4gIHByaXZhdGUgYXNzZXJ0Um91dGFibGUocm91dGU6IHN0cmluZywgZ3JvdXBOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBzZWdtZW50cyA9IChyb3V0ZS5lbmRzV2l0aChcIi8qKlwiKSA/IHJvdXRlLnNsaWNlKDAsIC0zKSA6IHJvdXRlKVxuICAgICAgLnNwbGl0KFwiL1wiKVxuICAgICAgLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCBpbnZhbGlkID0gc2VnbWVudHMuZmluZCgoc2VnbWVudCkgPT4gIUFQSV9QQVRIX1BBUlQudGVzdChzZWdtZW50KSk7XG4gICAgaWYgKGludmFsaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtMT0dfUFJFRklYfSBmdW5jdGlvbkdyb3VwcyBwYXR0ZXJuIFwiJHtyb3V0ZX1cIiAoZ3JvdXAgXCIke2dyb3VwTmFtZX1cIikgYCArXG4gICAgICAgIGBoYXMgYSBzZWdtZW50LCBcIiR7aW52YWxpZH1cIiwgdGhhdCBhbiBBUEkgR2F0ZXdheSByZXNvdXJjZSBwYXRoIHBhcnQgYCArXG4gICAgICAgIFwiY2Fubm90IGhvbGQ6IG9ubHkgW2EtekEtWjAtOTouXy0kXSBhcmUgYWxsb3dlZC4gUm91dGUgdGhhdCBwYXRoIGZyb20gXCIgK1xuICAgICAgICBcImEgcGF0dGVybiBoaWdoZXIgdXAgdGhlIHRyZWUgKGUuZy4gaXRzIHBhcmVudCBkaXJlY3Rvcnkgd2l0aCBgLyoqYCksIFwiICtcbiAgICAgICAgXCJvciB1c2UgTmV4dGpzR2xvYmFsRnVuY3Rpb25zLCB3aG9zZSBDbG91ZEZyb250IGJlaGF2aW9ycyBhbGxvdyBpdC5cIixcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZnVzZSBhIGdyb3VwIHJvdXRlIHRoYXQgc2hhcmVzIGEgcmVzb3VyY2Ugd2l0aCBhIGBwdWJsaWMvYCBlbnRyeS5cbiAgICpcbiAgICogQSBwdWJsaWMgZGlyZWN0b3J5IGBkb2NzYCBpcyBgZG9jcy97cHJveHkrfWAgd2l0aCBhIGBHRVRgIHRvIFMzLiBgL2RvY3MvKipgXG4gICAqIGFkZHMgYEFOWWAgdG8gdGhhdCBzYW1lIHJlc291cmNlLCBhbmQgQVBJIEdhdGV3YXkgcHJlZmVycyB0aGUgYEdFVGAsIHNvXG4gICAqIGV2ZXJ5IHBhZ2UgbG9hZCB1bmRlciB0aGUgZ3JvdXAgd2VudCB0byBTMzsgYC9kb2NzL2d1aWRlLyoqYCBpcyBhIG1vcmVcbiAgICogc3BlY2lmaWMgcmVzb3VyY2UgaW5zdGVhZCwgYW5kIHRha2VzIGAvZG9jcy9ndWlkZS/igKZgIGF3YXkgZnJvbSB0aGUgcHVibGljXG4gICAqIGZpbGVzLiBBIHB1YmxpYyBmaWxlIGBwcmljaW5nYCBhbmQgYW4gZXhhY3QgYC9wcmljaW5nYCBhcmUgdGhlIHNhbWVcbiAgICogcmVzb3VyY2UgdGhlIHNhbWUgd2F5LiBgTmV4dGpzRGlzdHJpYnV0aW9uYCByZWplY3RzIHRoZSBDbG91ZEZyb250XG4gICAqIGVxdWl2YWxlbnRzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3NlcnROb1B1YmxpY0NvbGxpc2lvbihyb3V0ZTogc3RyaW5nLCBncm91cE5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IGlzU3VidHJlZSA9IHJvdXRlLmVuZHNXaXRoKFwiLyoqXCIpO1xuICAgIGNvbnN0IHNlZ21lbnRzID0gKGlzU3VidHJlZSA/IHJvdXRlLnNsaWNlKDAsIC0zKSA6IHJvdXRlKVxuICAgICAgLnNwbGl0KFwiL1wiKVxuICAgICAgLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMucHJvcHMucHVibGljRGlyRW50cmllcy5maW5kKChpdCkgPT5cbiAgICAgIGl0LmlzRGlyZWN0b3J5XG4gICAgICAgID8gaXQubmFtZSA9PT0gc2VnbWVudHNbMF0gJiYgKGlzU3VidHJlZSB8fCBzZWdtZW50cy5sZW5ndGggPiAxKVxuICAgICAgICA6ICFpc1N1YnRyZWUgJiYgc2VnbWVudHMubGVuZ3RoID09PSAxICYmIGl0Lm5hbWUgPT09IHNlZ21lbnRzWzBdLFxuICAgICk7XG4gICAgaWYgKCFlbnRyeSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtMT0dfUFJFRklYfSBmdW5jdGlvbkdyb3VwcyBwYXR0ZXJuIFwiJHtyb3V0ZX1cIiAoZ3JvdXAgXCIke2dyb3VwTmFtZX1cIikgYCArXG4gICAgICAgIGBvdmVybGFwcyB0aGUgdG9wLWxldmVsIHB1YmxpYy8gJHtlbnRyeS5pc0RpcmVjdG9yeSA/IFwiZGlyZWN0b3J5XCIgOiBcImZpbGVcIn0gYCArXG4gICAgICAgIGBcIiR7ZW50cnkubmFtZX1cIiwgd2hpY2ggQVBJIEdhdGV3YXkgc2VydmVzIGZyb20gUzMgb24gdGhlIHNhbWUgYCArXG4gICAgICAgIGByZXNvdXJjZSBwYXRoLCBzbyBvbmUgb2YgdGhlIHR3byB3b3VsZCBuZXZlciBiZSByZWFjaGVkLiBNb3ZlIHRob3NlIGAgK1xuICAgICAgICBgcHVibGljLyBmaWxlcyB1bmRlciBhIGRpcmVjdG9yeSBubyByb3V0ZSB1c2VzLCBvciBncm91cCBhIGRpZmZlcmVudCBgICtcbiAgICAgICAgYHBhdGguYCxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIHBhdGhzLCBhcyBzZWdtZW50IGFycmF5cywgZm9yIG9uZSBncm91cCBwYXR0ZXJuLlxuICAgKlxuICAgKiBBIHN1YnRyZWUgZ2V0cyBge3Byb3h5K31gIGFzIGl0cyBsYXN0IHNlZ21lbnQgYW5kIHNvIG93bnMgZXZlcnl0aGluZyAqdW5kZXIqXG4gICAqIHRoZSBwYXRoIGJ1dCBub3QgdGhlIHBhdGggaXRzZWxmLCBtYXRjaGluZyBib3RoIHRoZSBDbG91ZEZyb250IHRyYW5zbGF0aW9uIGFuZFxuICAgKiBgYXNzaWduUm91dGVzVG9Hcm91cHNgLiBBbiBleGFjdCBwYXRoIGdldHMgbm8gcHJveHkgc2VnbWVudCwgd2hpY2ggbGVhdmVzIGl0c1xuICAgKiBjaGlsZHJlbiBmYWxsaW5nIHRocm91Z2ggdG8gdGhlIHJvb3QgYHtwcm94eSt9YCDigJQgYWxzbyB0aGUgQ2xvdWRGcm9udCByZXN1bHQuXG4gICAqL1xuICBwcml2YXRlIHJlc291cmNlUGF0aHNGb3Iocm91dGU6IHN0cmluZywgaGFzRGF0YVJvdXRlcz86IGJvb2xlYW4pOiBzdHJpbmdbXVtdIHtcbiAgICBjb25zdCBpc1N1YnRyZWUgPSByb3V0ZS5lbmRzV2l0aChcIi8qKlwiKTtcbiAgICBjb25zdCBiYXNlID0gKGlzU3VidHJlZSA/IHJvdXRlLnNsaWNlKDAsIC0zKSA6IHJvdXRlKVxuICAgICAgLnNwbGl0KFwiL1wiKVxuICAgICAgLmZpbHRlcihCb29sZWFuKTtcbiAgICBjb25zdCBwYXRocyA9IFtpc1N1YnRyZWUgPyBbLi4uYmFzZSwgXCJ7cHJveHkrfVwiXSA6IGJhc2VdO1xuICAgIGlmIChoYXNEYXRhUm91dGVzKSB7XG4gICAgICAvLyBgPGJ1aWxkSWQ+YCBjaGFuZ2VzIGV2ZXJ5IGJ1aWxkLCBzbyBpdCBpcyBhIHBhdGggcGFyYW1ldGVyIHJhdGhlciB0aGFuIGFcbiAgICAgIC8vIGxpdGVyYWwg4oCUIHRoZSBpbnRlZ3JhdGlvbiBpZ25vcmVzIGl0LCB0aGUgcnVudGltZSByZWFkcyBpdCBvZmYgdGhlIFVSTC5cbiAgICAgIC8vIFVubGlrZSBDbG91ZEZyb250J3MgYCpgLCB3aGljaCBgTmV4dGpzRGlzdHJpYnV0aW9uYCBoYWQgdG8gcmVwbGFjZSB3aXRoXG4gICAgICAvLyB0aGUgbGl0ZXJhbCBJRCwgYSBwYXRoIHBhcmFtZXRlciBpcyBleGFjdGx5IG9uZSBzZWdtZW50LCBzb1xuICAgICAgLy8gYC9fbmV4dC9kYXRhL3tidWlsZElkfS9ibG9nL3twcm94eSt9YCBjYW5ub3QgY2FwdHVyZSBhbm90aGVyIGdyb3VwJ3NcbiAgICAgIC8vIGAvX25leHQvZGF0YS88aWQ+L2RvY3MvYmxvZy/igKZgLiBBIHJlcXVlc3QgZm9yIGFuIG9sZCBidWlsZCBJRCByZWFjaGVzXG4gICAgICAvLyB0aGUgZ3JvdXAsIHdoaWNoIDQwNHMgaXQganVzdCBhcyB0aGUgZGVmYXVsdCBmdW5jdGlvbiB3b3VsZC5cbiAgICAgIGNvbnN0IGRhdGFQcmVmaXggPSBbXCJfbmV4dFwiLCBcImRhdGFcIiwgXCJ7YnVpbGRJZH1cIl07XG4gICAgICBwYXRocy5wdXNoKFxuICAgICAgICBpc1N1YnRyZWVcbiAgICAgICAgICA/IFsuLi5kYXRhUHJlZml4LCAuLi5iYXNlLCBcIntwcm94eSt9XCJdXG4gICAgICAgICAgOiBbXG4gICAgICAgICAgICAgIC4uLmRhdGFQcmVmaXgsXG4gICAgICAgICAgICAgIC4uLmJhc2Uuc2xpY2UoMCwgLTEpLFxuICAgICAgICAgICAgICBgJHtiYXNlW2Jhc2UubGVuZ3RoIC0gMV19Lmpzb25gLFxuICAgICAgICAgICAgXSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBwYXRocztcbiAgfVxuXG4gIC8qKiBXYWxrIG9yIGNyZWF0ZSBhIHJlc291cmNlIHBhdGgsIHJldXNpbmcgd2hhdGV2ZXIgYWxyZWFkeSBleGlzdHMuICovXG4gIHByaXZhdGUgcmVzb3VyY2VGb3Ioc2VnbWVudHM6IHN0cmluZ1tdKTogSVJlc291cmNlIHtcbiAgICBsZXQgcmVzb3VyY2UgPSB0aGlzLmJhc2VSZXNvdXJjZTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgc2VnbWVudF0gb2Ygc2VnbWVudHMuZW50cmllcygpKSB7XG4gICAgICBjb25zdCBleGlzdGluZyA9IHJlc291cmNlLmdldFJlc291cmNlKHNlZ21lbnQpO1xuICAgICAgcmVzb3VyY2UgPSBleGlzdGluZyA/PyByZXNvdXJjZS5hZGRSZXNvdXJjZShzZWdtZW50KTtcbiAgICAgIGlmICghZXhpc3RpbmcgJiYgaW5kZXggPCBzZWdtZW50cy5sZW5ndGggLSAxKSB7XG4gICAgICAgIHRoaXMuZ3JvdXBQYXJlbnRSZXNvdXJjZXMuc2V0KHJlc291cmNlLCBzZWdtZW50cy5zbGljZSgwLCBpbmRleCArIDEpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc291cmNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBMYW1iZGEgUHJveHkgaW50ZWdyYXRpb24gZm9yIGFsbCBvdGhlciByb3V0ZXNcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY0ludGVncmF0aW9uKHNlcnZlckZ1bmN0aW9uOiBJRnVuY3Rpb24pIHtcbiAgICAvLyBBbGwgb3RoZXIgcm91dGVzIHVzZSBzdHJlYW1pbmcgZm9yIGJldHRlciBwZXJmb3JtYW5jZS5cbiAgICAvL1xuICAgIC8vIGBzY29wZVBlcm1pc3Npb25Ub01ldGhvZDogZmFsc2VgIGdyYW50cyB0aGUgZnVuY3Rpb24gb25lIHBlcm1pc3Npb24gZm9yXG4gICAgLy8gdGhpcyBBUEkncyBleGVjdXRlLWFwaSBBUk4gKGA8YXBpPi8qLyovKmApIGluc3RlYWQgb2YgdHdvIHBlciBtZXRob2QgKHRoZVxuICAgIC8vIG1ldGhvZCBhbmQgaXRzIGNvbnNvbGUgdGVzdC1pbnZva2UpLiBFdmVyeSBncm91cCBhZGRzIHJlc291cmNlcyB0aGF0IHRoZVxuICAgIC8vIGRlZmF1bHQgZnVuY3Rpb24gc3RpbGwgYW5zd2VycyBmb3IgaXRzIHBhcmVudHMgYW5kIGRhdGEgcm91dGVzLCBhbmQgYXRcbiAgICAvLyB+MzUwIGJ5dGVzIGEgc3RhdGVtZW50IHRoZSBwZXItbWV0aG9kIHBvbGljeSBvdXRncm93cyBMYW1iZGEncyAyMCBLQlxuICAgIC8vIHJlc291cmNlLXBvbGljeSBjYXAgYWZ0ZXIgYSBmZXcgZG96ZW4gYEFOWWAgbWV0aG9kcywgZmFpbGluZyB0aGUgZGVwbG95LlxuICAgIGNvbnN0IHN0cmVhbWluZ0ludGVncmF0aW9uID0gbmV3IExhbWJkYUludGVncmF0aW9uKHNlcnZlckZ1bmN0aW9uLCB7XG4gICAgICByZXNwb25zZVRyYW5zZmVyTW9kZTogUmVzcG9uc2VUcmFuc2Zlck1vZGUuU1RSRUFNLFxuICAgICAgc2NvcGVQZXJtaXNzaW9uVG9NZXRob2Q6IGZhbHNlLFxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmR5bmFtaWNJbnRlZ3JhdGlvblByb3BzLFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIGNhdGNoLWFsbCByb3V0ZXMgd2l0aCBzdHJlYW1pbmcgaW50ZWdyYXRpb24gZm9yIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xuICAgIHRoaXMuYmFzZVJlc291cmNlLmFkZE1ldGhvZChcIkFOWVwiLCBzdHJlYW1pbmdJbnRlZ3JhdGlvbik7XG4gICAgZm9yIChjb25zdCByZXNvdXJjZSBvZiB0aGlzLmdyb3VwUGFyZW50UmVzb3VyY2VzLmtleXMoKSkge1xuICAgICAgcmVzb3VyY2UuYWRkTWV0aG9kKFwiQU5ZXCIsIHN0cmVhbWluZ0ludGVncmF0aW9uKTtcbiAgICB9XG4gICAgY29uc3QgcHJveHlSZXNvdXJjZSA9IHRoaXMuYmFzZVJlc291cmNlLmFkZFJlc291cmNlKFwie3Byb3h5K31cIik7XG4gICAgcHJveHlSZXNvdXJjZS5hZGRNZXRob2QoXCJBTllcIiwgc3RyZWFtaW5nSW50ZWdyYXRpb24pO1xuICB9XG59XG4iXX0=