cdk-nextjs 0.6.2 → 0.7.1

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 (263) hide show
  1. package/.jsii +2404 -2723
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1681 -1930
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
  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 +667 -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 +1551 -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 +857 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +863 -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 +8 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
  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/prune-cache-bucket.d.ts +7 -3
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  88. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  92. package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
  93. package/lib/lambdas/post-deploy/prune-s3.js +41 -12
  94. package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
  95. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  96. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  103. package/lib/nextjs-api.d.ts +102 -18
  104. package/lib/nextjs-api.js +338 -38
  105. package/lib/nextjs-api.test.js +537 -1
  106. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  107. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  108. package/lib/nextjs-build/nextjs-build.js +684 -327
  109. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  110. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  111. package/lib/nextjs-build/patch-fetch.js +1 -1
  112. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  113. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  114. package/lib/nextjs-cache.d.ts +82 -4
  115. package/lib/nextjs-cache.js +186 -10
  116. package/lib/nextjs-cache.test.js +176 -1
  117. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  118. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  120. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  121. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  122. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  123. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  124. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  125. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  126. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  127. package/lib/nextjs-distribution.d.ts +194 -23
  128. package/lib/nextjs-distribution.js +535 -62
  129. package/lib/nextjs-distribution.test.d.ts +1 -0
  130. package/lib/nextjs-distribution.test.js +697 -0
  131. package/lib/nextjs-post-deploy.d.ts +13 -5
  132. package/lib/nextjs-post-deploy.js +13 -10
  133. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  134. package/lib/nextjs-post-deploy.test.js +34 -0
  135. package/lib/nextjs-static-assets.d.ts +17 -4
  136. package/lib/nextjs-static-assets.js +22 -5
  137. package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
  138. package/lib/root-constructs/nextjs-base-construct.js +139 -47
  139. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  140. package/lib/root-constructs/nextjs-global-containers.js +20 -71
  141. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  142. package/lib/root-constructs/nextjs-global-functions.js +52 -70
  143. package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
  144. package/lib/root-constructs/nextjs-regional-containers.js +8 -15
  145. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  146. package/lib/root-constructs/nextjs-regional-functions.js +8 -26
  147. package/lib/runtime/api-gateway-path.d.ts +34 -0
  148. package/lib/runtime/api-gateway-path.js +71 -0
  149. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  150. package/lib/runtime/api-gateway-path.test.js +65 -0
  151. package/lib/runtime/case-redirect.d.ts +22 -0
  152. package/lib/runtime/case-redirect.js +63 -0
  153. package/lib/runtime/case-redirect.test.d.ts +1 -0
  154. package/lib/runtime/case-redirect.test.js +32 -0
  155. package/lib/runtime/core.d.ts +234 -0
  156. package/lib/runtime/core.js +1216 -0
  157. package/lib/runtime/core.test.d.ts +1 -0
  158. package/lib/runtime/core.test.js +1686 -0
  159. package/lib/runtime/deployment-root.d.ts +13 -0
  160. package/lib/runtime/deployment-root.js +29 -0
  161. package/lib/runtime/dispatch.d.ts +331 -0
  162. package/lib/runtime/dispatch.js +751 -0
  163. package/lib/runtime/dispatch.test.d.ts +1 -0
  164. package/lib/runtime/dispatch.test.js +853 -0
  165. package/lib/runtime/entrypoints.d.ts +57 -0
  166. package/lib/runtime/entrypoints.js +115 -0
  167. package/lib/runtime/http/abort-signal.d.ts +6 -0
  168. package/lib/runtime/http/abort-signal.js +19 -0
  169. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  170. package/lib/runtime/http/abort-signal.test.js +49 -0
  171. package/lib/runtime/http/node-server.d.ts +38 -0
  172. package/lib/runtime/http/node-server.js +99 -0
  173. package/lib/runtime/http/node-server.test.d.ts +1 -0
  174. package/lib/runtime/http/node-server.test.js +96 -0
  175. package/lib/runtime/http/node-sink.d.ts +16 -0
  176. package/lib/runtime/http/node-sink.js +48 -0
  177. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  178. package/lib/runtime/http/node-sink.test.js +66 -0
  179. package/lib/runtime/http/request.d.ts +62 -0
  180. package/lib/runtime/http/request.js +134 -0
  181. package/lib/runtime/http/request.test.d.ts +1 -0
  182. package/lib/runtime/http/request.test.js +103 -0
  183. package/lib/runtime/http/response.d.ts +77 -0
  184. package/lib/runtime/http/response.js +229 -0
  185. package/lib/runtime/http/response.test.d.ts +1 -0
  186. package/lib/runtime/http/response.test.js +178 -0
  187. package/lib/runtime/http/sink.d.ts +73 -0
  188. package/lib/runtime/http/sink.js +188 -0
  189. package/lib/runtime/http/sink.test.d.ts +1 -0
  190. package/lib/runtime/http/sink.test.js +257 -0
  191. package/lib/runtime/image-utils.d.ts +78 -0
  192. package/lib/runtime/image-utils.js +129 -0
  193. package/lib/runtime/image-utils.test.d.ts +1 -0
  194. package/lib/runtime/image-utils.test.js +237 -0
  195. package/lib/runtime/image.d.ts +76 -0
  196. package/lib/runtime/image.js +296 -0
  197. package/lib/runtime/image.test.d.ts +1 -0
  198. package/lib/runtime/image.test.js +405 -0
  199. package/lib/runtime/lambda-event.d.ts +4 -0
  200. package/lib/runtime/lambda-event.js +113 -0
  201. package/lib/runtime/lambda-event.test.d.ts +1 -0
  202. package/lib/runtime/lambda-event.test.js +119 -0
  203. package/lib/runtime/lambda.mjs +41600 -0
  204. package/lib/runtime/load-module.d.ts +8 -0
  205. package/lib/runtime/load-module.js +35 -0
  206. package/lib/runtime/manifest.d.ts +215 -0
  207. package/lib/runtime/manifest.js +118 -0
  208. package/lib/runtime/middleware.d.ts +43 -0
  209. package/lib/runtime/middleware.js +113 -0
  210. package/lib/runtime/middleware.test.d.ts +1 -0
  211. package/lib/runtime/middleware.test.js +259 -0
  212. package/lib/runtime/next-modules.d.ts +71 -0
  213. package/lib/runtime/next-modules.js +144 -0
  214. package/lib/runtime/next-modules.test.d.ts +1 -0
  215. package/lib/runtime/next-modules.test.js +34 -0
  216. package/lib/runtime/public-files.d.ts +32 -0
  217. package/lib/runtime/public-files.js +117 -0
  218. package/lib/runtime/public-files.test.d.ts +1 -0
  219. package/lib/runtime/public-files.test.js +97 -0
  220. package/lib/runtime/server.mjs +41593 -0
  221. package/lib/runtime/static-files.d.ts +50 -0
  222. package/lib/runtime/static-files.js +266 -0
  223. package/lib/runtime/static-files.test.d.ts +1 -0
  224. package/lib/runtime/static-files.test.js +118 -0
  225. package/lib/runtime/util.d.ts +28 -0
  226. package/lib/runtime/util.js +79 -0
  227. package/lib/utils/base-path.d.ts +106 -13
  228. package/lib/utils/base-path.js +254 -41
  229. package/lib/utils/base-path.test.js +219 -51
  230. package/lib/utils/get-architecture.d.ts +7 -8
  231. package/lib/utils/get-architecture.js +12 -13
  232. package/lib/utils/zip-directory.d.ts +14 -0
  233. package/lib/utils/zip-directory.js +121 -0
  234. package/lib/utils/zip-directory.test.d.ts +1 -0
  235. package/lib/utils/zip-directory.test.js +99 -0
  236. package/package.json +22 -3
  237. package/scripts/capture-adapter-fixture.mjs +325 -0
  238. package/scripts/e2e-deploy.sh +398 -0
  239. package/scripts/e2e-harness/README.md +707 -0
  240. package/scripts/e2e-harness/app.js +370 -0
  241. package/scripts/e2e-harness/common.sh +249 -0
  242. package/scripts/e2e-harness/screen.mjs +302 -0
  243. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  244. package/scripts/e2e-harness/type-filters.mjs +47 -0
  245. package/scripts/e2e-logs.sh +75 -0
  246. package/scripts/e2e-offline.sh +91 -0
  247. package/scripts/e2e-sweep.sh +370 -0
  248. package/scripts/e2e-warm.sh +114 -0
  249. package/scripts/zero-config-build.mjs +418 -0
  250. package/docs/1k-concurrent-users-executions.png +0 -0
  251. package/docs/plans/adapter-runtime-release.md +0 -362
  252. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  253. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  254. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  255. package/lib/image-optimization/handler-utils.d.ts +0 -34
  256. package/lib/image-optimization/handler-utils.js +0 -83
  257. package/lib/image-optimization/handler-utils.test.js +0 -178
  258. package/lib/nextjs-build/functions.Dockerfile +0 -31
  259. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  260. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  261. package/lib/utils/experimental-flags.d.ts +0 -24
  262. package/lib/utils/experimental-flags.js +0 -30
  263. /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.2" };
25
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsApi", version: "0.7.1" };
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,7 +165,12 @@ 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
  }
@@ -102,13 +197,21 @@ class NextjsApi extends constructs_1.Construct {
102
197
  const staticIntegrationRole = new aws_iam_1.Role(this, "StaticIntegrationRole", {
103
198
  assumedBy: new aws_iam_1.ServicePrincipal("apigateway.amazonaws.com"),
104
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.
105
205
  staticIntegrationRole.addToPolicy(new aws_iam_1.PolicyStatement({
106
- actions: ["s3:GetObject", "s3:ListBucket"],
206
+ actions: ["s3:GetObject"],
107
207
  resources: [
108
- this.props.staticAssetsBucket.bucketArn,
109
- `${this.props.staticAssetsBucket.bucketArn}/*`,
208
+ `${this.props.staticAssetsBucket.bucketArn}/${(0, nextjs_static_assets_1.staticAssetsObjectsPattern)(this.props.staticAssetsKeyPrefix)}`,
110
209
  ],
111
210
  }));
211
+ staticIntegrationRole.addToPolicy(new aws_iam_1.PolicyStatement({
212
+ actions: ["s3:ListBucket"],
213
+ resources: [this.props.staticAssetsBucket.bucketArn],
214
+ }));
112
215
  return staticIntegrationRole;
113
216
  }
114
217
  createStaticIntegrations() {
@@ -117,7 +220,17 @@ class NextjsApi extends constructs_1.Construct {
117
220
  .addResource("{proxy+}")
118
221
  .addMethod("GET", this.createS3Integration({ key: this.s3Key("_next/static/{key}") }), this.getStaticMethodOptions({ proxy: true }));
119
222
  // add public directory files/directories that exist at top level but need to go to S3.
223
+ const unroutable = [];
120
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
+ }
121
234
  if (publicDirEntry.isDirectory) {
122
235
  this.baseResource
123
236
  .addResource(publicDirEntry.name)
@@ -132,6 +245,15 @@ class NextjsApi extends constructs_1.Construct {
132
245
  .addMethod("GET", this.createS3Integration({ key: this.s3Key(publicDirEntry.name) }), this.getStaticMethodOptions());
133
246
  }
134
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
+ }
135
257
  }
136
258
  /**
137
259
  * Prefixes a request path with the key prefix the assets were uploaded under,
@@ -153,11 +275,18 @@ class NextjsApi extends constructs_1.Construct {
153
275
  options: {
154
276
  credentialsRole: this.staticIntegrationRole,
155
277
  passthroughBehavior: aws_apigateway_1.PassthroughBehavior.WHEN_NO_TEMPLATES, // recommended
156
- requestParameters: key.includes("{key}")
157
- ? {
158
- "integration.request.path.key": "method.request.path.proxy",
159
- }
160
- : 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
+ },
161
290
  integrationResponses: [
162
291
  {
163
292
  statusCode: "200",
@@ -169,6 +298,17 @@ class NextjsApi extends constructs_1.Construct {
169
298
  "method.response.header.Last-Modified": "integration.response.header.Last-Modified",
170
299
  },
171
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
+ },
172
312
  {
173
313
  statusCode: "404",
174
314
  selectionPattern: "404",
@@ -181,11 +321,13 @@ class NextjsApi extends constructs_1.Construct {
181
321
  }
182
322
  getStaticMethodOptions({ proxy } = { proxy: false }) {
183
323
  return {
184
- requestParameters: proxy
185
- ? {
186
- "method.request.path.proxy": true,
187
- }
188
- : 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
+ },
189
331
  methodResponses: [
190
332
  {
191
333
  statusCode: "200",
@@ -197,6 +339,14 @@ class NextjsApi extends constructs_1.Construct {
197
339
  "method.response.header.Last-Modified": true,
198
340
  },
199
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
+ },
200
350
  {
201
351
  statusCode: "404",
202
352
  },
@@ -205,38 +355,188 @@ class NextjsApi extends constructs_1.Construct {
205
355
  };
206
356
  }
207
357
  /**
208
- * 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}.
209
365
  */
210
- createImageIntegration(imageFunction) {
211
- // imageFunction is assumed to be the dedicated, streaming-capable image
212
- // Lambda (see its doc comment); override responseTransferMode via
213
- // imageIntegrationProps if that assumption doesn't hold for a custom
214
- // imageFunction, otherwise API Gateway returns a 502. Deliberately
215
- // doesn't inherit dynamicIntegrationProps: that's for serverFunction,
216
- // a different Lambda with different (and possibly conflicting, e.g.
217
- // BUFFERED for a non-streaming Lambda Web Adapter setup) streaming
218
- // requirements than the always-streaming dedicated image Lambda.
219
- const imageIntegration = new aws_apigateway_1.LambdaIntegration(imageFunction, {
220
- responseTransferMode: aws_apigateway_1.ResponseTransferMode.STREAM,
221
- ...this.props.overrides?.imageIntegrationProps,
222
- });
223
- const imageResource = this.nextResource.addResource("image");
224
- 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;
225
514
  }
226
515
  /**
227
516
  * Create Lambda Proxy integration for all other routes
228
517
  */
229
518
  createDynamicIntegration(serverFunction) {
230
- // 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.
231
527
  const streamingIntegration = new aws_apigateway_1.LambdaIntegration(serverFunction, {
232
528
  responseTransferMode: aws_apigateway_1.ResponseTransferMode.STREAM,
529
+ scopePermissionToMethod: false,
233
530
  ...this.props.overrides?.dynamicIntegrationProps,
234
531
  });
235
532
  // Add catch-all routes with streaming integration for server-side rendering
236
533
  this.baseResource.addMethod("ANY", streamingIntegration);
534
+ for (const resource of this.groupParentResources.keys()) {
535
+ resource.addMethod("ANY", streamingIntegration);
536
+ }
237
537
  const proxyResource = this.baseResource.addResource("{proxy+}");
238
538
  proxyResource.addMethod("ANY", streamingIntegration);
239
539
  }
240
540
  }
241
541
  exports.NextjsApi = NextjsApi;
242
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9uZXh0anMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSw2Q0FBMEM7QUFDMUMsK0RBWW9DO0FBRXBDLGlEQUs2QjtBQUc3QiwyQ0FBdUM7QUFFdkMsaURBQWdFO0FBOERoRTs7R0FFRztBQUNILE1BQWEsU0FBVSxTQUFRLHNCQUFTOztJQUN0Qzs7T0FFRztJQUNhLEdBQUcsQ0FBVTtJQUU3Qjs7Ozs7Ozs7T0FRRztJQUNILElBQUksR0FBRztRQUNMLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1FBQ3pDLHdFQUF3RTtRQUN4RSxvRUFBb0U7UUFDcEUsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxZQUFZO1lBQ25DLENBQUMsQ0FBQztnQkFDRSxXQUFXLFlBQVksQ0FBQyxVQUFVLEVBQUU7Z0JBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsUUFBUTthQUN6RDtZQUNILENBQUMsQ0FBQztnQkFDRSxXQUFXLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxnQkFBZ0IsbUJBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxnQkFBZ0I7Z0JBQ2xGLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLFNBQVM7YUFDbkMsQ0FBQztRQUNOLE9BQU8sSUFBQSxvQkFBUSxFQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRWdCLFlBQVksQ0FBWTtJQUN4QixZQUFZLENBQVk7SUFDeEIsS0FBSyxDQUFpQjtJQUMvQixxQkFBcUIsQ0FBUTtJQUVyQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXFCO1FBQzdELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFB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LElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdELGFBQWEsQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOztPQUVHO0lBQ0ssd0JBQXdCLENBQUMsY0FBeUI7UUFDeEQsd0RBQXdEO1FBQ3hELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxrQ0FBaUIsQ0FBQyxjQUFjLEVBQUU7WUFDakUsb0JBQW9CLEVBQUUscUNBQW9CLENBQUMsTUFBTTtZQUNqRCxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLHVCQUF1QjtTQUNqRCxDQUFDLENBQUM7UUFFSCw0RUFBNEU7UUFDNUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLG9CQUFvQixDQUFDLENBQUM7UUFDekQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEUsYUFBYSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztJQUN2RCxDQUFDOztBQXBRSCw4QkFxUUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTaXplLCBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHtcbiAgUmVzdEFwaSxcbiAgTGFtYmRhSW50ZWdyYXRpb24sXG4gIEF3c0ludGVncmF0aW9uLFxuICBNZXRob2RPcHRpb25zLFxuICBJUmVzb3VyY2UsXG4gIEVuZHBvaW50VHlwZSxcbiAgUmVzdEFwaVByb3BzLFxuICBBd3NJbnRlZ3JhdGlvblByb3BzLFxuICBMYW1iZGFJbnRlZ3JhdGlvbk9wdGlvbnMsXG4gIFBhc3N0aHJvdWdoQmVoYXZpb3IsXG4gIFJlc3BvbnNlVHJhbnNmZXJNb2RlLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXlcIjtcbmltcG9ydCB7IElWcGMgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuaW1wb3J0IHtcbiAgUm9sZSxcbiAgU2VydmljZVByaW5jaXBhbCxcbiAgUG9saWN5U3RhdGVtZW50LFxuICBJUm9sZSxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7IElGdW5jdGlvbiB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBJQnVja2V0IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IFB1YmxpY0RpckVudHJ5IH0gZnJvbSBcIi4vbmV4dGpzLWJ1aWxkL25leHRqcy1idWlsZFwiO1xuaW1wb3J0IHsgam9pblBhdGgsIG5vcm1hbGl6ZUJhc2VQYXRoIH0gZnJvbSBcIi4vdXRpbHMvYmFzZS1wYXRoXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzQXBpT3ZlcnJpZGVzIHtcbiAgcmVhZG9ubHkgcmVzdEFwaVByb3BzPzogUmVzdEFwaVByb3BzO1xuICByZWFkb25seSBzdGF0aWNJbnRlZ3JhdGlvblByb3BzPzogQXdzSW50ZWdyYXRpb25Qcm9wcztcbiAgcmVhZG9ubHkgczNNZXRob2RPcHRpb25zPzogTWV0aG9kT3B0aW9ucztcbiAgcmVhZG9ubHkgZHluYW1pY0ludGVncmF0aW9uUHJvcHM/OiBMYW1iZGFJbnRlZ3JhdGlvbk9wdGlvbnM7XG4gIHJlYWRvbmx5IGltYWdlSW50ZWdyYXRpb25Qcm9wcz86IExhbWJkYUludGVncmF0aW9uT3B0aW9ucztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOZXh0anNBcGlQcm9wcyB7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBiYXNlIHBhdGggZm9yIHRoZSBhcHBsaWNhdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgYmFzZVBhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBPdmVycmlkZSBwcm9wcyBmb3IgZXZlcnkgY29uc3RydWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgb3ZlcnJpZGVzPzogTmV4dGpzQXBpT3ZlcnJpZGVzO1xuICAvKipcbiAgICogUGF0aCB0byBkaXJlY3Rvcnkgb2YgTmV4dC5qcyBhcHAncyBwdWJsaWMgZGlyZWN0b3J5LiBVc2VkIHRvIGFkZCByZXNvdXJjZXNcbiAgICogdG8gQVBJIEdhdGV3YXkgUkVTVCBBUEkgZm9yIHB1YmxpYyBkaXJlY3RvcnkgdG8gZ28gZGlyZWN0bHkgdG8gUzMuXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNEaXJFbnRyaWVzOiBQdWJsaWNEaXJFbnRyeVtdO1xuICAvKipcbiAgICogUmVxdWlyZWQgaWYgYE5leHRqc1JlZ2lvbmFsRnVuY3Rpb25zYC4gVGhlIExhbWJkYSBmdW5jdGlvbiBmb3Igc2VydmVyLXNpZGUgcmVuZGVyaW5nXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJGdW5jdGlvbj86IElGdW5jdGlvbjtcbiAgLyoqXG4gICAqIERlZGljYXRlZCBpbWFnZSBvcHRpbWl6YXRpb24gTGFtYmRhIGZvciB0aGUgYF9uZXh0L2ltYWdlYCByb3V0ZS4gV2hlblxuICAgKiBvbWl0dGVkLCBubyBgX25leHQvaW1hZ2VgIHJlc291cmNlIGlzIGNyZWF0ZWQgYW5kIHRob3NlIHJlcXVlc3RzIGZhbGxcbiAgICogdGhyb3VnaCB0byBgc2VydmVyRnVuY3Rpb25gIHZpYSB0aGUgYHtwcm94eSt9YCBjYXRjaC1hbGwuXG4gICAqXG4gICAqIFdoZW4gcHJvdmlkZWQsIGl0IGlzIGFzc3VtZWQgdG8gc3VwcG9ydCBMYW1iZGEgcmVzcG9uc2Ugc3RyZWFtaW5nIChhcyB0aGVcbiAgICogZGVkaWNhdGVkIGltYWdlIExhbWJkYSB0aGlzIHBhY2thZ2UgYnVpbGRzIGRvZXMpIGFuZCBpcyBpbnZva2VkIHdpdGhcbiAgICogYFJlc3BvbnNlVHJhbnNmZXJNb2RlLlNUUkVBTWAgYWNjb3JkaW5nbHkuIElmIHlvdSBzdXBwbHkgYSBjdXN0b21cbiAgICogYGltYWdlRnVuY3Rpb25gIHRoYXQgZG9lc24ndCBzdXBwb3J0IHN0cmVhbWluZywgb3ZlcnJpZGVcbiAgICogYHJlc3BvbnNlVHJhbnNmZXJNb2RlYCB0byBgQlVGRkVSRURgIHZpYSBgb3ZlcnJpZGVzLmltYWdlSW50ZWdyYXRpb25Qcm9wc2AsXG4gICAqIG90aGVyd2lzZSBBUEkgR2F0ZXdheSByZXR1cm5zIGEgNTAyLlxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2VGdW5jdGlvbj86IElGdW5jdGlvbjtcbiAgLyoqXG4gICAqIFRoZSBTMyBidWNrZXQgY29udGFpbmluZyBzdGF0aWMgYXNzZXRzXG4gICAqL1xuICByZWFkb25seSBzdGF0aWNBc3NldHNCdWNrZXQ6IElCdWNrZXQ7XG4gIC8qKlxuICAgKiBTMyBrZXkgcHJlZml4IHRoZSBzdGF0aWMgYXNzZXRzIHdlcmUgdXBsb2FkZWQgdW5kZXIsIGkuZS5cbiAgICogYE5leHRqc1N0YXRpY0Fzc2V0cy5rZXlQcmVmaXhgLCB3aGljaCBuYW1lc3BhY2VzIGEgc2hhcmVkIGJ1Y2tldC5cbiAgICpcbiAgICogSW5kZXBlbmRlbnQgb2YgYGJhc2VQYXRoYCBhYm92ZTogdGhhdCBvbmUgaXMgdGhlIFVSTCBwcmVmaXggdGhlIFJFU1QgQVBJXG4gICAqIHNlcnZlcyB0aGUgYXBwIGF0IChjb21tb25seSB0aGUgQVBJIEdhdGV3YXkgc3RhZ2UpLCB3aGlsZSB0aGlzIG9uZSBpcyB3aGVyZVxuICAgKiB0aGUgb2JqZWN0cyBsaXZlIGluIHRoZSBidWNrZXQuIGBfbmV4dC9zdGF0aWNgIGFuZCBwdWJsaWMgZGlyZWN0b3J5XG4gICAqIHJlcXVlc3RzIGFyZSBtYXBwZWQgdG8gUzMga2V5cyBkaXJlY3RseSwgc28gdGhleSA0MDQgdW5sZXNzIHRoaXMgcHJlZml4IGlzXG4gICAqIGFwcGxpZWQuXG4gICAqL1xuICByZWFkb25seSBzdGF0aWNBc3NldHNLZXlQcmVmaXg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBbRnV0dXJlXSBSZXF1aXJlZCBpZiBgTmV4dGpzUmVnaW9uYWxDb250YWluZXJzYC4gVlBDIHRvIGNyZWF0ZSBWUEMgTGluayBhbmQgRUNTIFNlcnZpY2UgRGlzY292ZXJ5XG4gICAqL1xuICByZWFkb25seSB2cGM/OiBJVnBjO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gQVBJIEdhdGV3YXkgUkVTVCBBUEkgZm9yIE5leHQuanMgYXBwbGljYXRpb25zXG4gKi9cbmV4cG9ydCBjbGFzcyBOZXh0anNBcGkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogVGhlIEFQSSBHYXRld2F5IFJFU1QgQVBJXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYXBpOiBSZXN0QXBpO1xuXG4gIC8qKlxuICAgKiBQdWJsaWMgVVJMIG9mIHRoZSBhcHAsIGluY2x1ZGluZyBldmVyeSBwYXRoIHNlZ21lbnQgdGhlIEFQSSBuZXN0cyBpdCB1bmRlci5cbiAgICogUHJlZmVycyBhIGN1c3RvbSBkb21haW4gY29uZmlndXJlZCB0aHJvdWdoIGBvdmVycmlkZXMucmVzdEFwaVByb3BzLmRvbWFpbk5hbWVgXG4gICAqIG92ZXIgdGhlIGV4ZWN1dGUtYXBpIGVuZHBvaW50LlxuICAgKlxuICAgKiBBIGRvbWFpbiBhdHRhY2hlZCBhZnRlciB0aGlzIGNvbnN0cnVjdCBpcyBjcmVhdGVkIChgYXBpLmFkZERvbWFpbk5hbWUoKWApIGlzXG4gICAqIHN0aWxsIHVzZWQgZm9yIHRoZSBob3N0LCBidXQgQ0RLIGtlZXBzIGl0cyBiYXNlIHBhdGggbWFwcGluZ3MgcHJpdmF0ZSwgc28gYVxuICAgKiBtYXBwaW5nIGFkZGVkIHRoYXQgd2F5IHdvbid0IHNob3cgdXAgaGVyZS5cbiAgICovXG4gIGdldCB1cmwoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjdXN0b21Eb21haW4gPSB0aGlzLmFwaS5kb21haW5OYW1lO1xuICAgIC8vIEEgY3VzdG9tIGRvbWFpbiByZWFjaGVzIHRoZSBzdGFnZSB0aHJvdWdoIGEgYmFzZSBwYXRoIG1hcHBpbmcsIHNvIHRoZVxuICAgIC8vIHN0YWdlIG5hbWUgaXNuJ3QgaW4gdGhlIHBhdGggdGhlcmU7IHRoZSBtYXBwaW5nIG1heSBiZSwgd2hlbiBzZXQuXG4gICAgY29uc3QgW29yaWdpbiwgcHJlZml4XSA9IGN1c3RvbURvbWFpblxuICAgICAgPyBbXG4gICAgICAgICAgYGh0dHBzOi8vJHtjdXN0b21Eb21haW4uZG9tYWluTmFtZX1gLFxuICAgICAgICAgIHRoaXMucHJvcHMub3ZlcnJpZGVzPy5yZXN0QXBpUHJvcHM/LmRvbWFpbk5hbWU/LmJhc2VQYXRoLFxuICAgICAgICBdXG4gICAgICA6IFtcbiAgICAgICAgICBgaHR0cHM6Ly8ke3RoaXMuYXBpLnJlc3RBcGlJZH0uZXhlY3V0ZS1hcGkuJHtTdGFjay5vZih0aGlzKS5yZWdpb259LmFtYXpvbmF3cy5jb21gLFxuICAgICAgICAgIHRoaXMuYXBpLmRlcGxveW1lbnRTdGFnZS5zdGFnZU5hbWUsXG4gICAgICAgIF07XG4gICAgcmV0dXJuIGpvaW5QYXRoKG9yaWdpbiwgcHJlZml4LCB0aGlzLnByb3BzLmJhc2VQYXRoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgYmFzZVJlc291cmNlOiBJUmVzb3VyY2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgbmV4dFJlc291cmNlOiBJUmVzb3VyY2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IE5leHRqc0FwaVByb3BzO1xuICBwcml2YXRlIHN0YXRpY0ludGVncmF0aW9uUm9sZTogSVJvbGU7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE5leHRqc0FwaVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICB0aGlzLnByb3BzID0gcHJvcHM7XG5cbiAgICB0aGlzLnZhbGlkYXRlUHJvcHMocHJvcHMpO1xuICAgIHRoaXMuYXBpID0gdGhpcy5jcmVhdGVSZXN0QXBpKCk7XG4gICAgdGhpcy5iYXNlUmVzb3VyY2UgPSB0aGlzLmNyZWF0ZUJhc2VSZXNvdXJjZShwcm9wcy5iYXNlUGF0aCk7XG4gICAgdGhpcy5uZXh0UmVzb3VyY2UgPSB0aGlzLmJhc2VSZXNvdXJjZS5hZGRSZXNvdXJjZShcIl9uZXh0XCIpO1xuICAgIHRoaXMuc3RhdGljSW50ZWdyYXRpb25Sb2xlID0gdGhpcy5jcmVhdGVTdGF0aWNJbnRlZ3JhdGlvblJvbGUoKTtcbiAgICB0aGlzLmNyZWF0ZVN0YXRpY0ludGVncmF0aW9ucygpO1xuICAgIGlmIChwcm9wcy5zZXJ2ZXJGdW5jdGlvbikge1xuICAgICAgLy8gV2l0aG91dCBhIGRlZGljYXRlZCBpbWFnZSBmdW5jdGlvbiwgYF9uZXh0L2ltYWdlYCBmYWxscyB0aHJvdWdoIHRvIHRoZVxuICAgICAgLy8gYHtwcm94eSt9YCBjYXRjaC1hbGwgb24gdGhlIHNlcnZlciBmdW5jdGlvbi5cbiAgICAgIGlmIChwcm9wcy5pbWFnZUZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlSW1hZ2VJbnRlZ3JhdGlvbihwcm9wcy5pbWFnZUZ1bmN0aW9uKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY3JlYXRlRHluYW1pY0ludGVncmF0aW9uKHByb3BzLnNlcnZlckZ1bmN0aW9uKTtcbiAgICB9IGVsc2UgaWYgKHByb3BzLnZwYykge1xuICAgICAgLy8gW0Z1dHVyZV0gY3JlYXRlIGludGVncmF0aW9uIHdpdGggRUNTIHZpYSBWUEMgTGluayBhbmQgRUNTIFNlcnZpY2UgRGlzY292ZXJ5XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByb3BzKHByb3BzOiBOZXh0anNBcGlQcm9wcykge1xuICAgIGlmICghcHJvcHMuc2VydmVyRnVuY3Rpb24gJiYgIXByb3BzLnZwYykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2VydmVyRnVuY3Rpb24gb3IgdnBjIG11c3QgYmUgc2V0IGluIE5leHRqc0FwaVByb3BzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUmVzdEFwaSgpOiBSZXN0QXBpIHtcbiAgICByZXR1cm4gbmV3IFJlc3RBcGkodGhpcywgXCJSZXN0QXBpXCIsIHtcbiAgICAgIGJpbmFyeU1lZGlhVHlwZXM6IFtcIiovKlwiXSxcbiAgICAgIGRlc2NyaXB0aW9uOiBgY2RrLW5leHRqcyBSRVNUIEFQSSBmb3IgJHtTdGFjay5vZih0aGlzKS5zdGFja05hbWV9YCxcbiAgICAgIGVuZHBvaW50VHlwZXM6IFtFbmRwb2ludFR5cGUuUkVHSU9OQUxdLFxuICAgICAgbWluQ29tcHJlc3Npb25TaXplOiBTaXplLmJ5dGVzKDApLCAvLyBjb21wcmVzcyBhbGwgcmVzcG9uc2VzIGZvciBiZXR0ZXIgcGVyZlxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LnJlc3RBcGlQcm9wcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYmFzZSByZXNvdXJjZSBwYXRoIGlmIG5lZWRlZC4gSW1wb3J0YW50IGlmIGBiYXNlUGF0aGAgaXMgc2V0LlxuICAgKlxuICAgKiBBIG5lc3RlZCBgYmFzZVBhdGhgIChcIi90ZWFtL2FwcFwiKSBoYXMgdG8gYmVjb21lIG9uZSByZXNvdXJjZSBwZXIgc2VnbWVudDpcbiAgICogQVBJIEdhdGV3YXkgcGF0aCBwYXJ0cyBjYW4ndCBjb250YWluIFwiL1wiLCBzbyBwYXNzaW5nIHRoZSB3aG9sZSB0aGluZyB0byBhXG4gICAqIHNpbmdsZSBgYWRkUmVzb3VyY2VgIGZhaWxzIHZhbGlkYXRpb24gYXQgc3ludGguIGByZXNvbHZlQmFzZVBhdGhgIGFjY2VwdHNcbiAgICogbmVzdGVkIHZhbHVlcywgc28gdGhpcyBpcyByZWFjaGFibGUuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUJhc2VSZXNvdXJjZShiYXNlUGF0aD86IHN0cmluZyk6IElSZXNvdXJjZSB7XG4gICAgLy8gQ3JlYXRlIGJhc2UgcmVzb3VyY2UgcGF0aCBpZiBuZWVkZWRcbiAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplQmFzZVBhdGgoYmFzZVBhdGgpO1xuICAgIGlmICghbm9ybWFsaXplZCkge1xuICAgICAgcmV0dXJuIHRoaXMuYXBpLnJvb3Q7XG4gICAgfVxuICAgIHJldHVybiBub3JtYWxpemVkXG4gICAgICAuc3BsaXQoXCIvXCIpXG4gICAgICAucmVkdWNlPElSZXNvdXJjZT4oXG4gICAgICAgIChwYXJlbnQsIHNlZ21lbnQpID0+IHBhcmVudC5hZGRSZXNvdXJjZShzZWdtZW50KSxcbiAgICAgICAgdGhpcy5hcGkucm9vdCxcbiAgICAgICk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN0YXRpY0ludGVncmF0aW9uUm9sZSgpIHtcbiAgICAvLyBDcmVhdGUgUzMgaW50ZWdyYXRpb24gcm9sZVxuICAgIGNvbnN0IHN0YXRpY0ludGVncmF0aW9uUm9sZSA9IG5ldyBSb2xlKHRoaXMsIFwiU3RhdGljSW50ZWdyYXRpb25Sb2xlXCIsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IFNlcnZpY2VQcmluY2lwYWwoXCJhcGlnYXRld2F5LmFtYXpvbmF3cy5jb21cIiksXG4gICAgfSk7XG5cbiAgICBzdGF0aWNJbnRlZ3JhdGlvblJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogW1wiczM6R2V0T2JqZWN0XCIsIFwiczM6TGlzdEJ1Y2tldFwiXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgICAgdGhpcy5wcm9wcy5zdGF0aWNBc3NldHNCdWNrZXQuYnVja2V0QXJuLFxuICAgICAgICAgIGAke3RoaXMucHJvcHMuc3RhdGljQXNzZXRzQnVja2V0LmJ1Y2tldEFybn0vKmAsXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiBzdGF0aWNJbnRlZ3JhdGlvblJvbGU7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN0YXRpY0ludGVncmF0aW9ucygpIHtcbiAgICB0aGlzLm5leHRSZXNvdXJjZVxuICAgICAgLmFkZFJlc291cmNlKFwic3RhdGljXCIpXG4gICAgICAuYWRkUmVzb3VyY2UoXCJ7cHJveHkrfVwiKVxuICAgICAgLmFkZE1ldGhvZChcbiAgICAgICAgXCJHRVRcIixcbiAgICAgICAgdGhpcy5jcmVhdGVTM0ludGVncmF0aW9uKHsga2V5OiB0aGlzLnMzS2V5KFwiX25leHQvc3RhdGljL3trZXl9XCIpIH0pLFxuICAgICAgICB0aGlzLmdldFN0YXRpY01ldGhvZE9wdGlvbnMoeyBwcm94eTogdHJ1ZSB9KSxcbiAgICAgICk7XG4gICAgLy8gYWRkIHB1YmxpYyBkaXJlY3RvcnkgZmlsZXMvZGlyZWN0b3JpZXMgdGhhdCBleGlzdCBhdCB0b3AgbGV2ZWwgYnV0IG5lZWQgdG8gZ28gdG8gUzMuXG4gICAgZm9yIChjb25zdCBwdWJsaWNEaXJFbnRyeSBvZiB0aGlzLnByb3BzLnB1YmxpY0RpckVudHJpZXMpIHtcbiAgICAgIGlmIChwdWJsaWNEaXJFbnRyeS5pc0RpcmVjdG9yeSkge1xuICAgICAgICB0aGlzLmJhc2VSZXNvdXJjZVxuICAgICAgICAgIC5hZGRSZXNvdXJjZShwdWJsaWNEaXJFbnRyeS5uYW1lKVxuICAgICAgICAgIC5hZGRSZXNvdXJjZShcIntwcm94eSt9XCIpXG4gICAgICAgICAgLmFkZE1ldGhvZChcbiAgICAgICAgICAgIFwiR0VUXCIsXG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVMzSW50ZWdyYXRpb24oe1xuICAgICAgICAgICAgICBrZXk6IHRoaXMuczNLZXkoYCR7cHVibGljRGlyRW50cnkubmFtZX0ve2tleX1gKSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgdGhpcy5nZXRTdGF0aWNNZXRob2RPcHRpb25zKHsgcHJveHk6IHRydWUgfSksXG4gICAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYmFzZVJlc291cmNlXG4gICAgICAgICAgLmFkZFJlc291cmNlKHB1YmxpY0RpckVudHJ5Lm5hbWUpXG4gICAgICAgICAgLmFkZE1ldGhvZChcbiAgICAgICAgICAgIFwiR0VUXCIsXG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVMzSW50ZWdyYXRpb24oeyBrZXk6IHRoaXMuczNLZXkocHVibGljRGlyRW50cnkubmFtZSkgfSksXG4gICAgICAgICAgICB0aGlzLmdldFN0YXRpY01ldGhvZE9wdGlvbnMoKSxcbiAgICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVmaXhlcyBhIHJlcXVlc3QgcGF0aCB3aXRoIHRoZSBrZXkgcHJlZml4IHRoZSBhc3NldHMgd2VyZSB1cGxvYWRlZCB1bmRlcixcbiAgICogc2luY2UgdGhlIFMzIGludGVncmF0aW9ucyBhZGRyZXNzIG9iamVjdHMgYnkga2V5IHJhdGhlciB0aGFuIGJ5IFVSTC5cbiAgICovXG4gIHByaXZhdGUgczNLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBqb2luUGF0aCh0aGlzLnByb3BzLnN0YXRpY0Fzc2V0c0tleVByZWZpeCwga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIEFQSSByZXF1ZXN0IHRvIFMzIHJlcXVlc3QuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL3Jlc3QtYXBpLXBhcmFtZXRlci1tYXBwaW5nLXNvdXJjZXMuaHRtbFxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcGlnYXRld2F5L2xhdGVzdC9kZXZlbG9wZXJndWlkZS9pbnRlZ3JhdGluZy1hcGktd2l0aC1hd3Mtc2VydmljZXMtczMuaHRtbCNhcGktaXRlbXMtaW4tZm9sZGVyLWFzLXMzLW9iamVjdHMtaW4tYnVja2V0XG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZVMzSW50ZWdyYXRpb24oeyBrZXkgfTogeyBrZXk6IHN0cmluZyB9KSB7XG4gICAgY29uc3QgczNJbnRlZ3JhdGlvbiA9IG5ldyBBd3NJbnRlZ3JhdGlvbih7XG4gICAgICBzZXJ2aWNlOiBcInMzXCIsXG4gICAgICBpbnRlZ3JhdGlvbkh0dHBNZXRob2Q6IFwiR0VUXCIsXG4gICAgICBwYXRoOiBgJHt0aGlzLnByb3BzLnN0YXRpY0Fzc2V0c0J1Y2tldC5idWNrZXROYW1lfS8ke2tleX1gLFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICBjcmVkZW50aWFsc1JvbGU6IHRoaXMuc3RhdGljSW50ZWdyYXRpb25Sb2xlLFxuICAgICAgICBwYXNzdGhyb3VnaEJlaGF2aW9yOiBQYXNzdGhyb3VnaEJlaGF2aW9yLldIRU5fTk9fVEVNUExBVEVTLCAvLyByZWNvbW1lbmRlZFxuICAgICAgICByZXF1ZXN0UGFyYW1ldGVyczoga2V5LmluY2x1ZGVzKFwie2tleX1cIilcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgXCJpbnRlZ3JhdGlvbi5yZXF1ZXN0LnBhdGgua2V5XCI6IFwibWV0aG9kLnJlcXVlc3QucGF0aC5wcm94eVwiLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICBpbnRlZ3JhdGlvblJlc3BvbnNlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHN0YXR1c0NvZGU6IFwiMjAwXCIsXG4gICAgICAgICAgICByZXNwb25zZVBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNvbnRlbnQtVHlwZVwiOlxuICAgICAgICAgICAgICAgIFwiaW50ZWdyYXRpb24ucmVzcG9uc2UuaGVhZGVyLkNvbnRlbnQtVHlwZVwiLFxuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuQ29udGVudC1MZW5ndGhcIjpcbiAgICAgICAgICAgICAgICBcImludGVncmF0aW9uLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LUxlbmd0aFwiLFxuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuQ2FjaGUtQ29udHJvbFwiOlxuICAgICAgICAgICAgICAgIFwiaW50ZWdyYXRpb24ucmVzcG9uc2UuaGVhZGVyLkNhY2hlLUNvbnRyb2xcIixcbiAgICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkVUYWdcIjogXCJpbnRlZ3JhdGlvbi5yZXNwb25zZS5oZWFkZXIuRVRhZ1wiLFxuICAgICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuTGFzdC1Nb2RpZmllZFwiOlxuICAgICAgICAgICAgICAgIFwiaW50ZWdyYXRpb24ucmVzcG9uc2UuaGVhZGVyLkxhc3QtTW9kaWZpZWRcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzdGF0dXNDb2RlOiBcIjQwNFwiLFxuICAgICAgICAgICAgc2VsZWN0aW9uUGF0dGVybjogXCI0MDRcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5zdGF0aWNJbnRlZ3JhdGlvblByb3BzLFxuICAgIH0pO1xuICAgIHJldHVybiBzM0ludGVncmF0aW9uO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTdGF0aWNNZXRob2RPcHRpb25zKHsgcHJveHkgfSA9IHsgcHJveHk6IGZhbHNlIH0pOiBNZXRob2RPcHRpb25zIHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVxdWVzdFBhcmFtZXRlcnM6IHByb3h5XG4gICAgICAgID8ge1xuICAgICAgICAgICAgXCJtZXRob2QucmVxdWVzdC5wYXRoLnByb3h5XCI6IHRydWUsXG4gICAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIG1ldGhvZFJlc3BvbnNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgc3RhdHVzQ29kZTogXCIyMDBcIixcbiAgICAgICAgICByZXNwb25zZVBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LVR5cGVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5Db250ZW50LUxlbmd0aFwiOiB0cnVlLFxuICAgICAgICAgICAgXCJtZXRob2QucmVzcG9uc2UuaGVhZGVyLkNhY2hlLUNvbnRyb2xcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwibWV0aG9kLnJlc3BvbnNlLmhlYWRlci5FVGFnXCI6IHRydWUsXG4gICAgICAgICAgICBcIm1ldGhvZC5yZXNwb25zZS5oZWFkZXIuTGFzdC1Nb2RpZmllZFwiOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiBcIjQwNFwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5zM01ldGhvZE9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgTGFtYmRhIFByb3h5IGludGVncmF0aW9uIGZvciB0aGUgYF9uZXh0L2ltYWdlYCByb3V0ZS5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlSW1hZ2VJbnRlZ3JhdGlvbihpbWFnZUZ1bmN0aW9uOiBJRnVuY3Rpb24pIHtcbiAgICAvLyBpbWFnZUZ1bmN0aW9uIGlzIGFzc3VtZWQgdG8gYmUgdGhlIGRlZGljYXRlZCwgc3RyZWFtaW5nLWNhcGFibGUgaW1hZ2VcbiAgICAvLyBMYW1iZGEgKHNlZSBpdHMgZG9jIGNvbW1lbnQpOyBvdmVycmlkZSByZXNwb25zZVRyYW5zZmVyTW9kZSB2aWFcbiAgICAvLyBpbWFnZUludGVncmF0aW9uUHJvcHMgaWYgdGhhdCBhc3N1bXB0aW9uIGRvZXNuJ3QgaG9sZCBmb3IgYSBjdXN0b21cbiAgICAvLyBpbWFnZUZ1bmN0aW9uLCBvdGhlcndpc2UgQVBJIEdhdGV3YXkgcmV0dXJucyBhIDUwMi4gRGVsaWJlcmF0ZWx5XG4gICAgLy8gZG9lc24ndCBpbmhlcml0IGR5bmFtaWNJbnRlZ3JhdGlvblByb3BzOiB0aGF0J3MgZm9yIHNlcnZlckZ1bmN0aW9uLFxuICAgIC8vIGEgZGlmZmVyZW50IExhbWJkYSB3aXRoIGRpZmZlcmVudCAoYW5kIHBvc3NpYmx5IGNvbmZsaWN0aW5nLCBlLmcuXG4gICAgLy8gQlVGRkVSRUQgZm9yIGEgbm9uLXN0cmVhbWluZyBMYW1iZGEgV2ViIEFkYXB0ZXIgc2V0dXApIHN0cmVhbWluZ1xuICAgIC8vIHJlcXVpcmVtZW50cyB0aGFuIHRoZSBhbHdheXMtc3RyZWFtaW5nIGRlZGljYXRlZCBpbWFnZSBMYW1iZGEuXG4gICAgY29uc3QgaW1hZ2VJbnRlZ3JhdGlvbiA9IG5ldyBMYW1iZGFJbnRlZ3JhdGlvbihpbWFnZUZ1bmN0aW9uLCB7XG4gICAgICByZXNwb25zZVRyYW5zZmVyTW9kZTogUmVzcG9uc2VUcmFuc2Zlck1vZGUuU1RSRUFNLFxuICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmltYWdlSW50ZWdyYXRpb25Qcm9wcyxcbiAgICB9KTtcbiAgICBjb25zdCBpbWFnZVJlc291cmNlID0gdGhpcy5uZXh0UmVzb3VyY2UuYWRkUmVzb3VyY2UoXCJpbWFnZVwiKTtcbiAgICBpbWFnZVJlc291cmNlLmFkZE1ldGhvZChcIkFOWVwiLCBpbWFnZUludGVncmF0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgTGFtYmRhIFByb3h5IGludGVncmF0aW9uIGZvciBhbGwgb3RoZXIgcm91dGVzXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUR5bmFtaWNJbnRlZ3JhdGlvbihzZXJ2ZXJGdW5jdGlvbjogSUZ1bmN0aW9uKSB7XG4gICAgLy8gQWxsIG90aGVyIHJvdXRlcyB1c2Ugc3RyZWFtaW5nIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICBjb25zdCBzdHJlYW1pbmdJbnRlZ3JhdGlvbiA9IG5ldyBMYW1iZGFJbnRlZ3JhdGlvbihzZXJ2ZXJGdW5jdGlvbiwge1xuICAgICAgcmVzcG9uc2VUcmFuc2Zlck1vZGU6IFJlc3BvbnNlVHJhbnNmZXJNb2RlLlNUUkVBTSxcbiAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5keW5hbWljSW50ZWdyYXRpb25Qcm9wcyxcbiAgICB9KTtcblxuICAgIC8vIEFkZCBjYXRjaC1hbGwgcm91dGVzIHdpdGggc3RyZWFtaW5nIGludGVncmF0aW9uIGZvciBzZXJ2ZXItc2lkZSByZW5kZXJpbmdcbiAgICB0aGlzLmJhc2VSZXNvdXJjZS5hZGRNZXRob2QoXCJBTllcIiwgc3RyZWFtaW5nSW50ZWdyYXRpb24pO1xuICAgIGNvbnN0IHByb3h5UmVzb3VyY2UgPSB0aGlzLmJhc2VSZXNvdXJjZS5hZGRSZXNvdXJjZShcIntwcm94eSt9XCIpO1xuICAgIHByb3h5UmVzb3VyY2UuYWRkTWV0aG9kKFwiQU5ZXCIsIHN0cmVhbWluZ0ludGVncmF0aW9uKTtcbiAgfVxufVxuIl19
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=