cdk-nextjs 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/.jsii +2467 -2714
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1725 -1909
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +687 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1548 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +852 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +861 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  88. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  92. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  93. package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
  94. package/lib/lambdas/post-deploy/prune-s3.js +54 -15
  95. package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
  96. package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  103. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  104. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  105. package/lib/nextjs-api.d.ts +107 -18
  106. package/lib/nextjs-api.js +349 -39
  107. package/lib/nextjs-api.test.js +582 -1
  108. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  109. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  110. package/lib/nextjs-build/nextjs-build.js +684 -327
  111. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  112. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  113. package/lib/nextjs-build/patch-fetch.js +1 -1
  114. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  115. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  116. package/lib/nextjs-cache.d.ts +82 -4
  117. package/lib/nextjs-cache.js +186 -10
  118. package/lib/nextjs-cache.test.js +176 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  120. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  121. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  122. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  123. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  124. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  125. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  126. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  127. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  128. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  129. package/lib/nextjs-distribution.d.ts +194 -23
  130. package/lib/nextjs-distribution.js +535 -62
  131. package/lib/nextjs-distribution.test.d.ts +1 -0
  132. package/lib/nextjs-distribution.test.js +697 -0
  133. package/lib/nextjs-post-deploy.d.ts +23 -3
  134. package/lib/nextjs-post-deploy.js +14 -10
  135. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  136. package/lib/nextjs-post-deploy.test.js +34 -0
  137. package/lib/nextjs-static-assets.d.ts +23 -4
  138. package/lib/nextjs-static-assets.js +29 -6
  139. package/lib/nextjs-static-assets.test.js +20 -1
  140. package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
  141. package/lib/root-constructs/nextjs-base-construct.js +144 -34
  142. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  143. package/lib/root-constructs/nextjs-global-containers.js +20 -70
  144. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  145. package/lib/root-constructs/nextjs-global-functions.js +52 -69
  146. package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
  147. package/lib/root-constructs/nextjs-regional-containers.js +17 -15
  148. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  149. package/lib/root-constructs/nextjs-regional-functions.js +8 -25
  150. package/lib/runtime/api-gateway-path.d.ts +34 -0
  151. package/lib/runtime/api-gateway-path.js +71 -0
  152. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  153. package/lib/runtime/api-gateway-path.test.js +65 -0
  154. package/lib/runtime/case-redirect.d.ts +22 -0
  155. package/lib/runtime/case-redirect.js +63 -0
  156. package/lib/runtime/case-redirect.test.d.ts +1 -0
  157. package/lib/runtime/case-redirect.test.js +32 -0
  158. package/lib/runtime/core.d.ts +234 -0
  159. package/lib/runtime/core.js +1213 -0
  160. package/lib/runtime/core.test.d.ts +1 -0
  161. package/lib/runtime/core.test.js +1678 -0
  162. package/lib/runtime/deployment-root.d.ts +13 -0
  163. package/lib/runtime/deployment-root.js +29 -0
  164. package/lib/runtime/dispatch.d.ts +331 -0
  165. package/lib/runtime/dispatch.js +751 -0
  166. package/lib/runtime/dispatch.test.d.ts +1 -0
  167. package/lib/runtime/dispatch.test.js +853 -0
  168. package/lib/runtime/entrypoints.d.ts +57 -0
  169. package/lib/runtime/entrypoints.js +115 -0
  170. package/lib/runtime/http/abort-signal.d.ts +6 -0
  171. package/lib/runtime/http/abort-signal.js +19 -0
  172. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  173. package/lib/runtime/http/abort-signal.test.js +49 -0
  174. package/lib/runtime/http/node-server.d.ts +38 -0
  175. package/lib/runtime/http/node-server.js +99 -0
  176. package/lib/runtime/http/node-server.test.d.ts +1 -0
  177. package/lib/runtime/http/node-server.test.js +96 -0
  178. package/lib/runtime/http/node-sink.d.ts +16 -0
  179. package/lib/runtime/http/node-sink.js +48 -0
  180. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  181. package/lib/runtime/http/node-sink.test.js +66 -0
  182. package/lib/runtime/http/request.d.ts +62 -0
  183. package/lib/runtime/http/request.js +134 -0
  184. package/lib/runtime/http/request.test.d.ts +1 -0
  185. package/lib/runtime/http/request.test.js +103 -0
  186. package/lib/runtime/http/response.d.ts +77 -0
  187. package/lib/runtime/http/response.js +229 -0
  188. package/lib/runtime/http/response.test.d.ts +1 -0
  189. package/lib/runtime/http/response.test.js +178 -0
  190. package/lib/runtime/http/sink.d.ts +73 -0
  191. package/lib/runtime/http/sink.js +188 -0
  192. package/lib/runtime/http/sink.test.d.ts +1 -0
  193. package/lib/runtime/http/sink.test.js +257 -0
  194. package/lib/runtime/image-utils.d.ts +78 -0
  195. package/lib/runtime/image-utils.js +129 -0
  196. package/lib/runtime/image-utils.test.d.ts +1 -0
  197. package/lib/runtime/image-utils.test.js +237 -0
  198. package/lib/runtime/image.d.ts +76 -0
  199. package/lib/runtime/image.js +296 -0
  200. package/lib/runtime/image.test.d.ts +1 -0
  201. package/lib/runtime/image.test.js +405 -0
  202. package/lib/runtime/lambda-event.d.ts +4 -0
  203. package/lib/runtime/lambda-event.js +113 -0
  204. package/lib/runtime/lambda-event.test.d.ts +1 -0
  205. package/lib/runtime/lambda-event.test.js +119 -0
  206. package/lib/runtime/lambda.mjs +41595 -0
  207. package/lib/runtime/load-module.d.ts +8 -0
  208. package/lib/runtime/load-module.js +35 -0
  209. package/lib/runtime/manifest.d.ts +215 -0
  210. package/lib/runtime/manifest.js +118 -0
  211. package/lib/runtime/middleware.d.ts +43 -0
  212. package/lib/runtime/middleware.js +113 -0
  213. package/lib/runtime/middleware.test.d.ts +1 -0
  214. package/lib/runtime/middleware.test.js +259 -0
  215. package/lib/runtime/next-modules.d.ts +55 -0
  216. package/lib/runtime/next-modules.js +124 -0
  217. package/lib/runtime/next-modules.test.d.ts +1 -0
  218. package/lib/runtime/next-modules.test.js +34 -0
  219. package/lib/runtime/public-files.d.ts +32 -0
  220. package/lib/runtime/public-files.js +117 -0
  221. package/lib/runtime/public-files.test.d.ts +1 -0
  222. package/lib/runtime/public-files.test.js +97 -0
  223. package/lib/runtime/server.mjs +41588 -0
  224. package/lib/runtime/static-files.d.ts +50 -0
  225. package/lib/runtime/static-files.js +266 -0
  226. package/lib/runtime/static-files.test.d.ts +1 -0
  227. package/lib/runtime/static-files.test.js +118 -0
  228. package/lib/runtime/util.d.ts +28 -0
  229. package/lib/runtime/util.js +79 -0
  230. package/lib/utils/base-path.d.ts +123 -11
  231. package/lib/utils/base-path.js +276 -39
  232. package/lib/utils/base-path.test.js +275 -50
  233. package/lib/utils/get-architecture.d.ts +7 -8
  234. package/lib/utils/get-architecture.js +12 -13
  235. package/lib/utils/zip-directory.d.ts +14 -0
  236. package/lib/utils/zip-directory.js +121 -0
  237. package/lib/utils/zip-directory.test.d.ts +1 -0
  238. package/lib/utils/zip-directory.test.js +99 -0
  239. package/package.json +22 -3
  240. package/scripts/capture-adapter-fixture.mjs +325 -0
  241. package/scripts/e2e-deploy.sh +398 -0
  242. package/scripts/e2e-harness/README.md +707 -0
  243. package/scripts/e2e-harness/app.js +370 -0
  244. package/scripts/e2e-harness/common.sh +249 -0
  245. package/scripts/e2e-harness/screen.mjs +302 -0
  246. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  247. package/scripts/e2e-harness/type-filters.mjs +47 -0
  248. package/scripts/e2e-logs.sh +75 -0
  249. package/scripts/e2e-offline.sh +91 -0
  250. package/scripts/e2e-sweep.sh +370 -0
  251. package/scripts/e2e-warm.sh +114 -0
  252. package/scripts/zero-config-build.mjs +418 -0
  253. package/docs/1k-concurrent-users-executions.png +0 -0
  254. package/docs/plans/adapter-runtime-release.md +0 -362
  255. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  256. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  257. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  258. package/lib/image-optimization/handler-utils.d.ts +0 -34
  259. package/lib/image-optimization/handler-utils.js +0 -83
  260. package/lib/image-optimization/handler-utils.test.js +0 -178
  261. package/lib/nextjs-build/functions.Dockerfile +0 -31
  262. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  263. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  264. package/lib/utils/experimental-flags.d.ts +0 -24
  265. package/lib/utils/experimental-flags.js +0 -30
  266. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
@@ -5,11 +5,13 @@ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
5
5
  const aws_cdk_lib_1 = require("aws-cdk-lib");
6
6
  const aws_cloudfront_1 = require("aws-cdk-lib/aws-cloudfront");
7
7
  const aws_cloudfront_origins_1 = require("aws-cdk-lib/aws-cloudfront-origins");
8
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
8
9
  const constructs_1 = require("constructs");
10
+ const function_groups_1 = require("./adapter/function-groups");
9
11
  const constants_1 = require("./constants");
10
12
  const base_path_1 = require("./utils/base-path");
11
13
  class NextjsDistribution extends constructs_1.Construct {
12
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsDistribution", version: "0.6.1" };
14
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsDistribution", version: "0.7.0" };
13
15
  distribution;
14
16
  props;
15
17
  /**
@@ -19,6 +21,13 @@ class NextjsDistribution extends constructs_1.Construct {
19
21
  * relying on the caller having passed one.
20
22
  */
21
23
  basePath;
24
+ /**
25
+ * `props.assetPrefix` normalized to a leading-slash path, `""` when the app
26
+ * sets none or sets one that already equals the `basePath` prefix — in which
27
+ * case the ordinary `_next/static*` behavior already covers it and a second one
28
+ * would be a duplicate pattern CloudFront rejects.
29
+ */
30
+ assetPrefix;
22
31
  /**
23
32
  * Common security headers applied by default to all origins
24
33
  * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html#managed-response-headers-policies-security
@@ -43,7 +52,6 @@ class NextjsDistribution extends constructs_1.Construct {
43
52
  };
44
53
  staticOrigin;
45
54
  dynamicOrigin;
46
- imageOrigin;
47
55
  dynamicOriginResponsePolicy;
48
56
  dynamicCloudFrontFunctionAssociations;
49
57
  isFunctionCompute;
@@ -54,10 +62,11 @@ class NextjsDistribution extends constructs_1.Construct {
54
62
  super(scope, id);
55
63
  this.props = props;
56
64
  this.basePath = (0, base_path_1.normalizeBasePath)(props.basePath);
65
+ this.assetPrefix = this.resolveAssetPrefix();
57
66
  this.staticOrigin = this.createStaticOrigin();
58
67
  this.isFunctionCompute = props.nextjsType === constants_1.NextjsType.GLOBAL_FUNCTIONS;
68
+ this.validateFunctionGroupProps();
59
69
  this.dynamicOrigin = this.createDynamicOrigin();
60
- this.imageOrigin = this.createImageOrigin();
61
70
  this.dynamicOriginResponsePolicy = this.createDynamicOriginRequestPolicy();
62
71
  this.dynamicCloudFrontFunctionAssociations =
63
72
  this.createDynamicCloudFrontFunctionAssociations();
@@ -65,6 +74,9 @@ class NextjsDistribution extends constructs_1.Construct {
65
74
  this.dynamicBehaviorOptions = this.createDynamicBehaviorOptions();
66
75
  this.imageBehaviorOptions = this.createImageBehaviorOptions();
67
76
  this.distribution = this.getDistribution();
77
+ if (this.isFunctionCompute) {
78
+ this.grantInvoke(function_groups_1.DEFAULT_FUNCTION_GROUP, props.functionUrl);
79
+ }
68
80
  this.addStaticBehaviors();
69
81
  this.addDynamicBehaviors();
70
82
  }
@@ -80,7 +92,11 @@ class NextjsDistribution extends constructs_1.Construct {
80
92
  return fullComment.length < 128 ? fullComment : baseComment;
81
93
  }
82
94
  createStaticOrigin() {
83
- return aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.props.assetsBucket, this.props.overrides?.s3BucketOriginProps);
95
+ return aws_cloudfront_origins_1.S3BucketOrigin.withOriginAccessControl(this.props.assetsBucket, {
96
+ // LIST lets S3 answer a missing key with 404 instead of 403
97
+ originAccessLevels: [aws_cloudfront_1.AccessLevel.READ, aws_cloudfront_1.AccessLevel.LIST],
98
+ ...this.props.overrides?.s3BucketOriginProps,
99
+ });
84
100
  }
85
101
  createDynamicOrigin() {
86
102
  if (this.isFunctionCompute) {
@@ -102,35 +118,22 @@ class NextjsDistribution extends constructs_1.Construct {
102
118
  });
103
119
  }
104
120
  }
105
- /**
106
- * A dedicated image optimization Lambda is only wired up when
107
- * {@link NextjsDistributionProps.imageFunctionUrl} is supplied, which today
108
- * only `NextjsType.GLOBAL_FUNCTIONS` does. Otherwise `_next/image*` keeps
109
- * going to the dynamic origin, where the Next.js server optimizes images
110
- * itself.
111
- *
112
- * The `_next/image*` behavior is kept either way: its cache policy
113
- * (`queryStringBehavior: all()`, `accept` in the cache key) is the right one
114
- * for image requests regardless of which origin answers them.
115
- */
116
- createImageOrigin() {
117
- if (!this.isFunctionCompute || !this.props.imageFunctionUrl) {
118
- return this.dynamicOrigin;
119
- }
120
- return aws_cloudfront_origins_1.FunctionUrlOrigin.withOriginAccessControl(this.props.imageFunctionUrl, {
121
- ...this.props.overrides?.dynamicFunctionUrlOriginWithOACProps,
122
- ...this.props.overrides?.imageFunctionUrlOriginWithOACProps,
123
- });
124
- }
125
121
  /**
126
122
  * Lambda Function URLs "expect the `Host` header to contain the origin domain
127
123
  * name, not the domain name of the CloudFront distribution."
124
+ *
125
+ * A container origin also gets CloudFront's own headers, for
126
+ * `CloudFront-Forwarded-Proto`: without a certificate CloudFront reaches the
127
+ * ALB over plain HTTP, so the ALB's `X-Forwarded-Proto` is `http`, and the
128
+ * runtime would build every absolute URL (`request.url`, the origin a server
129
+ * action is forwarded to) as `http://` behind a viewer on HTTPS.
128
130
  * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-all-viewer-except-host-header
131
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-all-viewer-and-cloudfront
129
132
  */
130
133
  createDynamicOriginRequestPolicy() {
131
134
  return this.isFunctionCompute
132
135
  ? aws_cloudfront_1.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER
133
- : aws_cloudfront_1.OriginRequestPolicy.ALL_VIEWER;
136
+ : aws_cloudfront_1.OriginRequestPolicy.ALL_VIEWER_AND_CLOUDFRONT_2022;
134
137
  }
135
138
  /**
136
139
  * Ensures Next.js `request.url` will be correct domain instead of URL of
@@ -141,9 +144,66 @@ class NextjsDistribution extends constructs_1.Construct {
141
144
  const associations = [];
142
145
  if (this.isFunctionCompute) {
143
146
  const cloudFrontFn = new aws_cloudfront_1.Function(this, "CloudFrontFn", {
147
+ // cloudfront-js-1.0, so ES5.1: `var`, no arrow functions, no template
148
+ // literals, no `Object.keys`.
144
149
  code: aws_cloudfront_1.FunctionCode.fromInline(`
145
150
  function handler(event) {
146
151
  var request = event.request;
152
+ var uri = request.uri;
153
+
154
+ // Next.js answers any path containing a backslash or a repeated
155
+ // slash with a 308 to the collapsed path
156
+ // (\`normalizeRepeatedSlashes\`, called from \`base-server.ts\`), and so
157
+ // does this runtime. Behind a Lambda Function URL the origin never
158
+ // gets the chance: Origin Access Control signs the raw path while the
159
+ // Function URL canonicalizes it before verifying, so the origin
160
+ // answers 403 SignatureDoesNotMatch. Doing the redirect here is what
161
+ // makes \`/basepath//to-sv\` behave as it does under \`next start\`.
162
+ //
163
+ // A bare \`//\` reaches here too, and is answered the same way -
164
+ // measured, because \`//\` at the start of a request target is also the
165
+ // authority form and it was not obvious CloudFront would route it to a
166
+ // function at all. It does: \`GET //\` answers 308 to \`/\` with
167
+ // \`x-cache: FunctionGeneratedResponse\`, over both HTTP/1.1 and HTTP/2,
168
+ // which is what \`test/e2e/hydration\` asks for.
169
+ //
170
+ // Two things Next.js does that this cannot:
171
+ //
172
+ // - the body it sends with its own redirect (the destination, as
173
+ // text), because a generated response can only carry one on
174
+ // cloudfront-js-2.0. No known client reads it.
175
+ // - the original order of the query string. The event exposes
176
+ // \`querystring\` as an object, never as the raw string, so
177
+ // \`/x//y?a=1&b=2\` redirects to \`/x/y?b=2&a=1\`. The pairs all
178
+ // survive; only their order is CloudFront's rather than the
179
+ // client's, and a redirect target is not order-sensitive.
180
+ //
181
+ // A repeated key's \`multiValue\` already holds its first value, which
182
+ // \`value\` repeats, so it is one or the other, never both. Names and
183
+ // values arrive as the client sent them, still percent-encoded
184
+ // (measured: \`?a=%20b%26c&p=1+2\` reads back unchanged), so they are
185
+ // joined as-is; encoding them again would turn \`%20\` into \`%2520\`.
186
+ if (/\\\\|\\/\\//.test(uri)) {
187
+ var location = uri.replace(/\\\\/g, "/").replace(/\\/\\/+/g, "/");
188
+ var qs = [];
189
+ for (var name in request.querystring) {
190
+ var q = request.querystring[name];
191
+ var values = q.multiValue || [q];
192
+ for (var i = 0; i < values.length; i++) {
193
+ var v = values[i].value;
194
+ qs.push(v === "" ? name : name + "=" + v);
195
+ }
196
+ }
197
+ if (qs.length) {
198
+ location = location + "?" + qs.join("&");
199
+ }
200
+ return {
201
+ statusCode: 308,
202
+ statusDescription: "Permanent Redirect",
203
+ headers: { location: { value: location } },
204
+ };
205
+ }
206
+
147
207
  request.headers["x-forwarded-host"] = request.headers.host;
148
208
  return request;
149
209
  }
@@ -176,30 +236,21 @@ class NextjsDistribution extends constructs_1.Construct {
176
236
  }
177
237
  createDynamicBehaviorOptions() {
178
238
  const dynamicBehaviorOptions = this.props.overrides?.dynamicBehaviorOptions;
239
+ const cachePolicyProps = this.props.overrides?.dynamicCachePolicyProps;
179
240
  // create default cache policy if not provided
180
241
  const cachePolicy = dynamicBehaviorOptions?.cachePolicy ??
181
242
  new aws_cloudfront_1.CachePolicy(this, "DynamicCachePolicy", {
182
- queryStringBehavior: aws_cloudfront_1.CacheQueryStringBehavior.all(),
183
- headerBehavior: aws_cloudfront_1.CacheHeaderBehavior.allowList(
184
- // NOTE: CloudFront Custom Cache Policies have soft max of 10 headers
185
- // cdk-nextjs includes the most essential headers for Next.js functionality
186
- // but it's recommended to request quota increase to include all headers (commented out ones below)
187
- // more here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-policies
188
- "accept", // content negotiation (HTML vs RSC payload)
189
- "rsc", // React Server Components requests
190
- "next-url", // Next.js routing
191
- "next-router-state-tree", // App Router navigation state
192
- "next-router-prefetch", // prefetch behavior
193
- "next-router-segment-prefetch", // segment-level prefetching
194
- "x-matched-path", // dynamic routes and rewrites
195
- "x-prerender-revalidate", // on-demand ISR revalidation
196
- "x-next-cache-tags", // tag-based cache revalidation
197
- "x-prerender-bypass"),
198
- cookieBehavior: aws_cloudfront_1.CacheCookieBehavior.all(),
199
- enableAcceptEncodingBrotli: true,
200
- enableAcceptEncodingGzip: true,
243
+ ...(isCachingDisabled(cachePolicyProps)
244
+ ? DISABLED_CACHE_KEY
245
+ : DYNAMIC_CACHE_KEY),
246
+ // A response with no `Cache-Control` is not cached, which is what Next.js
247
+ // and every app written for it assume: a dynamic route handler sets none.
248
+ // CDK's default is a day, which cached `/api/*` responses at the edge for
249
+ // 24 hours. Anything Next.js *means* to cache - ISR, SSG, a PPR shell -
250
+ // says so with `s-maxage`, which `maxTtl` still honors.
251
+ defaultTtl: aws_cdk_lib_1.Duration.seconds(0),
201
252
  comment: this.getComment("NextJS Dynamic Cache Policy", aws_cdk_lib_1.Stack.of(this).stackName),
202
- ...this.props.overrides?.dynamicCachePolicyProps,
253
+ ...cachePolicyProps,
203
254
  });
204
255
  const responseHeadersPolicy = dynamicBehaviorOptions?.responseHeadersPolicy ??
205
256
  new aws_cloudfront_1.ResponseHeadersPolicy(this, "DynamicResponseHeadersPolicy", {
@@ -210,14 +261,53 @@ class NextjsDistribution extends constructs_1.Construct {
210
261
  return {
211
262
  allowedMethods: aws_cloudfront_1.AllowedMethods.ALLOW_ALL,
212
263
  cachePolicy,
213
- functionAssociations: this.dynamicCloudFrontFunctionAssociations,
214
264
  origin: this.dynamicOrigin,
215
265
  originRequestPolicy: this.dynamicOriginResponsePolicy,
216
266
  responseHeadersPolicy,
217
267
  viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
218
268
  ...dynamicBehaviorOptions,
269
+ functionAssociations: this.withDynamicFunctionAssociations("dynamicBehaviorOptions", dynamicBehaviorOptions?.functionAssociations),
219
270
  };
220
271
  }
272
+ /**
273
+ * The behavior's function associations: an override's, plus the viewer-request
274
+ * function Global Functions depends on.
275
+ *
276
+ * Spreading the override's `functionAssociations` over ours would silently
277
+ * drop that function, and with it the only thing standing between a viewer's
278
+ * own `X-Forwarded-Host` and the runtime, which trusts that header on Function
279
+ * URL events (`lambda-event.ts`): host injection into redirects and absolute
280
+ * URLs, cached for other viewers because the header is not in the cache key.
281
+ * So ours is kept, and an override claiming VIEWER_REQUEST — which CloudFront
282
+ * allows only one of per behavior — is an error rather than a replacement.
283
+ */
284
+ withDynamicFunctionAssociations(overrideName, overridden) {
285
+ if (!overridden) {
286
+ return this.dynamicCloudFrontFunctionAssociations;
287
+ }
288
+ if (!this.isFunctionCompute) {
289
+ return overridden;
290
+ }
291
+ const claimed = overridden.some((association) => association.eventType === aws_cloudfront_1.FunctionEventType.VIEWER_REQUEST);
292
+ if (claimed) {
293
+ throw new Error(`${constants_1.LOG_PREFIX} \`overrides.${overrideName}.functionAssociations\` ` +
294
+ `associates a CloudFront function with ` +
295
+ `${aws_cloudfront_1.FunctionEventType.VIEWER_REQUEST}, but NextjsGlobalFunctions needs ` +
296
+ `that event type for its own function, which overwrites ` +
297
+ `\`x-forwarded-host\` with the viewer's \`Host\` (the runtime trusts ` +
298
+ `that header behind CloudFront) and redirects repeated slashes. ` +
299
+ `CloudFront permits only one function per event type per behavior. ` +
300
+ `Move the logic to ${aws_cloudfront_1.FunctionEventType.VIEWER_RESPONSE}, or into ` +
301
+ `the app's middleware.`);
302
+ }
303
+ return [...overridden, ...this.dynamicCloudFrontFunctionAssociations];
304
+ }
305
+ /**
306
+ * `_next/image*` goes to the same origin as everything else — the Next.js
307
+ * server optimizes images in-process — but keeps its own behavior for the
308
+ * cache policy: `queryStringBehavior: all()` plus `accept` in the cache key is
309
+ * right for image requests and wrong for the rest.
310
+ */
221
311
  createImageBehaviorOptions() {
222
312
  const imageBehaviorOptions = this.props.overrides?.imageBehaviorOptions;
223
313
  // add default cache policy if not provided
@@ -245,13 +335,13 @@ class NextjsDistribution extends constructs_1.Construct {
245
335
  return {
246
336
  allowedMethods: aws_cloudfront_1.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
247
337
  cachedMethods: aws_cloudfront_1.CachedMethods.CACHE_GET_HEAD_OPTIONS,
248
- functionAssociations: this.dynamicCloudFrontFunctionAssociations,
249
- origin: this.imageOrigin,
338
+ origin: this.dynamicOrigin,
250
339
  originRequestPolicy: this.dynamicOriginResponsePolicy,
251
340
  cachePolicy,
252
341
  responseHeadersPolicy,
253
342
  viewerProtocolPolicy: aws_cloudfront_1.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
254
343
  ...imageBehaviorOptions,
344
+ functionAssociations: this.withDynamicFunctionAssociations("imageBehaviorOptions", imageBehaviorOptions?.functionAssociations),
255
345
  };
256
346
  }
257
347
  /**
@@ -278,6 +368,10 @@ class NextjsDistribution extends constructs_1.Construct {
278
368
  addDynamicBehaviors() {
279
369
  // Image Behavior
280
370
  this.distribution.addBehavior(this.getPathPattern("_next/image*"), this.imageBehaviorOptions.origin, this.imageBehaviorOptions);
371
+ // Function group behaviors, before the basePath catch-all below and after
372
+ // `_next/image*` (no group pattern can match an image request, and keeping
373
+ // the order of the unsplit case byte-identical is worth more than symmetry).
374
+ this.addFunctionGroupBehaviors();
281
375
  // Root Path Behaviors
282
376
  if (this.basePath) {
283
377
  // because we already have a basePath we don't use / instead we use /base-path
@@ -289,31 +383,410 @@ class NextjsDistribution extends constructs_1.Construct {
289
383
  // if no base path, then default behavior will handle all other paths
290
384
  }
291
385
  }
386
+ /**
387
+ * Before any behavior is computed: the budget and the `public/` checks both
388
+ * generate the group patterns, and would otherwise fail first with a less
389
+ * useful message.
390
+ */
391
+ validateFunctionGroupProps() {
392
+ if (!this.props.functionGroups?.length &&
393
+ !this.props.functionGroupBehaviors?.length) {
394
+ return;
395
+ }
396
+ if (!this.isFunctionCompute) {
397
+ throw new Error("`functionGroups` is only supported by NextjsGlobalFunctions.");
398
+ }
399
+ }
400
+ /**
401
+ * Every group behavior, final path pattern included, in the order
402
+ * {@link addFunctionGroupBehaviors} adds them.
403
+ */
404
+ functionGroupBehaviors() {
405
+ return (this.props.functionGroupBehaviors ?? []).map((behavior) => {
406
+ const group = this.props.functionGroups?.find((it) => it.name === behavior.group);
407
+ if (!group) {
408
+ throw new Error(`${constants_1.LOG_PREFIX} \`functionGroupBehaviors\` routes to function group ` +
409
+ `"${behavior.group}", which is not in \`functionGroups\`.`);
410
+ }
411
+ return {
412
+ ...behavior,
413
+ group,
414
+ pathPattern: this.getPathPattern(behavior.pattern),
415
+ };
416
+ });
417
+ }
418
+ /**
419
+ * One behavior per group pattern, most specific first.
420
+ *
421
+ * The order is the whole mechanism. CloudFront evaluates behaviors in order
422
+ * and stops at the first whose path pattern matches, and `addBehavior`
423
+ * appends — so `api/*` added before `api/reports/*` would swallow every
424
+ * report request and send it to a function whose package has no report
425
+ * entrypoint. The adapter sorted the list when it checked it against how
426
+ * `assignRoutesToGroups` packaged the same routes, so it is added as it is.
427
+ */
428
+ addFunctionGroupBehaviors() {
429
+ const originPerGroup = new Map();
430
+ for (const { group, pathPattern } of this.functionGroupBehaviors()) {
431
+ let origin = originPerGroup.get(group.name);
432
+ if (!origin) {
433
+ origin = aws_cloudfront_origins_1.FunctionUrlOrigin.withOriginAccessControl(group.functionUrl, this.props.overrides?.dynamicFunctionUrlOriginWithOACProps);
434
+ originPerGroup.set(group.name, origin);
435
+ this.grantInvoke(group.name, group.functionUrl);
436
+ }
437
+ // Same behavior options as every other dynamic route — only the origin
438
+ // differs, and it is passed separately.
439
+ const { origin: _ignored, ...behaviorOptions } = this.dynamicBehaviorOptions;
440
+ this.distribution.addBehavior(pathPattern, origin, behaviorOptions);
441
+ }
442
+ }
443
+ /**
444
+ * `lambda:InvokeFunction` for CloudFront, which a Function URL behind OAC
445
+ * needs besides the `lambda:InvokeFunctionUrl` `FunctionUrlOrigin` grants,
446
+ * and scoped the same way: to this distribution, and to calls that come
447
+ * through the Function URL.
448
+ */
449
+ grantInvoke(group, functionUrl) {
450
+ new aws_lambda_1.CfnPermission(this, `InvokeFunction-${group}`, {
451
+ action: "lambda:InvokeFunction",
452
+ principal: "cloudfront.amazonaws.com",
453
+ functionName: functionUrl.functionArn,
454
+ sourceArn: this.distribution.distributionArn,
455
+ invokedViaFunctionUrl: true,
456
+ });
457
+ }
458
+ /**
459
+ * The `assetPrefix` path that needs a behavior of its own, or `""` for none.
460
+ *
461
+ * An absolute prefix contributes its *path*: "https://cdn.example.com" needs no
462
+ * behavior, but "https://cdn.example.com/cdn" does, because `next build`
463
+ * compiles a `/cdn/_next/:path+` rewrite of its own and `next start` serves
464
+ * every bundle under that path — so a CDN fronting this distribution there has
465
+ * to be answered. A prefix equal to the `basePath` prefix is dropped — that is
466
+ * the Next.js default when `basePath` is set, and `_next/static*` already
467
+ * resolves under it, so adding a second identical pattern would make CloudFront
468
+ * reject the distribution.
469
+ */
470
+ resolveAssetPrefix() {
471
+ const prefix = (0, base_path_1.assetPrefixPath)(this.props.assetPrefix ?? "");
472
+ return (0, base_path_1.normalizeBasePath)(prefix) === this.basePath ? "" : prefix;
473
+ }
474
+ /**
475
+ * Serves `<assetPrefix>/_next/static/*` from the same S3 objects as
476
+ * `_next/static/*`.
477
+ *
478
+ * Needed because Next.js puts `assetPrefix` in front of every bundle URL it
479
+ * emits while the objects keep their `<basePath>/_next/static/...` keys, and
480
+ * `assetPrefix` sits on top of `basePath` rather than under it, so
481
+ * `getPathPattern` is deliberately not used here. Without this behavior the
482
+ * request falls through to the default one, reaches the compute origin, and
483
+ * 404s: the deployment package carries no `.next/static` directory at all.
484
+ *
485
+ * A viewer-request function does the rewrite because an S3 origin keys on the
486
+ * request URI and `originPath` can only prepend. The prefix is a synth-time
487
+ * literal, so the function is a fixed-length string operation rather than a
488
+ * parse.
489
+ */
490
+ addAssetPrefixBehavior() {
491
+ // CloudFront allows one function per event type per behavior, so an override
492
+ // that already claims VIEWER_REQUEST on the static behavior cannot coexist
493
+ // with the rewrite below — the distribution would synth and then be rejected
494
+ // at deploy, naming neither. Thrown here instead, where both halves are
495
+ // known.
496
+ const claimed = (this.staticBehaviorOptions.functionAssociations ?? []).some((association) => association.eventType === aws_cloudfront_1.FunctionEventType.VIEWER_REQUEST);
497
+ if (claimed) {
498
+ throw new Error(`${constants_1.LOG_PREFIX} \`overrides.staticBehaviorOptions.functionAssociations\` ` +
499
+ `already associates a CloudFront function with ` +
500
+ `${aws_cloudfront_1.FunctionEventType.VIEWER_REQUEST}, but serving \`assetPrefix\` ` +
501
+ `("${this.assetPrefix}") needs that event type to rewrite the request ` +
502
+ `URI to the object's key, and CloudFront permits only one function per ` +
503
+ `event type per behavior. Either drop the override, or fold its logic ` +
504
+ `into a single function and set \`assetPrefix\` to "" so this ` +
505
+ `construct adds no behavior of its own.`);
506
+ }
507
+ const rewrite = new aws_cloudfront_1.Function(this, "AssetPrefixFn", {
508
+ comment: this.getComment("NextJS assetPrefix rewrite", aws_cdk_lib_1.Stack.of(this).stackName),
509
+ code: aws_cloudfront_1.FunctionCode.fromInline(`
510
+ function handler(event) {
511
+ var request = event.request;
512
+ request.uri = ${JSON.stringify(this.basePath ? `/${this.basePath}` : "")} + request.uri.slice(${this.assetPrefix.length});
513
+ return request;
514
+ }
515
+ `),
516
+ });
517
+ this.distribution.addBehavior(`${this.assetPrefix}/_next/static*`, this.staticOrigin, {
518
+ ...this.staticBehaviorOptions,
519
+ functionAssociations: [
520
+ ...(this.staticBehaviorOptions.functionAssociations ?? []),
521
+ { eventType: aws_cloudfront_1.FunctionEventType.VIEWER_REQUEST, function: rewrite },
522
+ ],
523
+ });
524
+ }
292
525
  addStaticBehaviors() {
293
526
  this.distribution.addBehavior(this.getPathPattern("_next/static*"), this.staticOrigin, this.staticBehaviorOptions);
294
- // 22 = 25 (max) - 1 (_next/image) - 1 (_next/static) - 1 (*)
295
- if (this.props.publicDirEntries.length >= 22) {
296
- throw new Error(`Too many public/ files in Next.js build. CloudFront limits Distributions to 25 Cache Behaviors. See documented limit here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions. Try including all public files into 1 top level directory (i.e. static/*).`);
527
+ if (this.assetPrefix) {
528
+ this.addAssetPrefixBehavior();
297
529
  }
530
+ const publicPathPatterns = this.publicPathPatterns();
531
+ this.assertBehaviorBudget(publicPathPatterns.length);
532
+ this.assertNoPublicCollisions(publicPathPatterns);
533
+ for (const pathPattern of publicPathPatterns) {
534
+ this.distribution.addBehavior(pathPattern, this.staticOrigin, this.staticBehaviorOptions);
535
+ }
536
+ }
537
+ /**
538
+ * The behavior path pattern for each top-level `public/` entry, final form:
539
+ * `/*` for a directory and the basePath prefix both applied.
540
+ *
541
+ * An entry whose name has no character CloudFront can spell is left out, with
542
+ * a warning, rather than given a pattern of nothing but wildcards. `фото/` is
543
+ * `????????/*` — any 8-byte first segment — and public/ behaviors are added
544
+ * ahead of every compute behavior, so it would send `/products/42` and
545
+ * `/settings/*` to S3, which answers 403. Leaving the entry out costs its own
546
+ * files instead: those requests reach the compute, which does not have them,
547
+ * and 404. One literal character is enough to keep a pattern narrow —
548
+ * `????????.jpg` only matches `.jpg` requests — so only the all-wildcard ones
549
+ * go.
550
+ *
551
+ * The length limit is checked here, on the final pattern, rather than in
552
+ * {@link toPathPattern}: the `/*` and the basePath count against it too, and a
553
+ * pattern that passed without them failed at deploy instead.
554
+ */
555
+ publicPathPatterns() {
556
+ const patterns = [];
557
+ const unmatchable = [];
298
558
  for (const publicFile of this.props.publicDirEntries) {
299
- const pathPattern = publicFile.isDirectory
300
- ? `${publicFile.name}/*`
301
- : publicFile.name;
302
- if (!/^[a-zA-Z0-9_\-.*$/~"'@:+?&]+$/.test(pathPattern)) {
303
- throw new Error(`Invalid CloudFront Distribution Cache Behavior Path Pattern: ${pathPattern}. Please see documentation here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesPathPattern`);
559
+ const name = toPathPattern(publicFile.name);
560
+ if (!/[^?*/]/.test(name)) {
561
+ unmatchable.push(`"${publicFile.name}"`);
562
+ continue;
563
+ }
564
+ const pathPattern = this.getPathPattern(publicFile.isDirectory ? `${name}/*` : name);
565
+ if (pathPattern.length > MAX_PATH_PATTERN_LENGTH) {
566
+ throw new Error(`The public/ entry "${publicFile.name}" needs a ` +
567
+ `${pathPattern.length}-character CloudFront path pattern, over ` +
568
+ `the ${MAX_PATH_PATTERN_LENGTH}-character ` +
569
+ "limit. Rename it, or move it into a subdirectory of public/ whose " +
570
+ "own name is short enough. See " +
571
+ "https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesCacheBehavior.html#DownloadDistValuesPathPattern");
304
572
  }
305
- const finalPathPattern = this.getPathPattern(pathPattern);
306
- this.distribution.addBehavior(finalPathPattern, this.staticOrigin, this.staticBehaviorOptions);
573
+ patterns.push(pathPattern);
574
+ }
575
+ if (unmatchable.length > 0) {
576
+ aws_cdk_lib_1.Annotations.of(this).addWarning(`${constants_1.LOG_PREFIX} These top-level public/ entries have no character a ` +
577
+ "CloudFront path pattern can spell, so their pattern would be " +
578
+ "wildcards alone and would capture every app route of the same " +
579
+ `length. They get no behavior, so their requests reach the server, ` +
580
+ `which reads them from S3 instead: ${unmatchable.join(", ")}. To serve ` +
581
+ "them from S3 directly, rename them, or move them into a public/ " +
582
+ "subdirectory whose name has at least one ASCII letter or digit.");
307
583
  }
584
+ return patterns;
585
+ }
586
+ /**
587
+ * Refuse a group behavior that a `public/` behavior would make unreachable.
588
+ *
589
+ * `public/` behaviors are added first, and CloudFront stops at the first match,
590
+ * so two cases send a group's route to S3 instead of its function — which is
591
+ * why this is checked at synth, where both sides are known:
592
+ * - the same pattern twice: `public/docs/` and `/docs/**` both deploy as
593
+ * `docs/*`. The synth succeeded and CloudFront rejected the deploy.
594
+ * - a group pattern under a public directory: `/docs/guide/**` behind
595
+ * `docs/*` deploys and never matches.
596
+ */
597
+ assertNoPublicCollisions(publicPathPatterns) {
598
+ const publicRegexes = publicPathPatterns.map((pattern) => ({
599
+ pattern,
600
+ regex: (0, function_groups_1.cloudFrontPatternRegex)(`/${pattern.replace(/^\/+/, "")}`),
601
+ }));
602
+ for (const { group, route, pathPattern } of this.functionGroupBehaviors()) {
603
+ const duplicate = publicPathPatterns.includes(pathPattern);
604
+ // Matching the group pattern's own text is enough: its only wildcard is a
605
+ // trailing `*`, so a public pattern that matches the text up to and
606
+ // including it matches every URL the group pattern does.
607
+ const shadow = duplicate
608
+ ? undefined
609
+ : publicRegexes.find(({ regex }) => regex.test(`/${pathPattern.replace(/^\/+/, "")}`));
610
+ if (!duplicate && !shadow) {
611
+ continue;
612
+ }
613
+ throw new Error(`${constants_1.LOG_PREFIX} \`functionGroups\` pattern "${route}" (group ` +
614
+ `"${group.name}") ` +
615
+ (duplicate
616
+ ? `deploys as the path pattern "${pathPattern}", which a top-level ` +
617
+ `public/ entry already uses — CloudFront rejects a distribution ` +
618
+ `with two behaviors on one path pattern. `
619
+ : `deploys as "${pathPattern}", but the top-level public/ entry ` +
620
+ `behind "${shadow.pattern}" is matched first and sends every ` +
621
+ `such request to S3, so the group's function would never see ` +
622
+ `them. `) +
623
+ `Move those public/ files under a directory no route uses, or ` +
624
+ `group a different path.`);
625
+ }
626
+ }
627
+ /**
628
+ * CloudFront has a per-distribution cache behavior quota, counting the default
629
+ * one — 75 unless raised, and `maxCacheBehaviors` says which — and there are
630
+ * three things competing for it: `public/` entries, function groups, and
631
+ * cdk-nextjs's own fixed set.
632
+ * Checked in one place so the error can say which to cut.
633
+ *
634
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions
635
+ */
636
+ assertBehaviorBudget(publicPatterns) {
637
+ const limit = this.props.maxCacheBehaviors ?? DEFAULT_MAX_CACHE_BEHAVIORS;
638
+ if (aws_cdk_lib_1.Token.isUnresolved(limit)) {
639
+ return;
640
+ }
641
+ const groupPatterns = this.functionGroupBehaviors().length;
642
+ // The default behavior, `_next/image*`, `_next/static*`, plus — with a
643
+ // basePath — the two that stand in for the default behavior's coverage, and
644
+ // — with a path-style assetPrefix — the one that serves bundles under it.
645
+ // `this.basePath`, not the raw prop: `basePath: "/"` normalizes to `""` and
646
+ // adds no behaviors, so counting it added 2 to the total and could throw
647
+ // "over the limit" on an app that is under it.
648
+ const fixed = 3 + (this.basePath ? 2 : 0) + (this.assetPrefix ? 1 : 0);
649
+ const total = fixed + publicPatterns + groupPatterns;
650
+ if (total <= limit) {
651
+ return;
652
+ }
653
+ const parts = [
654
+ `${fixed} used by cdk-nextjs itself`,
655
+ `${publicPatterns} for top-level public/ entries`,
656
+ ];
657
+ if (groupPatterns) {
658
+ parts.push(`${groupPatterns} for \`functionGroups\` patterns`);
659
+ }
660
+ throw new Error(`This Next.js app needs ${total} CloudFront cache behaviors, over the ` +
661
+ `limit of ${limit} per distribution: ${parts.join(", ")}. ` +
662
+ `Move public/ files into a single top-level directory (one behavior ` +
663
+ `serves \`static/*\`)` +
664
+ (groupPatterns
665
+ ? `, and prefer one subtree pattern per function group over several ` +
666
+ `exact paths`
667
+ : ``) +
668
+ `. If your account's quota is higher than ${limit}, set ` +
669
+ `\`maxCacheBehaviors\` to it. See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions`);
308
670
  }
309
671
  /**
310
672
  * Optionally prepends base path to given path pattern.
673
+ *
674
+ * A trailing slash on `pathPattern` is load-bearing and survives, which is why
675
+ * this concatenates rather than going through `joinPath`. The build's
676
+ * `functionGroupBehaviors` hold both "pricing" and "pricing/" for a
677
+ * `trailingSlash` app, and normalizing the second one collapsed it onto the
678
+ * first: `addBehavior` was
679
+ * then called twice with `/base/pricing`, which CloudFront rejects at deploy
680
+ * ("more than one cache behavior has the same path pattern"), and the
681
+ * canonical `/base/pricing/` was left to the `/base/*` catch-all — the misroute
682
+ * the second pattern exists to prevent.
311
683
  */
312
684
  getPathPattern(pathPattern) {
313
- return this.basePath
314
- ? `/${(0, base_path_1.joinPath)(this.basePath, pathPattern)}`
315
- : pathPattern;
685
+ if (!this.basePath) {
686
+ return pathPattern;
687
+ }
688
+ return `/${this.basePath}/${pathPattern.replace(/^\/+/, "")}`;
316
689
  }
317
690
  }
318
691
  exports.NextjsDistribution = NextjsDistribution;
319
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWRpc3RyaWJ1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9uZXh0anMtZGlzdHJpYnV0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSw2Q0FBOEM7QUFFOUMsK0RBMkJvQztBQUNwQywrRUFNNEM7QUFJNUMsMkNBQXVDO0FBQ3ZDLDJDQUF5QztBQUl6QyxpREFBZ0U7QUE4RGhFLE1BQWEsa0JBQW1CLFNBQVEsc0JBQVM7O0lBQy9DLFlBQVksQ0FBZTtJQUVuQixLQUFLLENBQTBCO0lBQ3ZDOzs7OztPQUtHO0lBQ0ssUUFBUSxDQUFTO0lBQ3pCOzs7T0FHRztJQUNLLDZCQUE2QixHQUFvQztRQUN2RSxrQkFBa0IsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUU7UUFDdkMsWUFBWSxFQUFFO1lBQ1osV0FBVyxFQUFFLG1DQUFrQixDQUFDLFVBQVU7WUFDMUMsUUFBUSxFQUFFLEtBQUs7U0FDaEI7UUFDRCxjQUFjLEVBQUU7WUFDZCxRQUFRLEVBQUUsS0FBSztZQUNmLGNBQWMsRUFBRSxzQ0FBcUIsQ0FBQywrQkFBK0I7U0FDdEU7UUFFRCx1QkFBdUIsRUFBRTtZQUN2QixtQkFBbUIsRUFBRSxzQkFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7WUFDdkMsaUJBQWlCLEVBQUUsSUFBSTtZQUN2QixRQUFRLEVBQUUsS0FBSztZQUNmLE9BQU8sRUFBRSxJQUFJO1NBQ2Q7UUFDRCxhQUFhLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRTtLQUN0RSxDQUFDO0lBQ00sWUFBWSxDQUFVO0lBQ3RCLGFBQWEsQ0FBVTtJQUN2QixXQUFXLENBQVU7SUFDckIsMkJBQTJCLENBQXVCO0lBQ2xELHFDQUFxQyxDQUF3QjtJQUM3RCxpQkFBaUIsQ0FBVTtJQUMzQixxQkFBcUIsQ0FBa0I7SUFDdkMsc0JBQXNCLENBQWtCO0lBQ3hD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QVUsQ0FBQyxJQUFJLElBQUk7Z0JBQ3hCLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ3BCLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDdkQsTUFBTSxJQUFJLEtBQUssQ0FDYixnRUFBZ0UsV0FBVyx3S0FBd0ssQ0FDcFAsQ0FBQztZQUNKLENBQUM7WUFDRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDMUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQzNCLGdCQUFnQixFQUNoQixJQUFJLENBQUMsWUFBWSxFQUNqQixJQUFJLENBQUMscUJBQXFCLENBQzNCLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUNEOztPQUVHO0lBQ0ssY0FBYyxDQUFDLFdBQW1CO1FBQ3hDLE9BQU8sSUFBSSxDQUFDLFFBQVE7WUFDbEIsQ0FBQyxDQUFDLElBQUksSUFBQSxvQkFBUSxFQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLEVBQUU7WUFDNUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztJQUNsQixDQUFDOztBQS9XSCxnREFnWEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEdXJhdGlvbiwgU3RhY2sgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IElDZXJ0aWZpY2F0ZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyXCI7XG5pbXBvcnQge1xuICBBZGRCZWhhdmlvck9wdGlvbnMsXG4gIEFsbG93ZWRNZXRob2RzLFxuICBCZWhhdmlvck9wdGlvbnMsXG4gIENhY2hlQ29va2llQmVoYXZpb3IsXG4gIENhY2hlSGVhZGVyQmVoYXZpb3IsXG4gIENhY2hlUG9saWN5LFxuICBDYWNoZVBvbGljeVByb3BzLFxuICBDYWNoZVF1ZXJ5U3RyaW5nQmVoYXZpb3IsXG4gIENhY2hlZE1ldGhvZHMsXG4gIEZ1bmN0aW9uIGFzIENsb3VkRnJvbnRGdW5jdGlvbixcbiAgRGlzdHJpYnV0aW9uLFxuICBGdW5jdGlvbkFzc29jaWF0aW9uLFxuICBGdW5jdGlvbkNvZGUsXG4gIEZ1bmN0aW9uRXZlbnRUeXBlLFxuICBIZWFkZXJzRnJhbWVPcHRpb24sXG4gIEhlYWRlcnNSZWZlcnJlclBvbGljeSxcbiAgSHR0cFZlcnNpb24sXG4gIElPcmlnaW4sXG4gIElPcmlnaW5SZXF1ZXN0UG9saWN5LFxuICBPcmlnaW5Qcm90b2NvbFBvbGljeSxcbiAgT3JpZ2luUmVxdWVzdFBvbGljeSxcbiAgUmVzcG9uc2VIZWFkZXJzUG9saWN5LFxuICBSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcyxcbiAgUmVzcG9uc2VTZWN1cml0eUhlYWRlcnNCZWhhdmlvcixcbiAgU2VjdXJpdHlQb2xpY3lQcm90b2NvbCxcbiAgVmlld2VyUHJvdG9jb2xQb2xpY3ksXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udFwiO1xuaW1wb3J0IHtcbiAgRnVuY3Rpb25VcmxPcmlnaW4sXG4gIEZ1bmN0aW9uVXJsT3JpZ2luV2l0aE9BQ1Byb3BzLFxuICBTM0J1Y2tldE9yaWdpbixcbiAgVnBjT3JpZ2luLFxuICBWcGNPcmlnaW5XaXRoRW5kcG9pbnRQcm9wcyxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZGZyb250LW9yaWdpbnNcIjtcbmltcG9ydCB7IElBcHBsaWNhdGlvbkxvYWRCYWxhbmNlciB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWxhc3RpY2xvYWRiYWxhbmNpbmd2MlwiO1xuaW1wb3J0IHsgSUZ1bmN0aW9uVXJsIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIjtcbmltcG9ydCB7IElCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgTmV4dGpzVHlwZSB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT3B0aW9uYWxEaXN0cmlidXRpb25Qcm9wcyB9IGZyb20gXCIuL2dlbmVyYXRlZC1zdHJ1Y3RzL09wdGlvbmFsRGlzdHJpYnV0aW9uUHJvcHNcIjtcbmltcG9ydCB7IE9wdGlvbmFsUzNPcmlnaW5CdWNrZXRXaXRoT0FDUHJvcHMgfSBmcm9tIFwiLi9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbFMzT3JpZ2luQnVja2V0V2l0aE9BQ1Byb3BzXCI7XG5pbXBvcnQgeyBQdWJsaWNEaXJFbnRyeSB9IGZyb20gXCIuL25leHRqcy1idWlsZC9uZXh0anMtYnVpbGRcIjtcbmltcG9ydCB7IGpvaW5QYXRoLCBub3JtYWxpemVCYXNlUGF0aCB9IGZyb20gXCIuL3V0aWxzL2Jhc2UtcGF0aFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE5leHRqc0Rpc3RyaWJ1dGlvbk92ZXJyaWRlcyB7XG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvblByb3BzPzogT3B0aW9uYWxEaXN0cmlidXRpb25Qcm9wcztcbiAgcmVhZG9ubHkgaW1hZ2VCZWhhdmlvck9wdGlvbnM/OiBBZGRCZWhhdmlvck9wdGlvbnM7XG4gIHJlYWRvbmx5IGltYWdlQ2FjaGVQb2xpY3lQcm9wcz86IENhY2hlUG9saWN5UHJvcHM7XG4gIHJlYWRvbmx5IGltYWdlUmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM/OiBSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcztcbiAgcmVhZG9ubHkgZHluYW1pY0JlaGF2aW9yT3B0aW9ucz86IEFkZEJlaGF2aW9yT3B0aW9ucztcbiAgcmVhZG9ubHkgZHluYW1pY0NhY2hlUG9saWN5UHJvcHM/OiBDYWNoZVBvbGljeVByb3BzO1xuICByZWFkb25seSBkeW5hbWljUmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM/OiBSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcztcbiAgcmVhZG9ubHkgZHluYW1pY0Z1bmN0aW9uVXJsT3JpZ2luV2l0aE9BQ1Byb3BzPzogRnVuY3Rpb25VcmxPcmlnaW5XaXRoT0FDUHJvcHM7XG4gIHJlYWRvbmx5IGR5bmFtaWNWcGNPcmlnaW5XaXRoRW5kcG9pbnRQcm9wcz86IFZwY09yaWdpbldpdGhFbmRwb2ludFByb3BzO1xuICByZWFkb25seSBpbWFnZUZ1bmN0aW9uVXJsT3JpZ2luV2l0aE9BQ1Byb3BzPzogRnVuY3Rpb25VcmxPcmlnaW5XaXRoT0FDUHJvcHM7XG4gIHJlYWRvbmx5IHN0YXRpY0JlaGF2aW9yT3B0aW9ucz86IEFkZEJlaGF2aW9yT3B0aW9ucztcbiAgcmVhZG9ubHkgc3RhdGljUmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM/OiBSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcztcbiAgcmVhZG9ubHkgczNCdWNrZXRPcmlnaW5Qcm9wcz86IE9wdGlvbmFsUzNPcmlnaW5CdWNrZXRXaXRoT0FDUHJvcHM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzRGlzdHJpYnV0aW9uUHJvcHMge1xuICAvKipcbiAgICogQnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0cy5cbiAgICogTXVzdCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0byBzZXJ2ZSBzdGF0aWMgZmlsZXMuXG4gICAqL1xuICByZWFkb25seSBhc3NldHNCdWNrZXQ6IElCdWNrZXQ7XG4gIC8qKlxuICAgKiBVUkkgcGF0aCBwcmVmaXggdGhlIGFwcCBpcyBzZXJ2ZWQgYXQuIFN1cnJvdW5kaW5nIHNsYXNoZXMgYXJlIG5vcm1hbGl6ZWRcbiAgICogYXdheSwgc28gXCIvYmFzZVwiLCBcImJhc2VcIiBhbmQgXCIvYmFzZS9cIiBhbGwgcHJvZHVjZSB0aGUgc2FtZSBjYWNoZSBiZWhhdmlvcnMuXG4gICAqL1xuICByZWFkb25seSBiYXNlUGF0aD86IHN0cmluZztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGJ1dCBvbmx5IGFwcGxpY2FibGUgZm9yIGBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTYFxuICAgKi9cbiAgcmVhZG9ubHkgY2VydGlmaWNhdGU/OiBJQ2VydGlmaWNhdGU7XG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbj86IERpc3RyaWJ1dGlvbjtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlNgXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvblVybD86IElGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIEZ1bmN0aW9uIFVSTCBvZiB0aGUgZGVkaWNhdGVkIGltYWdlIG9wdGltaXphdGlvbiBMYW1iZGEuIE9ubHkgYXBwbGljYWJsZVxuICAgKiB0byBgTmV4dGpzVHlwZS5HTE9CQUxfRlVOQ1RJT05TYCwgYW5kIG9ubHkgd2hlbiB0aGUgZGVkaWNhdGVkIGltYWdlXG4gICAqIGZ1bmN0aW9uIGlzIGVuYWJsZWQuIFdoZW4gb21pdHRlZCwgdGhlIGBfbmV4dC9pbWFnZSpgIGJlaGF2aW9yIHBvaW50cyBhdFxuICAgKiB0aGUgZHluYW1pYyBvcmlnaW4sIHdoaWNoIHNlcnZlcyBpbWFnZSBvcHRpbWl6YXRpb24gZnJvbSB0aGUgTmV4dC5qc1xuICAgKiBzZXJ2ZXIgaXRzZWxmLlxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2VGdW5jdGlvblVybD86IElGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTYCBvciBgTmV4dGpzVHlwZS5SRUdJT05BTF9DT05UQUlORVJTYFxuICAgKi9cbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyPzogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyO1xuICByZWFkb25seSBuZXh0anNUeXBlOiBOZXh0anNUeXBlO1xuICAvKipcbiAgICogT3ZlcnJpZGUgcHJvcHMgZm9yIGV2ZXJ5IGNvbnN0cnVjdC5cbiAgICovXG4gIHJlYWRvbmx5IG92ZXJyaWRlcz86IE5leHRqc0Rpc3RyaWJ1dGlvbk92ZXJyaWRlcztcbiAgLyoqXG4gICAqIEVudHJpZXMgKGZpbGVzL2RpcmVjdG9yaWVzKSB3aXRoaW4gTmV4dC5qcyBhcHAncyBwdWJsaWMgZGlyZWN0b3J5LiBVc2VkIHRvXG4gICAqIGFkZCBzdGF0aWMgYmVoYXZpb3JzIHRvIGRpc3RyaWJ1dGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHB1YmxpY0RpckVudHJpZXM6IFB1YmxpY0RpckVudHJ5W107XG59XG5cbmV4cG9ydCBjbGFzcyBOZXh0anNEaXN0cmlidXRpb24gZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBkaXN0cmlidXRpb246IERpc3RyaWJ1dGlvbjtcblxuICBwcml2YXRlIHByb3BzOiBOZXh0anNEaXN0cmlidXRpb25Qcm9wcztcbiAgLyoqXG4gICAqIGBwcm9wcy5iYXNlUGF0aGAgbm9ybWFsaXplZCB0byBhIGJhcmUgcGF0aCBzZWdtZW50LiBUaGlzIGNvbnN0cnVjdCBpcyB0aGVcbiAgICogb25lIHBsYWNlIHRoYXQgbmVlZHMgaXQgd2l0aCBhIGxlYWRpbmcgc2xhc2gg4oCUIENsb3VkRnJvbnQgcGF0aCBwYXR0ZXJucyBhcmVcbiAgICogd3JpdHRlbiBhZ2FpbnN0IHRoZSByZXF1ZXN0IHBhdGgg4oCUIHNvIGl0IHByZXBlbmRzIGl0cyBvd24gcmF0aGVyIHRoYW5cbiAgICogcmVseWluZyBvbiB0aGUgY2FsbGVyIGhhdmluZyBwYXNzZWQgb25lLlxuICAgKi9cbiAgcHJpdmF0ZSBiYXNlUGF0aDogc3RyaW5nO1xuICAvKipcbiAgICogQ29tbW9uIHNlY3VyaXR5IGhlYWRlcnMgYXBwbGllZCBieSBkZWZhdWx0IHRvIGFsbCBvcmlnaW5zXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkRnJvbnQvbGF0ZXN0L0RldmVsb3Blckd1aWRlL3VzaW5nLW1hbmFnZWQtcmVzcG9uc2UtaGVhZGVycy1wb2xpY2llcy5odG1sI21hbmFnZWQtcmVzcG9uc2UtaGVhZGVycy1wb2xpY2llcy1zZWN1cml0eVxuICAgKi9cbiAgcHJpdmF0ZSBjb21tb25TZWN1cml0eUhlYWRlcnNCZWhhdmlvcjogUmVzcG9uc2VTZWN1cml0eUhlYWRlcnNCZWhhdmlvciA9IHtcbiAgICBjb250ZW50VHlwZU9wdGlvbnM6IHsgb3ZlcnJpZGU6IGZhbHNlIH0sXG4gICAgZnJhbWVPcHRpb25zOiB7XG4gICAgICBmcmFtZU9wdGlvbjogSGVhZGVyc0ZyYW1lT3B0aW9uLlNBTUVPUklHSU4sXG4gICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgfSxcbiAgICByZWZlcnJlclBvbGljeToge1xuICAgICAgb3ZlcnJpZGU6IGZhbHNlLFxuICAgICAgcmVmZXJyZXJQb2xpY3k6IEhlYWRlcnNSZWZlcnJlclBvbGljeS5TVFJJQ1RfT1JJR0lOX1dIRU5fQ1JPU1NfT1JJR0lOLFxuICAgIH0sXG5cbiAgICBzdHJpY3RUcmFuc3BvcnRTZWN1cml0eToge1xuICAgICAgYWNjZXNzQ29udHJvbE1heEFnZTogRHVyYXRpb24uZGF5cygzNjUpLFxuICAgICAgaW5jbHVkZVN1YmRvbWFpbnM6IHRydWUsXG4gICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgICBwcmVsb2FkOiB0cnVlLFxuICAgIH0sXG4gICAgeHNzUHJvdGVjdGlvbjogeyBvdmVycmlkZTogZmFsc2UsIHByb3RlY3Rpb246IHRydWUsIG1vZGVCbG9jazogdHJ1ZSB9LFxuICB9O1xuICBwcml2YXRlIHN0YXRpY09yaWdpbjogSU9yaWdpbjtcbiAgcHJpdmF0ZSBkeW5hbWljT3JpZ2luOiBJT3JpZ2luO1xuICBwcml2YXRlIGltYWdlT3JpZ2luOiBJT3JpZ2luO1xuICBwcml2YXRlIGR5bmFtaWNPcmlnaW5SZXNwb25zZVBvbGljeTogSU9yaWdpblJlcXVlc3RQb2xpY3k7XG4gIHByaXZhdGUgZHluYW1pY0Nsb3VkRnJvbnRGdW5jdGlvbkFzc29jaWF0aW9uczogRnVuY3Rpb25Bc3NvY2lhdGlvbltdO1xuICBwcml2YXRlIGlzRnVuY3Rpb25Db21wdXRlOiBib29sZWFuO1xuICBwcml2YXRlIHN0YXRpY0JlaGF2aW9yT3B0aW9uczogQmVoYXZpb3JPcHRpb25zO1xuICBwcml2YXRlIGR5bmFtaWNCZWhhdmlvck9wdGlvbnM6IEJlaGF2aW9yT3B0aW9ucztcbiAgcHJpdmF0ZSBpbWFnZUJlaGF2aW9yT3B0aW9uczogQmVoYXZpb3JPcHRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBOZXh0anNEaXN0cmlidXRpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICAgIHRoaXMuYmFzZVBhdGggPSBub3JtYWxpemVCYXNlUGF0aChwcm9wcy5iYXNlUGF0aCk7XG4gICAgdGhpcy5zdGF0aWNPcmlnaW4gPSB0aGlzLmNyZWF0ZVN0YXRpY09yaWdpbigpO1xuICAgIHRoaXMuaXNGdW5jdGlvbkNvbXB1dGUgPSBwcm9wcy5uZXh0anNUeXBlID09PSBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlM7XG4gICAgdGhpcy5keW5hbWljT3JpZ2luID0gdGhpcy5jcmVhdGVEeW5hbWljT3JpZ2luKCk7XG4gICAgdGhpcy5pbWFnZU9yaWdpbiA9IHRoaXMuY3JlYXRlSW1hZ2VPcmlnaW4oKTtcbiAgICB0aGlzLmR5bmFtaWNPcmlnaW5SZXNwb25zZVBvbGljeSA9IHRoaXMuY3JlYXRlRHluYW1pY09yaWdpblJlcXVlc3RQb2xpY3koKTtcbiAgICB0aGlzLmR5bmFtaWNDbG91ZEZyb250RnVuY3Rpb25Bc3NvY2lhdGlvbnMgPVxuICAgICAgdGhpcy5jcmVhdGVEeW5hbWljQ2xvdWRGcm9udEZ1bmN0aW9uQXNzb2NpYXRpb25zKCk7XG4gICAgdGhpcy5zdGF0aWNCZWhhdmlvck9wdGlvbnMgPSB0aGlzLmNyZWF0ZVN0YXRpY0JlaGF2aW9yT3B0aW9ucygpO1xuICAgIHRoaXMuZHluYW1pY0JlaGF2aW9yT3B0aW9ucyA9IHRoaXMuY3JlYXRlRHluYW1pY0JlaGF2aW9yT3B0aW9ucygpO1xuICAgIHRoaXMuaW1hZ2VCZWhhdmlvck9wdGlvbnMgPSB0aGlzLmNyZWF0ZUltYWdlQmVoYXZpb3JPcHRpb25zKCk7XG4gICAgdGhpcy5kaXN0cmlidXRpb24gPSB0aGlzLmdldERpc3RyaWJ1dGlvbigpO1xuICAgIHRoaXMuYWRkU3RhdGljQmVoYXZpb3JzKCk7XG4gICAgdGhpcy5hZGREeW5hbWljQmVoYXZpb3JzKCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIENsb3VkRnJvbnQgY29tbWVudCB0aGF0IGlzIHNhZmUgZm9yIHRoZSAxMjggY2hhcmFjdGVyIGxpbWl0LlxuICAgKiBJZiB0aGUgZnVsbCBjb21tZW50IHdpdGggc3RhY2sgbmFtZSBleGNlZWRzIDEyOCBjaGFyYWN0ZXJzLCByZXR1cm5zIHRoZSBiYXNlIGNvbW1lbnQgb25seS5cbiAgICogQHBhcmFtIGJhc2VDb21tZW50IFRoZSBiYXNlIGNvbW1lbnQgdGV4dFxuICAgKiBAcGFyYW0gc3RhY2tOYW1lIFRoZSBzdGFjayBuYW1lIHRvIGFwcGVuZFxuICAgKiBAcmV0dXJucyBBIGNvbW1lbnQgc3RyaW5nIHRoYXQgaXMgZ3VhcmFudGVlZCB0byBiZSA8IDEyOCBjaGFyYWN0ZXJzXG4gICAqL1xuICBwcml2YXRlIGdldENvbW1lbnQoYmFzZUNvbW1lbnQ6IHN0cmluZywgc3RhY2tOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGZ1bGxDb21tZW50ID0gYCR7YmFzZUNvbW1lbnR9IGZvciAke3N0YWNrTmFtZX1gO1xuICAgIHJldHVybiBmdWxsQ29tbWVudC5sZW5ndGggPCAxMjggPyBmdWxsQ29tbWVudCA6IGJhc2VDb21tZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVTdGF0aWNPcmlnaW4oKTogSU9yaWdpbiB7XG4gICAgcmV0dXJuIFMzQnVja2V0T3JpZ2luLndpdGhPcmlnaW5BY2Nlc3NDb250cm9sKFxuICAgICAgdGhpcy5wcm9wcy5hc3NldHNCdWNrZXQsXG4gICAgICB0aGlzLnByb3BzLm92ZXJyaWRlcz8uczNCdWNrZXRPcmlnaW5Qcm9wcyxcbiAgICApO1xuICB9XG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY09yaWdpbigpOiBJT3JpZ2luIHtcbiAgICBpZiAodGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZSkge1xuICAgICAgaWYgKCF0aGlzLnByb3BzLmZ1bmN0aW9uVXJsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgTmV4dGpzRGlzdHJpYnV0aW9uUHJvcHMuZnVuY3Rpb25VcmxcIik7XG4gICAgICB9XG4gICAgICByZXR1cm4gRnVuY3Rpb25VcmxPcmlnaW4ud2l0aE9yaWdpbkFjY2Vzc0NvbnRyb2woXG4gICAgICAgIHRoaXMucHJvcHMuZnVuY3Rpb25VcmwsXG4gICAgICAgIHRoaXMucHJvcHMub3ZlcnJpZGVzPy5keW5hbWljRnVuY3Rpb25VcmxPcmlnaW5XaXRoT0FDUHJvcHMsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsb2FkQmFsYW5jZXIgPSB0aGlzLnByb3BzLmxvYWRCYWxhbmNlcjtcbiAgICAgIGlmICghbG9hZEJhbGFuY2VyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgTmV4dGpzRGlzdHJpYnV0aW9uUHJvcHMubG9hZEJhbGFuY2VyXCIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFZwY09yaWdpbi53aXRoQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIobG9hZEJhbGFuY2VyLCB7XG4gICAgICAgIHByb3RvY29sUG9saWN5OiB0aGlzLnByb3BzLmNlcnRpZmljYXRlXG4gICAgICAgICAgPyBPcmlnaW5Qcm90b2NvbFBvbGljeS5IVFRQU19PTkxZXG4gICAgICAgICAgOiBPcmlnaW5Qcm90b2NvbFBvbGljeS5IVFRQX09OTFksXG4gICAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5keW5hbWljVnBjT3JpZ2luV2l0aEVuZHBvaW50UHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIEEgZGVkaWNhdGVkIGltYWdlIG9wdGltaXphdGlvbiBMYW1iZGEgaXMgb25seSB3aXJlZCB1cCB3aGVuXG4gICAqIHtAbGluayBOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5pbWFnZUZ1bmN0aW9uVXJsfSBpcyBzdXBwbGllZCwgd2hpY2ggdG9kYXlcbiAgICogb25seSBgTmV4dGpzVHlwZS5HTE9CQUxfRlVOQ1RJT05TYCBkb2VzLiBPdGhlcndpc2UgYF9uZXh0L2ltYWdlKmAga2VlcHNcbiAgICogZ29pbmcgdG8gdGhlIGR5bmFtaWMgb3JpZ2luLCB3aGVyZSB0aGUgTmV4dC5qcyBzZXJ2ZXIgb3B0aW1pemVzIGltYWdlc1xuICAgKiBpdHNlbGYuXG4gICAqXG4gICAqIFRoZSBgX25leHQvaW1hZ2UqYCBiZWhhdmlvciBpcyBrZXB0IGVpdGhlciB3YXk6IGl0cyBjYWNoZSBwb2xpY3lcbiAgICogKGBxdWVyeVN0cmluZ0JlaGF2aW9yOiBhbGwoKWAsIGBhY2NlcHRgIGluIHRoZSBjYWNoZSBrZXkpIGlzIHRoZSByaWdodCBvbmVcbiAgICogZm9yIGltYWdlIHJlcXVlc3RzIHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggb3JpZ2luIGFuc3dlcnMgdGhlbS5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlSW1hZ2VPcmlnaW4oKTogSU9yaWdpbiB7XG4gICAgaWYgKCF0aGlzLmlzRnVuY3Rpb25Db21wdXRlIHx8ICF0aGlzLnByb3BzLmltYWdlRnVuY3Rpb25VcmwpIHtcbiAgICAgIHJldHVybiB0aGlzLmR5bmFtaWNPcmlnaW47XG4gICAgfVxuICAgIHJldHVybiBGdW5jdGlvblVybE9yaWdpbi53aXRoT3JpZ2luQWNjZXNzQ29udHJvbChcbiAgICAgIHRoaXMucHJvcHMuaW1hZ2VGdW5jdGlvblVybCxcbiAgICAgIHtcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmR5bmFtaWNGdW5jdGlvblVybE9yaWdpbldpdGhPQUNQcm9wcyxcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmltYWdlRnVuY3Rpb25VcmxPcmlnaW5XaXRoT0FDUHJvcHMsXG4gICAgICB9LFxuICAgICk7XG4gIH1cbiAgLyoqXG4gICAqIExhbWJkYSBGdW5jdGlvbiBVUkxzIFwiZXhwZWN0IHRoZSBgSG9zdGAgaGVhZGVyIHRvIGNvbnRhaW4gdGhlIG9yaWdpbiBkb21haW5cbiAgICogbmFtZSwgbm90IHRoZSBkb21haW4gbmFtZSBvZiB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24uXCJcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvdXNpbmctbWFuYWdlZC1vcmlnaW4tcmVxdWVzdC1wb2xpY2llcy5odG1sI21hbmFnZWQtb3JpZ2luLXJlcXVlc3QtcG9saWN5LWFsbC12aWV3ZXItZXhjZXB0LWhvc3QtaGVhZGVyXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUR5bmFtaWNPcmlnaW5SZXF1ZXN0UG9saWN5KCk6IElPcmlnaW5SZXF1ZXN0UG9saWN5IHtcbiAgICByZXR1cm4gdGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZVxuICAgICAgPyBPcmlnaW5SZXF1ZXN0UG9saWN5LkFMTF9WSUVXRVJfRVhDRVBUX0hPU1RfSEVBREVSXG4gICAgICA6IE9yaWdpblJlcXVlc3RQb2xpY3kuQUxMX1ZJRVdFUjtcbiAgfVxuICAvKipcbiAgICogRW5zdXJlcyBOZXh0LmpzIGByZXF1ZXN0LnVybGAgd2lsbCBiZSBjb3JyZWN0IGRvbWFpbiBpbnN0ZWFkIG9mIFVSTCBvZlxuICAgKiBjb21wdXRlIChMYW1iZGEgb3IgRmFyZ2F0ZSlcbiAgICogQHNlZSBodHRwczovL29wZW4tbmV4dC5qcy5vcmcvYWR2YW5jZWQvd29ya2Fyb3VuZCN3b3JrYXJvdW5kLXNldC14LWZvcndhcmRlZC1ob3N0LWhlYWRlci1hd3Mtc3BlY2lmaWNcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY0Nsb3VkRnJvbnRGdW5jdGlvbkFzc29jaWF0aW9ucygpOiBGdW5jdGlvbkFzc29jaWF0aW9uW10ge1xuICAgIGNvbnN0IGFzc29jaWF0aW9uczogRnVuY3Rpb25Bc3NvY2lhdGlvbltdID0gW107XG4gICAgaWYgKHRoaXMuaXNGdW5jdGlvbkNvbXB1dGUpIHtcbiAgICAgIGNvbnN0IGNsb3VkRnJvbnRGbiA9IG5ldyBDbG91ZEZyb250RnVuY3Rpb24odGhpcywgXCJDbG91ZEZyb250Rm5cIiwge1xuICAgICAgICBjb2RlOiBGdW5jdGlvbkNvZGUuZnJvbUlubGluZShgXG4gICAgICAgICAgZnVuY3Rpb24gaGFuZGxlcihldmVudCkge1xuICAgICAgICAgICAgdmFyIHJlcXVlc3QgPSBldmVudC5yZXF1ZXN0O1xuICAgICAgICAgICAgcmVxdWVzdC5oZWFkZXJzW1wieC1mb3J3YXJkZWQtaG9zdFwiXSA9IHJlcXVlc3QuaGVhZGVycy5ob3N0O1xuICAgICAgICAgICAgcmV0dXJuIHJlcXVlc3Q7XG4gICAgICAgICAgfVxuICAgICAgICAgIGApLFxuICAgICAgfSk7XG4gICAgICBhc3NvY2lhdGlvbnMucHVzaCh7XG4gICAgICAgIGV2ZW50VHlwZTogRnVuY3Rpb25FdmVudFR5cGUuVklFV0VSX1JFUVVFU1QsXG4gICAgICAgIGZ1bmN0aW9uOiBjbG91ZEZyb250Rm4sXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFzc29jaWF0aW9ucztcbiAgfVxuICBwcml2YXRlIGNyZWF0ZVN0YXRpY0JlaGF2aW9yT3B0aW9ucygpOiBCZWhhdmlvck9wdGlvbnMge1xuICAgIGNvbnN0IHN0YXRpY0JlaGF2aW9yT3B0aW9ucyA9IHRoaXMucHJvcHMub3ZlcnJpZGVzPy5zdGF0aWNCZWhhdmlvck9wdGlvbnM7XG4gICAgY29uc3QgcmVzcG9uc2VIZWFkZXJzUG9saWN5ID1cbiAgICAgIHN0YXRpY0JlaGF2aW9yT3B0aW9ucz8ucmVzcG9uc2VIZWFkZXJzUG9saWN5ID8/XG4gICAgICBuZXcgUmVzcG9uc2VIZWFkZXJzUG9saWN5KHRoaXMsIFwiU3RhdGljUmVzcG9uc2VIZWFkZXJzUG9saWN5XCIsIHtcbiAgICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHRoaXMuY29tbW9uU2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IsXG4gICAgICAgIGNvbW1lbnQ6IHRoaXMuZ2V0Q29tbWVudChcbiAgICAgICAgICBcIk5leHRKUyBTdGF0aWMgUmVzcG9uc2UgSGVhZGVycyBQb2xpY3lcIixcbiAgICAgICAgICBTdGFjay5vZih0aGlzKS5zdGFja05hbWUsXG4gICAgICAgICksXG4gICAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5zdGF0aWNSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcyxcbiAgICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBhbGxvd2VkTWV0aG9kczogQWxsb3dlZE1ldGhvZHMuQUxMT1dfR0VUX0hFQURfT1BUSU9OUyxcbiAgICAgIGNhY2hlZE1ldGhvZHM6IENhY2hlZE1ldGhvZHMuQ0FDSEVfR0VUX0hFQURfT1BUSU9OUyxcbiAgICAgIGNhY2hlUG9saWN5OiBDYWNoZVBvbGljeS5DQUNISU5HX09QVElNSVpFRCxcbiAgICAgIG9yaWdpbjogdGhpcy5zdGF0aWNPcmlnaW4sXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3ksXG4gICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAuLi5zdGF0aWNCZWhhdmlvck9wdGlvbnMsXG4gICAgfTtcbiAgfVxuICBwcml2YXRlIGNyZWF0ZUR5bmFtaWNCZWhhdmlvck9wdGlvbnMoKTogQmVoYXZpb3JPcHRpb25zIHtcbiAgICBjb25zdCBkeW5hbWljQmVoYXZpb3JPcHRpb25zID0gdGhpcy5wcm9wcy5vdmVycmlkZXM/LmR5bmFtaWNCZWhhdmlvck9wdGlvbnM7XG4gICAgLy8gY3JlYXRlIGRlZmF1bHQgY2FjaGUgcG9saWN5IGlmIG5vdCBwcm92aWRlZFxuICAgIGNvbnN0IGNhY2hlUG9saWN5ID1cbiAgICAgIGR5bmFtaWNCZWhhdmlvck9wdGlvbnM/LmNhY2hlUG9saWN5ID8/XG4gICAgICBuZXcgQ2FjaGVQb2xpY3kodGhpcywgXCJEeW5hbWljQ2FjaGVQb2xpY3lcIiwge1xuICAgICAgICBxdWVyeVN0cmluZ0JlaGF2aW9yOiBDYWNoZVF1ZXJ5U3RyaW5nQmVoYXZpb3IuYWxsKCksXG4gICAgICAgIGhlYWRlckJlaGF2aW9yOiBDYWNoZUhlYWRlckJlaGF2aW9yLmFsbG93TGlzdChcbiAgICAgICAgICAvLyBOT1RFOiBDbG91ZEZyb250IEN1c3RvbSBDYWNoZSBQb2xpY2llcyBoYXZlIHNvZnQgbWF4IG9mIDEwIGhlYWRlcnNcbiAgICAgICAgICAvLyBjZGstbmV4dGpzIGluY2x1ZGVzIHRoZSBtb3N0IGVzc2VudGlhbCBoZWFkZXJzIGZvciBOZXh0LmpzIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgICAvLyBidXQgaXQncyByZWNvbW1lbmRlZCB0byByZXF1ZXN0IHF1b3RhIGluY3JlYXNlIHRvIGluY2x1ZGUgYWxsIGhlYWRlcnMgKGNvbW1lbnRlZCBvdXQgb25lcyBiZWxvdylcbiAgICAgICAgICAvLyBtb3JlIGhlcmU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZEZyb250L2xhdGVzdC9EZXZlbG9wZXJHdWlkZS9jbG91ZGZyb250LWxpbWl0cy5odG1sI2xpbWl0cy1wb2xpY2llc1xuICAgICAgICAgIFwiYWNjZXB0XCIsIC8vIGNvbnRlbnQgbmVnb3RpYXRpb24gKEhUTUwgdnMgUlNDIHBheWxvYWQpXG4gICAgICAgICAgXCJyc2NcIiwgLy8gUmVhY3QgU2VydmVyIENvbXBvbmVudHMgcmVxdWVzdHNcbiAgICAgICAgICBcIm5leHQtdXJsXCIsIC8vIE5leHQuanMgcm91dGluZ1xuICAgICAgICAgIFwibmV4dC1yb3V0ZXItc3RhdGUtdHJlZVwiLCAvLyBBcHAgUm91dGVyIG5hdmlnYXRpb24gc3RhdGVcbiAgICAgICAgICBcIm5leHQtcm91dGVyLXByZWZldGNoXCIsIC8vIHByZWZldGNoIGJlaGF2aW9yXG4gICAgICAgICAgXCJuZXh0LXJvdXRlci1zZWdtZW50LXByZWZldGNoXCIsIC8vIHNlZ21lbnQtbGV2ZWwgcHJlZmV0Y2hpbmdcbiAgICAgICAgICBcIngtbWF0Y2hlZC1wYXRoXCIsIC8vIGR5bmFtaWMgcm91dGVzIGFuZCByZXdyaXRlc1xuICAgICAgICAgIFwieC1wcmVyZW5kZXItcmV2YWxpZGF0ZVwiLCAvLyBvbi1kZW1hbmQgSVNSIHJldmFsaWRhdGlvblxuICAgICAgICAgIFwieC1uZXh0LWNhY2hlLXRhZ3NcIiwgLy8gdGFnLWJhc2VkIGNhY2hlIHJldmFsaWRhdGlvblxuICAgICAgICAgIFwieC1wcmVyZW5kZXItYnlwYXNzXCIsIC8vIGRyYWZ0IG1vZGVcbiAgICAgICAgICAvLyBcIngtbmV4dGpzLXN0YWxlLXRpbWVcIiwgLy8gc3RhbGUtd2hpbGUtcmV2YWxpZGF0ZSBiZWhhdmlvclxuICAgICAgICAgIC8vIFwieC1uZXh0LWNhY2hlLXRhZy10b2tlblwiLCAvLyBhdXRoIHRva2VuIGZvciBjYWNoZSB0YWdzIChvbmx5IG5lZWRlZCB3aXRoIHJldmFsaWRhdGVUYWcgYXV0aClcbiAgICAgICAgICAvLyBcIngtbmV4dGpzLXBvc3Rwb25lZFwiLCAvLyBQYXJ0aWFsIFByZXJlbmRlcmluZyAoZXhwZXJpbWVudGFsIGZlYXR1cmUpXG4gICAgICAgICAgLy8gXCJ4LXByZXJlbmRlci1yZXZhbGlkYXRlLWlmLWdlbmVyYXRlZFwiLCAvLyBjb25kaXRpb25hbCByZXZhbGlkYXRpb24gKG5pY2hlIHVzZSBjYXNlKVxuICAgICAgICApLFxuICAgICAgICBjb29raWVCZWhhdmlvcjogQ2FjaGVDb29raWVCZWhhdmlvci5hbGwoKSxcbiAgICAgICAgZW5hYmxlQWNjZXB0RW5jb2RpbmdCcm90bGk6IHRydWUsXG4gICAgICAgIGVuYWJsZUFjY2VwdEVuY29kaW5nR3ppcDogdHJ1ZSxcbiAgICAgICAgY29tbWVudDogdGhpcy5nZXRDb21tZW50KFxuICAgICAgICAgIFwiTmV4dEpTIER5bmFtaWMgQ2FjaGUgUG9saWN5XCIsXG4gICAgICAgICAgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lLFxuICAgICAgICApLFxuICAgICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8uZHluYW1pY0NhY2hlUG9saWN5UHJvcHMsXG4gICAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZUhlYWRlcnNQb2xpY3kgPVxuICAgICAgZHluYW1pY0JlaGF2aW9yT3B0aW9ucz8ucmVzcG9uc2VIZWFkZXJzUG9saWN5ID8/XG4gICAgICBuZXcgUmVzcG9uc2VIZWFkZXJzUG9saWN5KHRoaXMsIFwiRHluYW1pY1Jlc3BvbnNlSGVhZGVyc1BvbGljeVwiLCB7XG4gICAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB0aGlzLmNvbW1vblNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yLFxuICAgICAgICBjb21tZW50OiB0aGlzLmdldENvbW1lbnQoXG4gICAgICAgICAgXCJOZXh0SlMgRHluYW1pYyBSZXNwb25zZSBIZWFkZXJzIFBvbGljeVwiLFxuICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmR5bmFtaWNSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcyxcbiAgICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBhbGxvd2VkTWV0aG9kczogQWxsb3dlZE1ldGhvZHMuQUxMT1dfQUxMLFxuICAgICAgY2FjaGVQb2xpY3ksXG4gICAgICBmdW5jdGlvbkFzc29jaWF0aW9uczogdGhpcy5keW5hbWljQ2xvdWRGcm9udEZ1bmN0aW9uQXNzb2NpYXRpb25zLFxuICAgICAgb3JpZ2luOiB0aGlzLmR5bmFtaWNPcmlnaW4sXG4gICAgICBvcmlnaW5SZXF1ZXN0UG9saWN5OiB0aGlzLmR5bmFtaWNPcmlnaW5SZXNwb25zZVBvbGljeSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeSxcbiAgICAgIHZpZXdlclByb3RvY29sUG9saWN5OiBWaWV3ZXJQcm90b2NvbFBvbGljeS5SRURJUkVDVF9UT19IVFRQUyxcbiAgICAgIC4uLmR5bmFtaWNCZWhhdmlvck9wdGlvbnMsXG4gICAgfTtcbiAgfVxuICBwcml2YXRlIGNyZWF0ZUltYWdlQmVoYXZpb3JPcHRpb25zKCk6IEJlaGF2aW9yT3B0aW9ucyB7XG4gICAgY29uc3QgaW1hZ2VCZWhhdmlvck9wdGlvbnMgPSB0aGlzLnByb3BzLm92ZXJyaWRlcz8uaW1hZ2VCZWhhdmlvck9wdGlvbnM7XG4gICAgLy8gYWRkIGRlZmF1bHQgY2FjaGUgcG9saWN5IGlmIG5vdCBwcm92aWRlZFxuICAgIGNvbnN0IGNhY2hlUG9saWN5ID1cbiAgICAgIGltYWdlQmVoYXZpb3JPcHRpb25zPy5jYWNoZVBvbGljeSA/P1xuICAgICAgbmV3IENhY2hlUG9saWN5KHRoaXMsIFwiSW1hZ2VDYWNoZVBvbGljeVwiLCB7XG4gICAgICAgIC8vIFNFQ1VSSVRZIE5PVEU6IGJ5IGRlZmF1bHQgd2UgZG9uJ3QgaW5jbHVkZSBjb29raWVzIGluIGNhY2hlIGZvclxuICAgICAgICAvLyBpbWFnZXMgYi9jIGl0IHNpZ25pZmljYW50bHkgaW1wcm92ZXMgaW1hZ2UgcGVyZiBmb3IgbW9zdCBzaXRlcyBCVVRcbiAgICAgICAgLy8gaWYgeW91IGhhdmUgcHJpdmF0ZSBpbWFnZXMgbG9ja2VkIGJlaGluZCBhdXRoIGltcGxlbWVudGVkIHdpdGggY29va2llc1xuICAgICAgICAvLyB5b3UgbmVlZCB0byBvdmVycmlkZSB0aGlzLlxuICAgICAgICBxdWVyeVN0cmluZ0JlaGF2aW9yOiBDYWNoZVF1ZXJ5U3RyaW5nQmVoYXZpb3IuYWxsKCksXG4gICAgICAgIGhlYWRlckJlaGF2aW9yOiBDYWNoZUhlYWRlckJlaGF2aW9yLmFsbG93TGlzdChcImFjY2VwdFwiKSxcbiAgICAgICAgY29va2llQmVoYXZpb3I6IENhY2hlQ29va2llQmVoYXZpb3Iubm9uZSgpLFxuICAgICAgICBlbmFibGVBY2NlcHRFbmNvZGluZ0Jyb3RsaTogdHJ1ZSxcbiAgICAgICAgZW5hYmxlQWNjZXB0RW5jb2RpbmdHemlwOiB0cnVlLFxuICAgICAgICBjb21tZW50OiB0aGlzLmdldENvbW1lbnQoXG4gICAgICAgICAgXCJOZXh0SlMgSW1hZ2UgQ2FjaGUgUG9saWN5XCIsXG4gICAgICAgICAgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lLFxuICAgICAgICApLFxuICAgICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8uaW1hZ2VDYWNoZVBvbGljeVByb3BzLFxuICAgICAgfSk7XG4gICAgLy8gYWRkIGRlZmF1bHQgcmVzcG9uc2UgaGVhZGVycyBwb2xpY3kgaWYgbm90IHByb3ZpZGVkXG4gICAgY29uc3QgcmVzcG9uc2VIZWFkZXJzUG9saWN5ID1cbiAgICAgIGltYWdlQmVoYXZpb3JPcHRpb25zPy5yZXNwb25zZUhlYWRlcnNQb2xpY3kgPz9cbiAgICAgIG5ldyBSZXNwb25zZUhlYWRlcnNQb2xpY3kodGhpcywgXCJJbWFnZVJlc3BvbnNlSGVhZGVyc1BvbGljeVwiLCB7XG4gICAgICAgIHNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiB0aGlzLmNvbW1vblNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yLFxuICAgICAgICBjb21tZW50OiB0aGlzLmdldENvbW1lbnQoXG4gICAgICAgICAgXCJOZXh0SlMgSW1hZ2UgUmVzcG9uc2UgSGVhZGVycyBQb2xpY3lcIixcbiAgICAgICAgICBTdGFjay5vZih0aGlzKS5zdGFja05hbWUsXG4gICAgICAgICksXG4gICAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5pbWFnZVJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzLFxuICAgICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFsbG93ZWRNZXRob2RzOiBBbGxvd2VkTWV0aG9kcy5BTExPV19HRVRfSEVBRF9PUFRJT05TLFxuICAgICAgY2FjaGVkTWV0aG9kczogQ2FjaGVkTWV0aG9kcy5DQUNIRV9HRVRfSEVBRF9PUFRJT05TLFxuICAgICAgZnVuY3Rpb25Bc3NvY2lhdGlvbnM6IHRoaXMuZHluYW1pY0Nsb3VkRnJvbnRGdW5jdGlvbkFzc29jaWF0aW9ucyxcbiAgICAgIG9yaWdpbjogdGhpcy5pbWFnZU9yaWdpbixcbiAgICAgIG9yaWdpblJlcXVlc3RQb2xpY3k6IHRoaXMuZHluYW1pY09yaWdpblJlc3BvbnNlUG9saWN5LFxuICAgICAgY2FjaGVQb2xpY3ksXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3ksXG4gICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAuLi5pbWFnZUJlaGF2aW9yT3B0aW9ucyxcbiAgICB9O1xuICB9XG4gIC8qKlxuICAgKiBDcmVhdGVzIG9yIHVzZXMgdXNlciBzcGVjaWZpZWQgQ2xvdWRGcm9udCBEaXN0cmlidXRpb25cbiAgICovXG4gIHByaXZhdGUgZ2V0RGlzdHJpYnV0aW9uKCk6IERpc3RyaWJ1dGlvbiB7XG4gICAgbGV0IGRpc3RyaWJ1dGlvbjogRGlzdHJpYnV0aW9uO1xuICAgIGlmICh0aGlzLnByb3BzLmRpc3RyaWJ1dGlvbikge1xuICAgICAgZGlzdHJpYnV0aW9uID0gdGhpcy5wcm9wcy5kaXN0cmlidXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpc3RyaWJ1dGlvbiA9IG5ldyBEaXN0cmlidXRpb24odGhpcywgXCJEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBtaW5pbXVtUHJvdG9jb2xWZXJzaW9uOiBTZWN1cml0eVBvbGljeVByb3RvY29sLlRMU19WMV8yXzIwMjEsXG4gICAgICAgIGRlZmF1bHRCZWhhdmlvcjogdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zLFxuICAgICAgICAvLyBiZXN0IHRvIHVzZSBIVFRQIDIgYW5kIDMgZm9yIGNvbXBhdGFiaWxpdHkgKEhUVFAgMikgYW5kIHBlcmZvcm1hbmNlIChIVFRQMylcbiAgICAgICAgLy8gQ2xvdWRGcm9udCB3aWxsIGNob29zZSBiZXN0IG9wdGlvbiBmb3IgY2xpZW50XG4gICAgICAgIGh0dHBWZXJzaW9uOiBIdHRwVmVyc2lvbi5IVFRQMl9BTkRfMyxcbiAgICAgICAgY29tbWVudDogdGhpcy5nZXRDb21tZW50KFxuICAgICAgICAgIFwiTmV4dEpTIERpc3RyaWJ1dGlvblwiLFxuICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmRpc3RyaWJ1dGlvblByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBkaXN0cmlidXRpb247XG4gIH1cbiAgcHJpdmF0ZSBhZGREeW5hbWljQmVoYXZpb3JzKCkge1xuICAgIC8vIEltYWdlIEJlaGF2aW9yXG4gICAgdGhpcy5kaXN0cmlidXRpb24uYWRkQmVoYXZpb3IoXG4gICAgICB0aGlzLmdldFBhdGhQYXR0ZXJuKFwiX25leHQvaW1hZ2UqXCIpLFxuICAgICAgdGhpcy5pbWFnZUJlaGF2aW9yT3B0aW9ucy5vcmlnaW4sXG4gICAgICB0aGlzLmltYWdlQmVoYXZpb3JPcHRpb25zLFxuICAgICk7XG4gICAgLy8gUm9vdCBQYXRoIEJlaGF2aW9yc1xuICAgIGlmICh0aGlzLmJhc2VQYXRoKSB7XG4gICAgICAvLyBiZWNhdXNlIHdlIGFscmVhZHkgaGF2ZSBhIGJhc2VQYXRoIHdlIGRvbid0IHVzZSAvIGluc3RlYWQgd2UgdXNlIC9iYXNlLXBhdGhcbiAgICAgIHRoaXMuZGlzdHJpYnV0aW9uLmFkZEJlaGF2aW9yKFxuICAgICAgICBgLyR7dGhpcy5iYXNlUGF0aH1gLFxuICAgICAgICB0aGlzLmR5bmFtaWNCZWhhdmlvck9wdGlvbnMub3JpZ2luLFxuICAgICAgICB0aGlzLmR5bmFtaWNCZWhhdmlvck9wdGlvbnMsXG4gICAgICApO1xuICAgICAgLy8gd2hlbiBiYXNlUGF0aCBpcyBzZXQsIHdlIGVtdWxhdGUgdGhlIFwiZGVmYXVsdCBiZWhhdmlvclwiICgqKSBmb3IgdGhlIHNpdGUgYXMgYC9iYXNlLXBhdGgvKmBcbiAgICAgIHRoaXMuZGlzdHJpYnV0aW9uLmFkZEJlaGF2aW9yKFxuICAgICAgICB0aGlzLmdldFBhdGhQYXR0ZXJuKFwiKlwiKSxcbiAgICAgICAgdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zLm9yaWdpbixcbiAgICAgICAgdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgbm8gYmFzZSBwYXRoLCB0aGVuIGRlZmF1bHQgYmVoYXZpb3Igd2lsbCBoYW5kbGUgYWxsIG90aGVyIHBhdGhzXG4gICAgfVxuICB9XG4gIHByaXZhdGUgYWRkU3RhdGljQmVoYXZpb3JzKCkge1xuICAgIHRoaXMuZGlzdHJpYnV0aW9uLmFkZEJlaGF2aW9yKFxuICAgICAgdGhpcy5nZXRQYXRoUGF0dGVybihcIl9uZXh0L3N0YXRpYypcIiksXG4gICAgICB0aGlzLnN0YXRpY09yaWdpbixcbiAgICAgIHRoaXMuc3RhdGljQmVoYXZpb3JPcHRpb25zLFxuICAgICk7XG4gICAgLy8gMjIgPSAyNSAobWF4KSAtIDEgKF9uZXh0L2ltYWdlKSAtIDEgKF9uZXh0L3N0YXRpYykgLSAxICgqKVxuICAgIGlmICh0aGlzLnByb3BzLnB1YmxpY0RpckVudHJpZXMubGVuZ3RoID49IDIyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUb28gbWFueSBwdWJsaWMvIGZpbGVzIGluIE5leHQuanMgYnVpbGQuIENsb3VkRnJvbnQgbGltaXRzIERpc3RyaWJ1dGlvbnMgdG8gMjUgQ2FjaGUgQmVoYXZpb3JzLiBTZWUgZG9jdW1lbnRlZCBsaW1pdCBoZXJlOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvY2xvdWRmcm9udC1saW1pdHMuaHRtbCNsaW1pdHMtd2ViLWRpc3RyaWJ1dGlvbnMuIFRyeSBpbmNsdWRpbmcgYWxsIHB1YmxpYyBmaWxlcyBpbnRvIDEgdG9wIGxldmVsIGRpcmVjdG9yeSAoaS5lLiBzdGF0aWMvKikuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgcHVibGljRmlsZSBvZiB0aGlzLnByb3BzLnB1YmxpY0RpckVudHJpZXMpIHtcbiAgICAgIGNvbnN0IHBhdGhQYXR0ZXJuID0gcHVibGljRmlsZS5pc0RpcmVjdG9yeVxuICAgICAgICA/IGAke3B1YmxpY0ZpbGUubmFtZX0vKmBcbiAgICAgICAgOiBwdWJsaWNGaWxlLm5hbWU7XG4gICAgICBpZiAoIS9eW2EtekEtWjAtOV9cXC0uKiQvflwiJ0A6Kz8mXSskLy50ZXN0KHBhdGhQYXR0ZXJuKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEludmFsaWQgQ2xvdWRGcm9udCBEaXN0cmlidXRpb24gQ2FjaGUgQmVoYXZpb3IgUGF0aCBQYXR0ZXJuOiAke3BhdGhQYXR0ZXJufS4gUGxlYXNlIHNlZSBkb2N1bWVudGF0aW9uIGhlcmU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZEZyb250L2xhdGVzdC9EZXZlbG9wZXJHdWlkZS9kaXN0cmlidXRpb24td2ViLXZhbHVlcy1zcGVjaWZ5Lmh0bWwjRG93bmxvYWREaXN0VmFsdWVzUGF0aFBhdHRlcm5gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3QgZmluYWxQYXRoUGF0dGVybiA9IHRoaXMuZ2V0UGF0aFBhdHRlcm4ocGF0aFBhdHRlcm4pO1xuICAgICAgdGhpcy5kaXN0cmlidXRpb24uYWRkQmVoYXZpb3IoXG4gICAgICAgIGZpbmFsUGF0aFBhdHRlcm4sXG4gICAgICAgIHRoaXMuc3RhdGljT3JpZ2luLFxuICAgICAgICB0aGlzLnN0YXRpY0JlaGF2aW9yT3B0aW9ucyxcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBPcHRpb25hbGx5IHByZXBlbmRzIGJhc2UgcGF0aCB0byBnaXZlbiBwYXRoIHBhdHRlcm4uXG4gICAqL1xuICBwcml2YXRlIGdldFBhdGhQYXR0ZXJuKHBhdGhQYXR0ZXJuOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5iYXNlUGF0aFxuICAgICAgPyBgLyR7am9pblBhdGgodGhpcy5iYXNlUGF0aCwgcGF0aFBhdHRlcm4pfWBcbiAgICAgIDogcGF0aFBhdHRlcm47XG4gIH1cbn1cbiJdfQ==
692
+ /**
693
+ * Whether `dynamicCachePolicyProps` turns the dynamic cache off, by capping every
694
+ * TTL at 0.
695
+ *
696
+ * CloudFront rejects a policy that caches nothing but still has a cache key
697
+ * ("HeaderBehavior is invalid for policy with caching disabled"), so such a
698
+ * policy has to drop the key. Until the default TTL became 0 this could not
699
+ * come up: CDK raises `maxTtl` to `defaultTtl` when it is lower, so an override
700
+ * of `maxTtl: 0` synthesized as a day and deployed. Now it is honored, and
701
+ * without this the upgrade deploy would fail.
702
+ *
703
+ * The TTLs are resolved the way CDK resolves them: `defaultTtl` raised to
704
+ * `minTtl`, then `maxTtl` raised to `defaultTtl`. Checking `maxTtl` alone called
705
+ * `{ maxTtl: 0, defaultTtl: 1h }` disabled, dropped the key, and CDK then
706
+ * synthesized a policy that caches for an hour keyed on nothing — one viewer's
707
+ * page served to every viewer.
708
+ */
709
+ function isCachingDisabled(props) {
710
+ const ttls = [props?.maxTtl, props?.defaultTtl, props?.minTtl];
711
+ if (props?.maxTtl === undefined)
712
+ return false; // CDK's default is a year
713
+ return ttls.every((ttl) => ttl === undefined ||
714
+ (!aws_cdk_lib_1.Token.isUnresolved(ttl.toString()) && ttl.toSeconds() === 0));
715
+ }
716
+ /**
717
+ * What the dynamic cache policy keys on: every request input a Next.js response
718
+ * varies by.
719
+ */
720
+ const DYNAMIC_CACHE_KEY = {
721
+ queryStringBehavior: aws_cloudfront_1.CacheQueryStringBehavior.all(),
722
+ headerBehavior: aws_cloudfront_1.CacheHeaderBehavior.allowList(
723
+ // NOTE: CloudFront Custom Cache Policies have soft max of 10 headers
724
+ // cdk-nextjs includes the most essential headers for Next.js functionality
725
+ // but it's recommended to request quota increase to include all headers (commented out ones below)
726
+ // more here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-policies
727
+ "accept", // content negotiation (HTML vs RSC payload)
728
+ "rsc", // React Server Components requests
729
+ "next-url", // Next.js routing
730
+ "next-router-state-tree", // App Router navigation state
731
+ "next-router-prefetch", // prefetch behavior
732
+ "next-router-segment-prefetch", // segment-level prefetching
733
+ "x-prerender-revalidate", // on-demand ISR revalidation
734
+ "x-prerender-bypass"),
735
+ cookieBehavior: aws_cloudfront_1.CacheCookieBehavior.all(),
736
+ enableAcceptEncodingBrotli: true,
737
+ enableAcceptEncodingGzip: true,
738
+ };
739
+ /**
740
+ * A cache key of nothing, for a policy that caches nothing. Forwarding is
741
+ * unaffected: the dynamic origin request policy sends every viewer header,
742
+ * cookie and query string regardless.
743
+ */
744
+ const DISABLED_CACHE_KEY = {
745
+ queryStringBehavior: aws_cloudfront_1.CacheQueryStringBehavior.none(),
746
+ headerBehavior: aws_cloudfront_1.CacheHeaderBehavior.none(),
747
+ cookieBehavior: aws_cloudfront_1.CacheCookieBehavior.none(),
748
+ enableAcceptEncodingBrotli: false,
749
+ enableAcceptEncodingGzip: false,
750
+ };
751
+ /**
752
+ * CloudFront's default "Cache behaviors per distribution" quota, the default
753
+ * behavior included. Adjustable, hence `maxCacheBehaviors`.
754
+ *
755
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions
756
+ */
757
+ const DEFAULT_MAX_CACHE_BEHAVIORS = 75;
758
+ /**
759
+ * Whether `char` is in CloudFront's path pattern alphabet: the literals, plus the
760
+ * `*` and `?` wildcards. No space, no `%`, nothing non-ASCII.
761
+ */
762
+ function isPathPatternChar(char) {
763
+ return char === "*" || char === "?" || function_groups_1.PATH_PATTERN_LITERAL.test(char);
764
+ }
765
+ /** CloudFront's path pattern length limit. */
766
+ const MAX_PATH_PATTERN_LENGTH = 255;
767
+ /**
768
+ * A `public/` entry's name as a CloudFront path pattern.
769
+ *
770
+ * `public/hello world.jpg` is a valid Next.js asset — `next start` serves it, and
771
+ * `next/image` points at it — but a space cannot appear in a path pattern, so
772
+ * cdk-nextjs used to throw at synth and the app could not be deployed at all
773
+ * (`next-image-legacy/unicode`, whose `public/` also holds `äöüščří.png`).
774
+ *
775
+ * CloudFront URL-decodes the request path before matching it, so the pattern is
776
+ * matched against `hello world.jpg`, not the `/hello%20world.jpg` on the wire.
777
+ * Each character outside the alphabet is replaced by one `?` per byte of its
778
+ * UTF-8 encoding, because that is what `?` matches: `hello?world.jpg` for the
779
+ * space, and two `?` for each character of `äöüščří.png`. Measured against a
780
+ * deployed distribution; a `?` per *percent-encoded* character (`hello???world`)
781
+ * synthesizes fine and never matches. A `*` would be shorter and much wider:
782
+ * `äöüščří.png` would become `*.png`, which would pull every `.png` request in
783
+ * the app onto the static origin.
784
+ */
785
+ function toPathPattern(name) {
786
+ return [...name]
787
+ .map((char) => isPathPatternChar(char)
788
+ ? char
789
+ : "?".repeat(Buffer.byteLength(char, "utf8")))
790
+ .join("");
791
+ }
792
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWRpc3RyaWJ1dGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9uZXh0anMtZGlzdHJpYnV0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSw2Q0FBa0U7QUFFbEUsK0RBNEJvQztBQUNwQywrRUFNNEM7QUFFNUMsdURBQXFFO0FBRXJFLDJDQUF1QztBQUN2QywrREFJbUM7QUFDbkMsMkNBQXFEO0FBT3JELGlEQUF1RTtBQXdHdkUsTUFBYSxrQkFBbUIsU0FBUSxzQkFBUzs7SUFDL0MsWUFBWSxDQUFlO0lBRW5CLEtBQUssQ0FBMEI7SUFDdkM7Ozs7O09BS0c7SUFDSyxRQUFRLENBQVM7SUFDekI7Ozs7O09BS0c7SUFDSyxXQUFXLENBQVM7SUFDNUI7OztPQUdHO0lBQ0ssNkJBQTZCLEdBQW9DO1FBQ3ZFLGtCQUFrQixFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtRQUN2QyxZQUFZLEVBQUU7WUFDWixXQUFXLEVBQUUsbUNBQWtCLENBQUMsVUFBVTtZQUMxQyxRQUFRLEVBQUUsS0FBSztTQUNoQjtRQUNELGNBQWMsRUFBRTtZQUNkLFFBQVEsRUFBRSxLQUFLO1lBQ2YsY0FBYyxFQUFFLHNDQUFxQixDQUFDLCtCQUErQjtTQUN0RTtRQUVELHVCQUF1QixFQUFFO1lBQ3ZCLG1CQUFtQixFQUFFLHNCQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUN2QyxpQkFBaUIsRUFBRSxJQUFJO1lBQ3ZCLFFBQVEsRUFBRSxLQUFLO1lBQ2YsT0FBTyxFQUFFLElBQUk7U0FDZDtRQUNELGFBQWEsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFO0tBQ3RFLENBQUM7SUFDTSxZQUFZLENBQVU7SUFDdEIsYUFBYSxDQUFVO0lBQ3ZCLDJCQUEyQixDQUF1QjtJQUNsRCxxQ0FBcUMsQ0FBd0I7SUFDN0QsaUJBQWlCLENBQVU7SUFD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b0NBQW1CLENBQUMsSUFBSSxFQUFFO0lBQzFDLGNBQWMsRUFBRSxvQ0FBbUIsQ0FBQyxJQUFJLEVBQUU7SUFDMUMsMEJBQTBCLEVBQUUsS0FBSztJQUNqQyx3QkFBd0IsRUFBRSxLQUFLO0NBQ2hDLENBQUM7QUFFRjs7Ozs7R0FLRztBQUNILE1BQU0sMkJBQTJCLEdBQUcsRUFBRSxDQUFDO0FBRXZDOzs7R0FHRztBQUNILFNBQVMsaUJBQWlCLENBQUMsSUFBWTtJQUNyQyxPQUFPLElBQUksS0FBSyxHQUFHLElBQUksSUFBSSxLQUFLLEdBQUcsSUFBSSxzQ0FBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDekUsQ0FBQztBQUNELDhDQUE4QztBQUM5QyxNQUFNLHVCQUF1QixHQUFHLEdBQUcsQ0FBQztBQUVwQzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxTQUFTLGFBQWEsQ0FBQyxJQUFZO0lBQ2pDLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQztTQUNiLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQ1osaUJBQWlCLENBQUMsSUFBSSxDQUFDO1FBQ3JCLENBQUMsQ0FBQyxJQUFJO1FBQ04sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FDaEQ7U0FDQSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQW5ub3RhdGlvbnMsIER1cmF0aW9uLCBTdGFjaywgVG9rZW4gfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IElDZXJ0aWZpY2F0ZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyXCI7XG5pbXBvcnQge1xuICBBY2Nlc3NMZXZlbCxcbiAgQWRkQmVoYXZpb3JPcHRpb25zLFxuICBBbGxvd2VkTWV0aG9kcyxcbiAgQmVoYXZpb3JPcHRpb25zLFxuICBDYWNoZUNvb2tpZUJlaGF2aW9yLFxuICBDYWNoZUhlYWRlckJlaGF2aW9yLFxuICBDYWNoZVBvbGljeSxcbiAgQ2FjaGVQb2xpY3lQcm9wcyxcbiAgQ2FjaGVRdWVyeVN0cmluZ0JlaGF2aW9yLFxuICBDYWNoZWRNZXRob2RzLFxuICBGdW5jdGlvbiBhcyBDbG91ZEZyb250RnVuY3Rpb24sXG4gIERpc3RyaWJ1dGlvbixcbiAgRnVuY3Rpb25Bc3NvY2lhdGlvbixcbiAgRnVuY3Rpb25Db2RlLFxuICBGdW5jdGlvbkV2ZW50VHlwZSxcbiAgSGVhZGVyc0ZyYW1lT3B0aW9uLFxuICBIZWFkZXJzUmVmZXJyZXJQb2xpY3ksXG4gIEh0dHBWZXJzaW9uLFxuICBJT3JpZ2luLFxuICBJT3JpZ2luUmVxdWVzdFBvbGljeSxcbiAgT3JpZ2luUHJvdG9jb2xQb2xpY3ksXG4gIE9yaWdpblJlcXVlc3RQb2xpY3ksXG4gIFJlc3BvbnNlSGVhZGVyc1BvbGljeSxcbiAgUmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHMsXG4gIFJlc3BvbnNlU2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IsXG4gIFNlY3VyaXR5UG9saWN5UHJvdG9jb2wsXG4gIFZpZXdlclByb3RvY29sUG9saWN5LFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnRcIjtcbmltcG9ydCB7XG4gIEZ1bmN0aW9uVXJsT3JpZ2luLFxuICBGdW5jdGlvblVybE9yaWdpbldpdGhPQUNQcm9wcyxcbiAgUzNCdWNrZXRPcmlnaW4sXG4gIFZwY09yaWdpbixcbiAgVnBjT3JpZ2luV2l0aEVuZHBvaW50UHJvcHMsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWRmcm9udC1vcmlnaW5zXCI7XG5pbXBvcnQgeyBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVsYXN0aWNsb2FkYmFsYW5jaW5ndjJcIjtcbmltcG9ydCB7IENmblBlcm1pc3Npb24sIElGdW5jdGlvblVybCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBJQnVja2V0IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7XG4gIGNsb3VkRnJvbnRQYXR0ZXJuUmVnZXgsXG4gIERFRkFVTFRfRlVOQ1RJT05fR1JPVVAsXG4gIFBBVEhfUEFUVEVSTl9MSVRFUkFMLFxufSBmcm9tIFwiLi9hZGFwdGVyL2Z1bmN0aW9uLWdyb3Vwc1wiO1xuaW1wb3J0IHsgTE9HX1BSRUZJWCwgTmV4dGpzVHlwZSB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT3B0aW9uYWxEaXN0cmlidXRpb25Qcm9wcyB9IGZyb20gXCIuL2dlbmVyYXRlZC1zdHJ1Y3RzL09wdGlvbmFsRGlzdHJpYnV0aW9uUHJvcHNcIjtcbmltcG9ydCB7IE9wdGlvbmFsUzNPcmlnaW5CdWNrZXRXaXRoT0FDUHJvcHMgfSBmcm9tIFwiLi9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbFMzT3JpZ2luQnVja2V0V2l0aE9BQ1Byb3BzXCI7XG5pbXBvcnQge1xuICBOZXh0anNGdW5jdGlvbkdyb3VwQmVoYXZpb3IsXG4gIFB1YmxpY0RpckVudHJ5LFxufSBmcm9tIFwiLi9uZXh0anMtYnVpbGQvbmV4dGpzLWJ1aWxkXCI7XG5pbXBvcnQgeyBhc3NldFByZWZpeFBhdGgsIG5vcm1hbGl6ZUJhc2VQYXRoIH0gZnJvbSBcIi4vdXRpbHMvYmFzZS1wYXRoXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzRGlzdHJpYnV0aW9uT3ZlcnJpZGVzIHtcbiAgcmVhZG9ubHkgZGlzdHJpYnV0aW9uUHJvcHM/OiBPcHRpb25hbERpc3RyaWJ1dGlvblByb3BzO1xuICByZWFkb25seSBpbWFnZUJlaGF2aW9yT3B0aW9ucz86IEFkZEJlaGF2aW9yT3B0aW9ucztcbiAgcmVhZG9ubHkgaW1hZ2VDYWNoZVBvbGljeVByb3BzPzogQ2FjaGVQb2xpY3lQcm9wcztcbiAgcmVhZG9ubHkgaW1hZ2VSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcz86IFJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzO1xuICByZWFkb25seSBkeW5hbWljQmVoYXZpb3JPcHRpb25zPzogQWRkQmVoYXZpb3JPcHRpb25zO1xuICByZWFkb25seSBkeW5hbWljQ2FjaGVQb2xpY3lQcm9wcz86IENhY2hlUG9saWN5UHJvcHM7XG4gIHJlYWRvbmx5IGR5bmFtaWNSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcz86IFJlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzO1xuICByZWFkb25seSBkeW5hbWljRnVuY3Rpb25VcmxPcmlnaW5XaXRoT0FDUHJvcHM/OiBGdW5jdGlvblVybE9yaWdpbldpdGhPQUNQcm9wcztcbiAgcmVhZG9ubHkgZHluYW1pY1ZwY09yaWdpbldpdGhFbmRwb2ludFByb3BzPzogVnBjT3JpZ2luV2l0aEVuZHBvaW50UHJvcHM7XG4gIHJlYWRvbmx5IHN0YXRpY0JlaGF2aW9yT3B0aW9ucz86IEFkZEJlaGF2aW9yT3B0aW9ucztcbiAgcmVhZG9ubHkgc3RhdGljUmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHM/OiBSZXNwb25zZUhlYWRlcnNQb2xpY3lQcm9wcztcbiAgcmVhZG9ubHkgczNCdWNrZXRPcmlnaW5Qcm9wcz86IE9wdGlvbmFsUzNPcmlnaW5CdWNrZXRXaXRoT0FDUHJvcHM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzRGlzdHJpYnV0aW9uUHJvcHMge1xuICAvKipcbiAgICogQnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0cy5cbiAgICogTXVzdCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0byBzZXJ2ZSBzdGF0aWMgZmlsZXMuXG4gICAqL1xuICByZWFkb25seSBhc3NldHNCdWNrZXQ6IElCdWNrZXQ7XG4gIC8qKlxuICAgKiBUaGUgYXBwJ3Mgb3duIGBhc3NldFByZWZpeGAuIE5leHQuanMgZW1pdHMgYDxhc3NldFByZWZpeD4vX25leHQvc3RhdGljLy4uLmBcbiAgICogZm9yIGV2ZXJ5IGJ1bmRsZSB3aGlsZSB0aGUgb2JqZWN0cyBzdGF5IGF0IGA8YmFzZVBhdGg+L19uZXh0L3N0YXRpYy8uLi5gIGluXG4gICAqIFMzLCBzbyB0aGUgcHJlZml4J3MgcGF0aCBnZXRzIGEgY2FjaGUgYmVoYXZpb3Igb2YgaXRzIG93biB0aGF0IHJld3JpdGVzIGl0XG4gICAqIGF3YXkuXG4gICAqXG4gICAqIEVpdGhlciBmb3JtIGlzIGFjY2VwdGVkOiBhIHBhdGggKFwiL2NkblwiKSwgb3IgYW4gYWJzb2x1dGUgVVJMLCBpbiB3aGljaCBjYXNlXG4gICAqIG9ubHkgaXRzIHBhdGggY291bnRzIChcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tL2NkblwiIGJlaGF2ZXMgYXMgXCIvY2RuXCIsIGFuZFxuICAgKiBcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tXCIgbmVlZHMgbm8gYmVoYXZpb3IgYXQgYWxsKS4gQW4gYWJzb2x1dGUgcHJlZml4J3MgcGF0aFxuICAgKiBtYXR0ZXJzIGJlY2F1c2UgYG5leHQgYnVpbGRgIGNvbXBpbGVzIGEgYC9jZG4vX25leHQvOnBhdGgrYCByZXdyaXRlIG9mIGl0c1xuICAgKiBvd24sIHNvIGBuZXh0IHN0YXJ0YCBzZXJ2ZXMgZXZlcnkgYnVuZGxlIHVuZGVyIGl0IOKAlCBhIENETiBmcm9udGluZyB0aGlzXG4gICAqIGRpc3RyaWJ1dGlvbiB0aGVyZSBoYXMgdG8gYmUgYW5zd2VyZWQgdG9vLlxuICAgKlxuICAgKiBBcHBsaWVkIG9uIHRvcCBvZiBgYmFzZVBhdGhgLCBub3QgdW5kZXIgaXQsIGJlY2F1c2UgdGhhdCBpcyBob3cgTmV4dC5qc1xuICAgKiBidWlsZHMgdGhlIFVSTC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lOyBwYXNzIGBOZXh0anNCdWlsZC5uZXh0Q29uZmlnQXNzZXRQcmVmaXhQYXRoYFxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRQcmVmaXg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBVUkkgcGF0aCBwcmVmaXggdGhlIGFwcCBpcyBzZXJ2ZWQgYXQuIFN1cnJvdW5kaW5nIHNsYXNoZXMgYXJlIG5vcm1hbGl6ZWRcbiAgICogYXdheSwgc28gXCIvYmFzZVwiLCBcImJhc2VcIiBhbmQgXCIvYmFzZS9cIiBhbGwgcHJvZHVjZSB0aGUgc2FtZSBjYWNoZSBiZWhhdmlvcnMuXG4gICAqL1xuICByZWFkb25seSBiYXNlUGF0aD86IHN0cmluZztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGJ1dCBvbmx5IGFwcGxpY2FibGUgZm9yIGBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTYFxuICAgKi9cbiAgcmVhZG9ubHkgY2VydGlmaWNhdGU/OiBJQ2VydGlmaWNhdGU7XG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbj86IERpc3RyaWJ1dGlvbjtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlNgXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvblVybD86IElGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTYCBvciBgTmV4dGpzVHlwZS5SRUdJT05BTF9DT05UQUlORVJTYFxuICAgKi9cbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyPzogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyO1xuICByZWFkb25seSBuZXh0anNUeXBlOiBOZXh0anNUeXBlO1xuICAvKipcbiAgICogT3ZlcnJpZGUgcHJvcHMgZm9yIGV2ZXJ5IGNvbnN0cnVjdC5cbiAgICovXG4gIHJlYWRvbmx5IG92ZXJyaWRlcz86IE5leHRqc0Rpc3RyaWJ1dGlvbk92ZXJyaWRlcztcbiAgLyoqXG4gICAqIEVudHJpZXMgKGZpbGVzL2RpcmVjdG9yaWVzKSB3aXRoaW4gTmV4dC5qcyBhcHAncyBwdWJsaWMgZGlyZWN0b3J5LiBVc2VkIHRvXG4gICAqIGFkZCBzdGF0aWMgYmVoYXZpb3JzIHRvIGRpc3RyaWJ1dGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHB1YmxpY0RpckVudHJpZXM6IFB1YmxpY0RpckVudHJ5W107XG4gIC8qKlxuICAgKiBUaGUgbm9uLWBkZWZhdWx0YCBmdW5jdGlvbiBncm91cHMsIHRoZSBvcmlnaW5zXG4gICAqIHtAbGluayBmdW5jdGlvbkdyb3VwQmVoYXZpb3JzfSByb3V0ZSB0by5cbiAgICogQGRlZmF1bHQgLSBubyBzcGxpdHRpbmc7IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHNlcnZlcyBldmVyeSBkeW5hbWljIHJvdXRlXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbkdyb3Vwcz86IE5leHRqc0Rpc3RyaWJ1dGlvbkZ1bmN0aW9uR3JvdXBbXTtcbiAgLyoqXG4gICAqIGBOZXh0anNCdWlsZC5mdW5jdGlvbkdyb3VwQmVoYXZpb3JzYDogb25lIGNhY2hlIGJlaGF2aW9yIGVhY2gsIGFkZGVkIGluXG4gICAqIG9yZGVyLCBzbyB0aGUgcm91dGVzIGVhY2ggZ3JvdXAgd2FzIHBhY2thZ2VkIHdpdGggcmVhY2ggaXQgcmF0aGVyIHRoYW4gdGhlXG4gICAqIGRlZmF1bHQgZnVuY3Rpb24uXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Hcm91cEJlaGF2aW9ycz86IE5leHRqc0Z1bmN0aW9uR3JvdXBCZWhhdmlvcltdO1xuICAvKipcbiAgICogVGhlIG1vc3QgY2FjaGUgYmVoYXZpb3JzIHRoZSBkaXN0cmlidXRpb24gbWF5IGhhdmUsIHRoZSBkZWZhdWx0IG9uZVxuICAgKiBpbmNsdWRlZC4gY2RrLW5leHRqcyBjb3VudHMgd2hhdCBpdCBhZGRzIGFnYWluc3QgdGhpcyBhdCBzeW50aCwgc28gcnVubmluZ1xuICAgKiBvdXQgaXMgYSBzeW50aCBlcnJvciBuYW1pbmcgd2hhdCB1c2VkIHRoZW0gcmF0aGVyIHRoYW4gYSBmYWlsZWQgZGVwbG95LlxuICAgKlxuICAgKiBSYWlzZSBpdCBhZnRlciByYWlzaW5nIHRoZSBcIkNhY2hlIGJlaGF2aW9ycyBwZXIgZGlzdHJpYnV0aW9uXCIgcXVvdGEgZm9yXG4gICAqIHlvdXIgYWNjb3VudC4gTG93ZXIgaXQgYnkgdGhlIGJlaGF2aW9ycyBhIHN1cHBsaWVkIHtAbGluayBkaXN0cmlidXRpb259XG4gICAqIChvciBgb3ZlcnJpZGVzLmRpc3RyaWJ1dGlvblByb3BzYCkgYWxyZWFkeSBoYXMsIHdoaWNoIGFyZSBub3QgY291bnRlZC5cbiAgICogQGRlZmF1bHQgNzUgLSBDbG91ZEZyb250J3MgZGVmYXVsdCBxdW90YVxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZEZyb250L2xhdGVzdC9EZXZlbG9wZXJHdWlkZS9jbG91ZGZyb250LWxpbWl0cy5odG1sI2xpbWl0cy13ZWItZGlzdHJpYnV0aW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgbWF4Q2FjaGVCZWhhdmlvcnM/OiBudW1iZXI7XG59XG5cbi8qKiBBIG5vbi1kZWZhdWx0IGZ1bmN0aW9uIGdyb3VwIGFuZCB0aGUgb3JpZ2luIGl0cyByb3V0ZXMgbXVzdCByZWFjaC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTmV4dGpzRGlzdHJpYnV0aW9uRnVuY3Rpb25Hcm91cCB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgLyoqIFRoZSBncm91cCdzIExhbWJkYSBGdW5jdGlvbiBVUkwuICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uVXJsOiBJRnVuY3Rpb25Vcmw7XG59XG5cbmV4cG9ydCBjbGFzcyBOZXh0anNEaXN0cmlidXRpb24gZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBkaXN0cmlidXRpb246IERpc3RyaWJ1dGlvbjtcblxuICBwcml2YXRlIHByb3BzOiBOZXh0anNEaXN0cmlidXRpb25Qcm9wcztcbiAgLyoqXG4gICAqIGBwcm9wcy5iYXNlUGF0aGAgbm9ybWFsaXplZCB0byBhIGJhcmUgcGF0aCBzZWdtZW50LiBUaGlzIGNvbnN0cnVjdCBpcyB0aGVcbiAgICogb25lIHBsYWNlIHRoYXQgbmVlZHMgaXQgd2l0aCBhIGxlYWRpbmcgc2xhc2gg4oCUIENsb3VkRnJvbnQgcGF0aCBwYXR0ZXJucyBhcmVcbiAgICogd3JpdHRlbiBhZ2FpbnN0IHRoZSByZXF1ZXN0IHBhdGgg4oCUIHNvIGl0IHByZXBlbmRzIGl0cyBvd24gcmF0aGVyIHRoYW5cbiAgICogcmVseWluZyBvbiB0aGUgY2FsbGVyIGhhdmluZyBwYXNzZWQgb25lLlxuICAgKi9cbiAgcHJpdmF0ZSBiYXNlUGF0aDogc3RyaW5nO1xuICAvKipcbiAgICogYHByb3BzLmFzc2V0UHJlZml4YCBub3JtYWxpemVkIHRvIGEgbGVhZGluZy1zbGFzaCBwYXRoLCBgXCJcImAgd2hlbiB0aGUgYXBwXG4gICAqIHNldHMgbm9uZSBvciBzZXRzIG9uZSB0aGF0IGFscmVhZHkgZXF1YWxzIHRoZSBgYmFzZVBhdGhgIHByZWZpeCDigJQgaW4gd2hpY2hcbiAgICogY2FzZSB0aGUgb3JkaW5hcnkgYF9uZXh0L3N0YXRpYypgIGJlaGF2aW9yIGFscmVhZHkgY292ZXJzIGl0IGFuZCBhIHNlY29uZCBvbmVcbiAgICogd291bGQgYmUgYSBkdXBsaWNhdGUgcGF0dGVybiBDbG91ZEZyb250IHJlamVjdHMuXG4gICAqL1xuICBwcml2YXRlIGFzc2V0UHJlZml4OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBDb21tb24gc2VjdXJpdHkgaGVhZGVycyBhcHBsaWVkIGJ5IGRlZmF1bHQgdG8gYWxsIG9yaWdpbnNcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvdXNpbmctbWFuYWdlZC1yZXNwb25zZS1oZWFkZXJzLXBvbGljaWVzLmh0bWwjbWFuYWdlZC1yZXNwb25zZS1oZWFkZXJzLXBvbGljaWVzLXNlY3VyaXR5XG4gICAqL1xuICBwcml2YXRlIGNvbW1vblNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yOiBSZXNwb25zZVNlY3VyaXR5SGVhZGVyc0JlaGF2aW9yID0ge1xuICAgIGNvbnRlbnRUeXBlT3B0aW9uczogeyBvdmVycmlkZTogZmFsc2UgfSxcbiAgICBmcmFtZU9wdGlvbnM6IHtcbiAgICAgIGZyYW1lT3B0aW9uOiBIZWFkZXJzRnJhbWVPcHRpb24uU0FNRU9SSUdJTixcbiAgICAgIG92ZXJyaWRlOiBmYWxzZSxcbiAgICB9LFxuICAgIHJlZmVycmVyUG9saWN5OiB7XG4gICAgICBvdmVycmlkZTogZmFsc2UsXG4gICAgICByZWZlcnJlclBvbGljeTogSGVhZGVyc1JlZmVycmVyUG9saWN5LlNUUklDVF9PUklHSU5fV0hFTl9DUk9TU19PUklHSU4sXG4gICAgfSxcblxuICAgIHN0cmljdFRyYW5zcG9ydFNlY3VyaXR5OiB7XG4gICAgICBhY2Nlc3NDb250cm9sTWF4QWdlOiBEdXJhdGlvbi5kYXlzKDM2NSksXG4gICAgICBpbmNsdWRlU3ViZG9tYWluczogdHJ1ZSxcbiAgICAgIG92ZXJyaWRlOiBmYWxzZSxcbiAgICAgIHByZWxvYWQ6IHRydWUsXG4gICAgfSxcbiAgICB4c3NQcm90ZWN0aW9uOiB7IG92ZXJyaWRlOiBmYWxzZSwgcHJvdGVjdGlvbjogdHJ1ZSwgbW9kZUJsb2NrOiB0cnVlIH0sXG4gIH07XG4gIHByaXZhdGUgc3RhdGljT3JpZ2luOiBJT3JpZ2luO1xuICBwcml2YXRlIGR5bmFtaWNPcmlnaW46IElPcmlnaW47XG4gIHByaXZhdGUgZHluYW1pY09yaWdpblJlc3BvbnNlUG9saWN5OiBJT3JpZ2luUmVxdWVzdFBvbGljeTtcbiAgcHJpdmF0ZSBkeW5hbWljQ2xvdWRGcm9udEZ1bmN0aW9uQXNzb2NpYXRpb25zOiBGdW5jdGlvbkFzc29jaWF0aW9uW107XG4gIHByaXZhdGUgaXNGdW5jdGlvbkNvbXB1dGU6IGJvb2xlYW47XG4gIHByaXZhdGUgc3RhdGljQmVoYXZpb3JPcHRpb25zOiBCZWhhdmlvck9wdGlvbnM7XG4gIHByaXZhdGUgZHluYW1pY0JlaGF2aW9yT3B0aW9uczogQmVoYXZpb3JPcHRpb25zO1xuICBwcml2YXRlIGltYWdlQmVoYXZpb3JPcHRpb25zOiBCZWhhdmlvck9wdGlvbnM7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICB0aGlzLnByb3BzID0gcHJvcHM7XG4gICAgdGhpcy5iYXNlUGF0aCA9IG5vcm1hbGl6ZUJhc2VQYXRoKHByb3BzLmJhc2VQYXRoKTtcbiAgICB0aGlzLmFzc2V0UHJlZml4ID0gdGhpcy5yZXNvbHZlQXNzZXRQcmVmaXgoKTtcbiAgICB0aGlzLnN0YXRpY09yaWdpbiA9IHRoaXMuY3JlYXRlU3RhdGljT3JpZ2luKCk7XG4gICAgdGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZSA9IHByb3BzLm5leHRqc1R5cGUgPT09IE5leHRqc1R5cGUuR0xPQkFMX0ZVTkNUSU9OUztcbiAgICB0aGlzLnZhbGlkYXRlRnVuY3Rpb25Hcm91cFByb3BzKCk7XG4gICAgdGhpcy5keW5hbWljT3JpZ2luID0gdGhpcy5jcmVhdGVEeW5hbWljT3JpZ2luKCk7XG4gICAgdGhpcy5keW5hbWljT3JpZ2luUmVzcG9uc2VQb2xpY3kgPSB0aGlzLmNyZWF0ZUR5bmFtaWNPcmlnaW5SZXF1ZXN0UG9saWN5KCk7XG4gICAgdGhpcy5keW5hbWljQ2xvdWRGcm9udEZ1bmN0aW9uQXNzb2NpYXRpb25zID1cbiAgICAgIHRoaXMuY3JlYXRlRHluYW1pY0Nsb3VkRnJvbnRGdW5jdGlvbkFzc29jaWF0aW9ucygpO1xuICAgIHRoaXMuc3RhdGljQmVoYXZpb3JPcHRpb25zID0gdGhpcy5jcmVhdGVTdGF0aWNCZWhhdmlvck9wdGlvbnMoKTtcbiAgICB0aGlzLmR5bmFtaWNCZWhhdmlvck9wdGlvbnMgPSB0aGlzLmNyZWF0ZUR5bmFtaWNCZWhhdmlvck9wdGlvbnMoKTtcbiAgICB0aGlzLmltYWdlQmVoYXZpb3JPcHRpb25zID0gdGhpcy5jcmVhdGVJbWFnZUJlaGF2aW9yT3B0aW9ucygpO1xuICAgIHRoaXMuZGlzdHJpYnV0aW9uID0gdGhpcy5nZXREaXN0cmlidXRpb24oKTtcbiAgICBpZiAodGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZSkge1xuICAgICAgdGhpcy5ncmFudEludm9rZShERUZBVUxUX0ZVTkNUSU9OX0dST1VQLCBwcm9wcy5mdW5jdGlvblVybCEpO1xuICAgIH1cbiAgICB0aGlzLmFkZFN0YXRpY0JlaGF2aW9ycygpO1xuICAgIHRoaXMuYWRkRHluYW1pY0JlaGF2aW9ycygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBDbG91ZEZyb250IGNvbW1lbnQgdGhhdCBpcyBzYWZlIGZvciB0aGUgMTI4IGNoYXJhY3RlciBsaW1pdC5cbiAgICogSWYgdGhlIGZ1bGwgY29tbWVudCB3aXRoIHN0YWNrIG5hbWUgZXhjZWVkcyAxMjggY2hhcmFjdGVycywgcmV0dXJucyB0aGUgYmFzZSBjb21tZW50IG9ubHkuXG4gICAqIEBwYXJhbSBiYXNlQ29tbWVudCBUaGUgYmFzZSBjb21tZW50IHRleHRcbiAgICogQHBhcmFtIHN0YWNrTmFtZSBUaGUgc3RhY2sgbmFtZSB0byBhcHBlbmRcbiAgICogQHJldHVybnMgQSBjb21tZW50IHN0cmluZyB0aGF0IGlzIGd1YXJhbnRlZWQgdG8gYmUgPCAxMjggY2hhcmFjdGVyc1xuICAgKi9cbiAgcHJpdmF0ZSBnZXRDb21tZW50KGJhc2VDb21tZW50OiBzdHJpbmcsIHN0YWNrTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBmdWxsQ29tbWVudCA9IGAke2Jhc2VDb21tZW50fSBmb3IgJHtzdGFja05hbWV9YDtcbiAgICByZXR1cm4gZnVsbENvbW1lbnQubGVuZ3RoIDwgMTI4ID8gZnVsbENvbW1lbnQgOiBiYXNlQ29tbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU3RhdGljT3JpZ2luKCk6IElPcmlnaW4ge1xuICAgIHJldHVybiBTM0J1Y2tldE9yaWdpbi53aXRoT3JpZ2luQWNjZXNzQ29udHJvbCh0aGlzLnByb3BzLmFzc2V0c0J1Y2tldCwge1xuICAgICAgLy8gTElTVCBsZXRzIFMzIGFuc3dlciBhIG1pc3Npbmcga2V5IHdpdGggNDA0IGluc3RlYWQgb2YgNDAzXG4gICAgICBvcmlnaW5BY2Nlc3NMZXZlbHM6IFtBY2Nlc3NMZXZlbC5SRUFELCBBY2Nlc3NMZXZlbC5MSVNUXSxcbiAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5zM0J1Y2tldE9yaWdpblByb3BzLFxuICAgIH0pO1xuICB9XG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY09yaWdpbigpOiBJT3JpZ2luIHtcbiAgICBpZiAodGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZSkge1xuICAgICAgaWYgKCF0aGlzLnByb3BzLmZ1bmN0aW9uVXJsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgTmV4dGpzRGlzdHJpYnV0aW9uUHJvcHMuZnVuY3Rpb25VcmxcIik7XG4gICAgICB9XG4gICAgICByZXR1cm4gRnVuY3Rpb25VcmxPcmlnaW4ud2l0aE9yaWdpbkFjY2Vzc0NvbnRyb2woXG4gICAgICAgIHRoaXMucHJvcHMuZnVuY3Rpb25VcmwsXG4gICAgICAgIHRoaXMucHJvcHMub3ZlcnJpZGVzPy5keW5hbWljRnVuY3Rpb25VcmxPcmlnaW5XaXRoT0FDUHJvcHMsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsb2FkQmFsYW5jZXIgPSB0aGlzLnByb3BzLmxvYWRCYWxhbmNlcjtcbiAgICAgIGlmICghbG9hZEJhbGFuY2VyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgTmV4dGpzRGlzdHJpYnV0aW9uUHJvcHMubG9hZEJhbGFuY2VyXCIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFZwY09yaWdpbi53aXRoQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIobG9hZEJhbGFuY2VyLCB7XG4gICAgICAgIHByb3RvY29sUG9saWN5OiB0aGlzLnByb3BzLmNlcnRpZmljYXRlXG4gICAgICAgICAgPyBPcmlnaW5Qcm90b2NvbFBvbGljeS5IVFRQU19PTkxZXG4gICAgICAgICAgOiBPcmlnaW5Qcm90b2NvbFBvbGljeS5IVFRQX09OTFksXG4gICAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5keW5hbWljVnBjT3JpZ2luV2l0aEVuZHBvaW50UHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIExhbWJkYSBGdW5jdGlvbiBVUkxzIFwiZXhwZWN0IHRoZSBgSG9zdGAgaGVhZGVyIHRvIGNvbnRhaW4gdGhlIG9yaWdpbiBkb21haW5cbiAgICogbmFtZSwgbm90IHRoZSBkb21haW4gbmFtZSBvZiB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24uXCJcbiAgICpcbiAgICogQSBjb250YWluZXIgb3JpZ2luIGFsc28gZ2V0cyBDbG91ZEZyb250J3Mgb3duIGhlYWRlcnMsIGZvclxuICAgKiBgQ2xvdWRGcm9udC1Gb3J3YXJkZWQtUHJvdG9gOiB3aXRob3V0IGEgY2VydGlmaWNhdGUgQ2xvdWRGcm9udCByZWFjaGVzIHRoZVxuICAgKiBBTEIgb3ZlciBwbGFpbiBIVFRQLCBzbyB0aGUgQUxCJ3MgYFgtRm9yd2FyZGVkLVByb3RvYCBpcyBgaHR0cGAsIGFuZCB0aGVcbiAgICogcnVudGltZSB3b3VsZCBidWlsZCBldmVyeSBhYnNvbHV0ZSBVUkwgKGByZXF1ZXN0LnVybGAsIHRoZSBvcmlnaW4gYSBzZXJ2ZXJcbiAgICogYWN0aW9uIGlzIGZvcndhcmRlZCB0bykgYXMgYGh0dHA6Ly9gIGJlaGluZCBhIHZpZXdlciBvbiBIVFRQUy5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvdXNpbmctbWFuYWdlZC1vcmlnaW4tcmVxdWVzdC1wb2xpY2llcy5odG1sI21hbmFnZWQtb3JpZ2luLXJlcXVlc3QtcG9saWN5LWFsbC12aWV3ZXItZXhjZXB0LWhvc3QtaGVhZGVyXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkRnJvbnQvbGF0ZXN0L0RldmVsb3Blckd1aWRlL3VzaW5nLW1hbmFnZWQtb3JpZ2luLXJlcXVlc3QtcG9saWNpZXMuaHRtbCNtYW5hZ2VkLW9yaWdpbi1yZXF1ZXN0LXBvbGljeS1hbGwtdmlld2VyLWFuZC1jbG91ZGZyb250XG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUR5bmFtaWNPcmlnaW5SZXF1ZXN0UG9saWN5KCk6IElPcmlnaW5SZXF1ZXN0UG9saWN5IHtcbiAgICByZXR1cm4gdGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZVxuICAgICAgPyBPcmlnaW5SZXF1ZXN0UG9saWN5LkFMTF9WSUVXRVJfRVhDRVBUX0hPU1RfSEVBREVSXG4gICAgICA6IE9yaWdpblJlcXVlc3RQb2xpY3kuQUxMX1ZJRVdFUl9BTkRfQ0xPVURGUk9OVF8yMDIyO1xuICB9XG4gIC8qKlxuICAgKiBFbnN1cmVzIE5leHQuanMgYHJlcXVlc3QudXJsYCB3aWxsIGJlIGNvcnJlY3QgZG9tYWluIGluc3RlYWQgb2YgVVJMIG9mXG4gICAqIGNvbXB1dGUgKExhbWJkYSBvciBGYXJnYXRlKVxuICAgKiBAc2VlIGh0dHBzOi8vb3Blbi1uZXh0LmpzLm9yZy9hZHZhbmNlZC93b3JrYXJvdW5kI3dvcmthcm91bmQtc2V0LXgtZm9yd2FyZGVkLWhvc3QtaGVhZGVyLWF3cy1zcGVjaWZpY1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVEeW5hbWljQ2xvdWRGcm9udEZ1bmN0aW9uQXNzb2NpYXRpb25zKCk6IEZ1bmN0aW9uQXNzb2NpYXRpb25bXSB7XG4gICAgY29uc3QgYXNzb2NpYXRpb25zOiBGdW5jdGlvbkFzc29jaWF0aW9uW10gPSBbXTtcbiAgICBpZiAodGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZSkge1xuICAgICAgY29uc3QgY2xvdWRGcm9udEZuID0gbmV3IENsb3VkRnJvbnRGdW5jdGlvbih0aGlzLCBcIkNsb3VkRnJvbnRGblwiLCB7XG4gICAgICAgIC8vIGNsb3VkZnJvbnQtanMtMS4wLCBzbyBFUzUuMTogYHZhcmAsIG5vIGFycm93IGZ1bmN0aW9ucywgbm8gdGVtcGxhdGVcbiAgICAgICAgLy8gbGl0ZXJhbHMsIG5vIGBPYmplY3Qua2V5c2AuXG4gICAgICAgIGNvZGU6IEZ1bmN0aW9uQ29kZS5mcm9tSW5saW5lKGBcbiAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgcmVxdWVzdCA9IGV2ZW50LnJlcXVlc3Q7XG4gICAgICAgICAgICB2YXIgdXJpID0gcmVxdWVzdC51cmk7XG5cbiAgICAgICAgICAgIC8vIE5leHQuanMgYW5zd2VycyBhbnkgcGF0aCBjb250YWluaW5nIGEgYmFja3NsYXNoIG9yIGEgcmVwZWF0ZWRcbiAgICAgICAgICAgIC8vIHNsYXNoIHdpdGggYSAzMDggdG8gdGhlIGNvbGxhcHNlZCBwYXRoXG4gICAgICAgICAgICAvLyAoXFxgbm9ybWFsaXplUmVwZWF0ZWRTbGFzaGVzXFxgLCBjYWxsZWQgZnJvbSBcXGBiYXNlLXNlcnZlci50c1xcYCksIGFuZCBzb1xuICAgICAgICAgICAgLy8gZG9lcyB0aGlzIHJ1bnRpbWUuIEJlaGluZCBhIExhbWJkYSBGdW5jdGlvbiBVUkwgdGhlIG9yaWdpbiBuZXZlclxuICAgICAgICAgICAgLy8gZ2V0cyB0aGUgY2hhbmNlOiBPcmlnaW4gQWNjZXNzIENvbnRyb2wgc2lnbnMgdGhlIHJhdyBwYXRoIHdoaWxlIHRoZVxuICAgICAgICAgICAgLy8gRnVuY3Rpb24gVVJMIGNhbm9uaWNhbGl6ZXMgaXQgYmVmb3JlIHZlcmlmeWluZywgc28gdGhlIG9yaWdpblxuICAgICAgICAgICAgLy8gYW5zd2VycyA0MDMgU2lnbmF0dXJlRG9lc05vdE1hdGNoLiBEb2luZyB0aGUgcmVkaXJlY3QgaGVyZSBpcyB3aGF0XG4gICAgICAgICAgICAvLyBtYWtlcyBcXGAvYmFzZXBhdGgvL3RvLXN2XFxgIGJlaGF2ZSBhcyBpdCBkb2VzIHVuZGVyIFxcYG5leHQgc3RhcnRcXGAuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gQSBiYXJlIFxcYC8vXFxgIHJlYWNoZXMgaGVyZSB0b28sIGFuZCBpcyBhbnN3ZXJlZCB0aGUgc2FtZSB3YXkgLVxuICAgICAgICAgICAgLy8gbWVhc3VyZWQsIGJlY2F1c2UgXFxgLy9cXGAgYXQgdGhlIHN0YXJ0IG9mIGEgcmVxdWVzdCB0YXJnZXQgaXMgYWxzbyB0aGVcbiAgICAgICAgICAgIC8vIGF1dGhvcml0eSBmb3JtIGFuZCBpdCB3YXMgbm90IG9idmlvdXMgQ2xvdWRGcm9udCB3b3VsZCByb3V0ZSBpdCB0byBhXG4gICAgICAgICAgICAvLyBmdW5jdGlvbiBhdCBhbGwuIEl0IGRvZXM6IFxcYEdFVCAvL1xcYCBhbnN3ZXJzIDMwOCB0byBcXGAvXFxgIHdpdGhcbiAgICAgICAgICAgIC8vIFxcYHgtY2FjaGU6IEZ1bmN0aW9uR2VuZXJhdGVkUmVzcG9uc2VcXGAsIG92ZXIgYm90aCBIVFRQLzEuMSBhbmQgSFRUUC8yLFxuICAgICAgICAgICAgLy8gd2hpY2ggaXMgd2hhdCBcXGB0ZXN0L2UyZS9oeWRyYXRpb25cXGAgYXNrcyBmb3IuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gVHdvIHRoaW5ncyBOZXh0LmpzIGRvZXMgdGhhdCB0aGlzIGNhbm5vdDpcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyAtIHRoZSBib2R5IGl0IHNlbmRzIHdpdGggaXRzIG93biByZWRpcmVjdCAodGhlIGRlc3RpbmF0aW9uLCBhc1xuICAgICAgICAgICAgLy8gICB0ZXh0KSwgYmVjYXVzZSBhIGdlbmVyYXRlZCByZXNwb25zZSBjYW4gb25seSBjYXJyeSBvbmUgb25cbiAgICAgICAgICAgIC8vICAgY2xvdWRmcm9udC1qcy0yLjAuIE5vIGtub3duIGNsaWVudCByZWFkcyBpdC5cbiAgICAgICAgICAgIC8vIC0gdGhlIG9yaWdpbmFsIG9yZGVyIG9mIHRoZSBxdWVyeSBzdHJpbmcuIFRoZSBldmVudCBleHBvc2VzXG4gICAgICAgICAgICAvLyAgIFxcYHF1ZXJ5c3RyaW5nXFxgIGFzIGFuIG9iamVjdCwgbmV2ZXIgYXMgdGhlIHJhdyBzdHJpbmcsIHNvXG4gICAgICAgICAgICAvLyAgIFxcYC94Ly95P2E9MSZiPTJcXGAgcmVkaXJlY3RzIHRvIFxcYC94L3k/Yj0yJmE9MVxcYC4gVGhlIHBhaXJzIGFsbFxuICAgICAgICAgICAgLy8gICBzdXJ2aXZlOyBvbmx5IHRoZWlyIG9yZGVyIGlzIENsb3VkRnJvbnQncyByYXRoZXIgdGhhbiB0aGVcbiAgICAgICAgICAgIC8vICAgY2xpZW50J3MsIGFuZCBhIHJlZGlyZWN0IHRhcmdldCBpcyBub3Qgb3JkZXItc2Vuc2l0aXZlLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIEEgcmVwZWF0ZWQga2V5J3MgXFxgbXVsdGlWYWx1ZVxcYCBhbHJlYWR5IGhvbGRzIGl0cyBmaXJzdCB2YWx1ZSwgd2hpY2hcbiAgICAgICAgICAgIC8vIFxcYHZhbHVlXFxgIHJlcGVhdHMsIHNvIGl0IGlzIG9uZSBvciB0aGUgb3RoZXIsIG5ldmVyIGJvdGguIE5hbWVzIGFuZFxuICAgICAgICAgICAgLy8gdmFsdWVzIGFycml2ZSBhcyB0aGUgY2xpZW50IHNlbnQgdGhlbSwgc3RpbGwgcGVyY2VudC1lbmNvZGVkXG4gICAgICAgICAgICAvLyAobWVhc3VyZWQ6IFxcYD9hPSUyMGIlMjZjJnA9MSsyXFxgIHJlYWRzIGJhY2sgdW5jaGFuZ2VkKSwgc28gdGhleSBhcmVcbiAgICAgICAgICAgIC8vIGpvaW5lZCBhcy1pczsgZW5jb2RpbmcgdGhlbSBhZ2FpbiB3b3VsZCB0dXJuIFxcYCUyMFxcYCBpbnRvIFxcYCUyNTIwXFxgLlxuICAgICAgICAgICAgaWYgKC9cXFxcXFxcXHxcXFxcL1xcXFwvLy50ZXN0KHVyaSkpIHtcbiAgICAgICAgICAgICAgdmFyIGxvY2F0aW9uID0gdXJpLnJlcGxhY2UoL1xcXFxcXFxcL2csIFwiL1wiKS5yZXBsYWNlKC9cXFxcL1xcXFwvKy9nLCBcIi9cIik7XG4gICAgICAgICAgICAgIHZhciBxcyA9IFtdO1xuICAgICAgICAgICAgICBmb3IgKHZhciBuYW1lIGluIHJlcXVlc3QucXVlcnlzdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB2YXIgcSA9IHJlcXVlc3QucXVlcnlzdHJpbmdbbmFtZV07XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IHEubXVsdGlWYWx1ZSB8fCBbcV07XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgIHZhciB2ID0gdmFsdWVzW2ldLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgcXMucHVzaCh2ID09PSBcIlwiID8gbmFtZSA6IG5hbWUgKyBcIj1cIiArIHYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAocXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24gPSBsb2NhdGlvbiArIFwiP1wiICsgcXMuam9pbihcIiZcIik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBzdGF0dXNDb2RlOiAzMDgsXG4gICAgICAgICAgICAgICAgc3RhdHVzRGVzY3JpcHRpb246IFwiUGVybWFuZW50IFJlZGlyZWN0XCIsXG4gICAgICAgICAgICAgICAgaGVhZGVyczogeyBsb2NhdGlvbjogeyB2YWx1ZTogbG9jYXRpb24gfSB9LFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXF1ZXN0LmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1ob3N0XCJdID0gcmVxdWVzdC5oZWFkZXJzLmhvc3Q7XG4gICAgICAgICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYCksXG4gICAgICB9KTtcbiAgICAgIGFzc29jaWF0aW9ucy5wdXNoKHtcbiAgICAgICAgZXZlbnRUeXBlOiBGdW5jdGlvbkV2ZW50VHlwZS5WSUVXRVJfUkVRVUVTVCxcbiAgICAgICAgZnVuY3Rpb246IGNsb3VkRnJvbnRGbixcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYXNzb2NpYXRpb25zO1xuICB9XG4gIHByaXZhdGUgY3JlYXRlU3RhdGljQmVoYXZpb3JPcHRpb25zKCk6IEJlaGF2aW9yT3B0aW9ucyB7XG4gICAgY29uc3Qgc3RhdGljQmVoYXZpb3JPcHRpb25zID0gdGhpcy5wcm9wcy5vdmVycmlkZXM/LnN0YXRpY0JlaGF2aW9yT3B0aW9ucztcbiAgICBjb25zdCByZXNwb25zZUhlYWRlcnNQb2xpY3kgPVxuICAgICAgc3RhdGljQmVoYXZpb3JPcHRpb25zPy5yZXNwb25zZUhlYWRlcnNQb2xpY3kgPz9cbiAgICAgIG5ldyBSZXNwb25zZUhlYWRlcnNQb2xpY3kodGhpcywgXCJTdGF0aWNSZXNwb25zZUhlYWRlcnNQb2xpY3lcIiwge1xuICAgICAgICBzZWN1cml0eUhlYWRlcnNCZWhhdmlvcjogdGhpcy5jb21tb25TZWN1cml0eUhlYWRlcnNCZWhhdmlvcixcbiAgICAgICAgY29tbWVudDogdGhpcy5nZXRDb21tZW50KFxuICAgICAgICAgIFwiTmV4dEpTIFN0YXRpYyBSZXNwb25zZSBIZWFkZXJzIFBvbGljeVwiLFxuICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LnN0YXRpY1Jlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzLFxuICAgICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFsbG93ZWRNZXRob2RzOiBBbGxvd2VkTWV0aG9kcy5BTExPV19HRVRfSEVBRF9PUFRJT05TLFxuICAgICAgY2FjaGVkTWV0aG9kczogQ2FjaGVkTWV0aG9kcy5DQUNIRV9HRVRfSEVBRF9PUFRJT05TLFxuICAgICAgY2FjaGVQb2xpY3k6IENhY2hlUG9saWN5LkNBQ0hJTkdfT1BUSU1JWkVELFxuICAgICAgb3JpZ2luOiB0aGlzLnN0YXRpY09yaWdpbixcbiAgICAgIHJlc3BvbnNlSGVhZGVyc1BvbGljeSxcbiAgICAgIHZpZXdlclByb3RvY29sUG9saWN5OiBWaWV3ZXJQcm90b2NvbFBvbGljeS5SRURJUkVDVF9UT19IVFRQUyxcbiAgICAgIC4uLnN0YXRpY0JlaGF2aW9yT3B0aW9ucyxcbiAgICB9O1xuICB9XG4gIHByaXZhdGUgY3JlYXRlRHluYW1pY0JlaGF2aW9yT3B0aW9ucygpOiBCZWhhdmlvck9wdGlvbnMge1xuICAgIGNvbnN0IGR5bmFtaWNCZWhhdmlvck9wdGlvbnMgPSB0aGlzLnByb3BzLm92ZXJyaWRlcz8uZHluYW1pY0JlaGF2aW9yT3B0aW9ucztcbiAgICBjb25zdCBjYWNoZVBvbGljeVByb3BzID0gdGhpcy5wcm9wcy5vdmVycmlkZXM/LmR5bmFtaWNDYWNoZVBvbGljeVByb3BzO1xuICAgIC8vIGNyZWF0ZSBkZWZhdWx0IGNhY2hlIHBvbGljeSBpZiBub3QgcHJvdmlkZWRcbiAgICBjb25zdCBjYWNoZVBvbGljeSA9XG4gICAgICBkeW5hbWljQmVoYXZpb3JPcHRpb25zPy5jYWNoZVBvbGljeSA/P1xuICAgICAgbmV3IENhY2hlUG9saWN5KHRoaXMsIFwiRHluYW1pY0NhY2hlUG9saWN5XCIsIHtcbiAgICAgICAgLi4uKGlzQ2FjaGluZ0Rpc2FibGVkKGNhY2hlUG9saWN5UHJvcHMpXG4gICAgICAgICAgPyBESVNBQkxFRF9DQUNIRV9LRVlcbiAgICAgICAgICA6IERZTkFNSUNfQ0FDSEVfS0VZKSxcbiAgICAgICAgLy8gQSByZXNwb25zZSB3aXRoIG5vIGBDYWNoZS1Db250cm9sYCBpcyBub3QgY2FjaGVkLCB3aGljaCBpcyB3aGF0IE5leHQuanNcbiAgICAgICAgLy8gYW5kIGV2ZXJ5IGFwcCB3cml0dGVuIGZvciBpdCBhc3N1bWU6IGEgZHluYW1pYyByb3V0ZSBoYW5kbGVyIHNldHMgbm9uZS5cbiAgICAgICAgLy8gQ0RLJ3MgZGVmYXVsdCBpcyBhIGRheSwgd2hpY2ggY2FjaGVkIGAvYXBpLypgIHJlc3BvbnNlcyBhdCB0aGUgZWRnZSBmb3JcbiAgICAgICAgLy8gMjQgaG91cnMuIEFueXRoaW5nIE5leHQuanMgKm1lYW5zKiB0byBjYWNoZSAtIElTUiwgU1NHLCBhIFBQUiBzaGVsbCAtXG4gICAgICAgIC8vIHNheXMgc28gd2l0aCBgcy1tYXhhZ2VgLCB3aGljaCBgbWF4VHRsYCBzdGlsbCBob25vcnMuXG4gICAgICAgIGRlZmF1bHRUdGw6IER1cmF0aW9uLnNlY29uZHMoMCksXG4gICAgICAgIGNvbW1lbnQ6IHRoaXMuZ2V0Q29tbWVudChcbiAgICAgICAgICBcIk5leHRKUyBEeW5hbWljIENhY2hlIFBvbGljeVwiLFxuICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgLi4uY2FjaGVQb2xpY3lQcm9wcyxcbiAgICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlSGVhZGVyc1BvbGljeSA9XG4gICAgICBkeW5hbWljQmVoYXZpb3JPcHRpb25zPy5yZXNwb25zZUhlYWRlcnNQb2xpY3kgPz9cbiAgICAgIG5ldyBSZXNwb25zZUhlYWRlcnNQb2xpY3kodGhpcywgXCJEeW5hbWljUmVzcG9uc2VIZWFkZXJzUG9saWN5XCIsIHtcbiAgICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHRoaXMuY29tbW9uU2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IsXG4gICAgICAgIGNvbW1lbnQ6IHRoaXMuZ2V0Q29tbWVudChcbiAgICAgICAgICBcIk5leHRKUyBEeW5hbWljIFJlc3BvbnNlIEhlYWRlcnMgUG9saWN5XCIsXG4gICAgICAgICAgU3RhY2sub2YodGhpcykuc3RhY2tOYW1lLFxuICAgICAgICApLFxuICAgICAgICAuLi50aGlzLnByb3BzLm92ZXJyaWRlcz8uZHluYW1pY1Jlc3BvbnNlSGVhZGVyc1BvbGljeVByb3BzLFxuICAgICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFsbG93ZWRNZXRob2RzOiBBbGxvd2VkTWV0aG9kcy5BTExPV19BTEwsXG4gICAgICBjYWNoZVBvbGljeSxcbiAgICAgIG9yaWdpbjogdGhpcy5keW5hbWljT3JpZ2luLFxuICAgICAgb3JpZ2luUmVxdWVzdFBvbGljeTogdGhpcy5keW5hbWljT3JpZ2luUmVzcG9uc2VQb2xpY3ksXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3ksXG4gICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAuLi5keW5hbWljQmVoYXZpb3JPcHRpb25zLFxuICAgICAgZnVuY3Rpb25Bc3NvY2lhdGlvbnM6IHRoaXMud2l0aER5bmFtaWNGdW5jdGlvbkFzc29jaWF0aW9ucyhcbiAgICAgICAgXCJkeW5hbWljQmVoYXZpb3JPcHRpb25zXCIsXG4gICAgICAgIGR5bmFtaWNCZWhhdmlvck9wdGlvbnM/LmZ1bmN0aW9uQXNzb2NpYXRpb25zLFxuICAgICAgKSxcbiAgICB9O1xuICB9XG4gIC8qKlxuICAgKiBUaGUgYmVoYXZpb3IncyBmdW5jdGlvbiBhc3NvY2lhdGlvbnM6IGFuIG92ZXJyaWRlJ3MsIHBsdXMgdGhlIHZpZXdlci1yZXF1ZXN0XG4gICAqIGZ1bmN0aW9uIEdsb2JhbCBGdW5jdGlvbnMgZGVwZW5kcyBvbi5cbiAgICpcbiAgICogU3ByZWFkaW5nIHRoZSBvdmVycmlkZSdzIGBmdW5jdGlvbkFzc29jaWF0aW9uc2Agb3ZlciBvdXJzIHdvdWxkIHNpbGVudGx5XG4gICAqIGRyb3AgdGhhdCBmdW5jdGlvbiwgYW5kIHdpdGggaXQgdGhlIG9ubHkgdGhpbmcgc3RhbmRpbmcgYmV0d2VlbiBhIHZpZXdlcidzXG4gICAqIG93biBgWC1Gb3J3YXJkZWQtSG9zdGAgYW5kIHRoZSBydW50aW1lLCB3aGljaCB0cnVzdHMgdGhhdCBoZWFkZXIgb24gRnVuY3Rpb25cbiAgICogVVJMIGV2ZW50cyAoYGxhbWJkYS1ldmVudC50c2ApOiBob3N0IGluamVjdGlvbiBpbnRvIHJlZGlyZWN0cyBhbmQgYWJzb2x1dGVcbiAgICogVVJMcywgY2FjaGVkIGZvciBvdGhlciB2aWV3ZXJzIGJlY2F1c2UgdGhlIGhlYWRlciBpcyBub3QgaW4gdGhlIGNhY2hlIGtleS5cbiAgICogU28gb3VycyBpcyBrZXB0LCBhbmQgYW4gb3ZlcnJpZGUgY2xhaW1pbmcgVklFV0VSX1JFUVVFU1Qg4oCUIHdoaWNoIENsb3VkRnJvbnRcbiAgICogYWxsb3dzIG9ubHkgb25lIG9mIHBlciBiZWhhdmlvciDigJQgaXMgYW4gZXJyb3IgcmF0aGVyIHRoYW4gYSByZXBsYWNlbWVudC5cbiAgICovXG4gIHByaXZhdGUgd2l0aER5bmFtaWNGdW5jdGlvbkFzc29jaWF0aW9ucyhcbiAgICBvdmVycmlkZU5hbWU6IHN0cmluZyxcbiAgICBvdmVycmlkZGVuOiBGdW5jdGlvbkFzc29jaWF0aW9uW10gfCB1bmRlZmluZWQsXG4gICk6IEZ1bmN0aW9uQXNzb2NpYXRpb25bXSB7XG4gICAgaWYgKCFvdmVycmlkZGVuKSB7XG4gICAgICByZXR1cm4gdGhpcy5keW5hbWljQ2xvdWRGcm9udEZ1bmN0aW9uQXNzb2NpYXRpb25zO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaXNGdW5jdGlvbkNvbXB1dGUpIHtcbiAgICAgIHJldHVybiBvdmVycmlkZGVuO1xuICAgIH1cbiAgICBjb25zdCBjbGFpbWVkID0gb3ZlcnJpZGRlbi5zb21lKFxuICAgICAgKGFzc29jaWF0aW9uKSA9PlxuICAgICAgICBhc3NvY2lhdGlvbi5ldmVudFR5cGUgPT09IEZ1bmN0aW9uRXZlbnRUeXBlLlZJRVdFUl9SRVFVRVNULFxuICAgICk7XG4gICAgaWYgKGNsYWltZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7TE9HX1BSRUZJWH0gXFxgb3ZlcnJpZGVzLiR7b3ZlcnJpZGVOYW1lfS5mdW5jdGlvbkFzc29jaWF0aW9uc1xcYCBgICtcbiAgICAgICAgICBgYXNzb2NpYXRlcyBhIENsb3VkRnJvbnQgZnVuY3Rpb24gd2l0aCBgICtcbiAgICAgICAgICBgJHtGdW5jdGlvbkV2ZW50VHlwZS5WSUVXRVJfUkVRVUVTVH0sIGJ1dCBOZXh0anNHbG9iYWxGdW5jdGlvbnMgbmVlZHMgYCArXG4gICAgICAgICAgYHRoYXQgZXZlbnQgdHlwZSBmb3IgaXRzIG93biBmdW5jdGlvbiwgd2hpY2ggb3ZlcndyaXRlcyBgICtcbiAgICAgICAgICBgXFxgeC1mb3J3YXJkZWQtaG9zdFxcYCB3aXRoIHRoZSB2aWV3ZXIncyBcXGBIb3N0XFxgICh0aGUgcnVudGltZSB0cnVzdHMgYCArXG4gICAgICAgICAgYHRoYXQgaGVhZGVyIGJlaGluZCBDbG91ZEZyb250KSBhbmQgcmVkaXJlY3RzIHJlcGVhdGVkIHNsYXNoZXMuIGAgK1xuICAgICAgICAgIGBDbG91ZEZyb250IHBlcm1pdHMgb25seSBvbmUgZnVuY3Rpb24gcGVyIGV2ZW50IHR5cGUgcGVyIGJlaGF2aW9yLiBgICtcbiAgICAgICAgICBgTW92ZSB0aGUgbG9naWMgdG8gJHtGdW5jdGlvbkV2ZW50VHlwZS5WSUVXRVJfUkVTUE9OU0V9LCBvciBpbnRvIGAgK1xuICAgICAgICAgIGB0aGUgYXBwJ3MgbWlkZGxld2FyZS5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIFsuLi5vdmVycmlkZGVuLCAuLi50aGlzLmR5bmFtaWNDbG91ZEZyb250RnVuY3Rpb25Bc3NvY2lhdGlvbnNdO1xuICB9XG4gIC8qKlxuICAgKiBgX25leHQvaW1hZ2UqYCBnb2VzIHRvIHRoZSBzYW1lIG9yaWdpbiBhcyBldmVyeXRoaW5nIGVsc2Ug4oCUIHRoZSBOZXh0LmpzXG4gICAqIHNlcnZlciBvcHRpbWl6ZXMgaW1hZ2VzIGluLXByb2Nlc3Mg4oCUIGJ1dCBrZWVwcyBpdHMgb3duIGJlaGF2aW9yIGZvciB0aGVcbiAgICogY2FjaGUgcG9saWN5OiBgcXVlcnlTdHJpbmdCZWhhdmlvcjogYWxsKClgIHBsdXMgYGFjY2VwdGAgaW4gdGhlIGNhY2hlIGtleSBpc1xuICAgKiByaWdodCBmb3IgaW1hZ2UgcmVxdWVzdHMgYW5kIHdyb25nIGZvciB0aGUgcmVzdC5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlSW1hZ2VCZWhhdmlvck9wdGlvbnMoKTogQmVoYXZpb3JPcHRpb25zIHtcbiAgICBjb25zdCBpbWFnZUJlaGF2aW9yT3B0aW9ucyA9IHRoaXMucHJvcHMub3ZlcnJpZGVzPy5pbWFnZUJlaGF2aW9yT3B0aW9ucztcbiAgICAvLyBhZGQgZGVmYXVsdCBjYWNoZSBwb2xpY3kgaWYgbm90IHByb3ZpZGVkXG4gICAgY29uc3QgY2FjaGVQb2xpY3kgPVxuICAgICAgaW1hZ2VCZWhhdmlvck9wdGlvbnM/LmNhY2hlUG9saWN5ID8/XG4gICAgICBuZXcgQ2FjaGVQb2xpY3kodGhpcywgXCJJbWFnZUNhY2hlUG9saWN5XCIsIHtcbiAgICAgICAgLy8gU0VDVVJJVFkgTk9URTogYnkgZGVmYXVsdCB3ZSBkb24ndCBpbmNsdWRlIGNvb2tpZXMgaW4gY2FjaGUgZm9yXG4gICAgICAgIC8vIGltYWdlcyBiL2MgaXQgc2lnbmlmaWNhbnRseSBpbXByb3ZlcyBpbWFnZSBwZXJmIGZvciBtb3N0IHNpdGVzIEJVVFxuICAgICAgICAvLyBpZiB5b3UgaGF2ZSBwcml2YXRlIGltYWdlcyBsb2NrZWQgYmVoaW5kIGF1dGggaW1wbGVtZW50ZWQgd2l0aCBjb29raWVzXG4gICAgICAgIC8vIHlvdSBuZWVkIHRvIG92ZXJyaWRlIHRoaXMuXG4gICAgICAgIHF1ZXJ5U3RyaW5nQmVoYXZpb3I6IENhY2hlUXVlcnlTdHJpbmdCZWhhdmlvci5hbGwoKSxcbiAgICAgICAgaGVhZGVyQmVoYXZpb3I6IENhY2hlSGVhZGVyQmVoYXZpb3IuYWxsb3dMaXN0KFwiYWNjZXB0XCIpLFxuICAgICAgICBjb29raWVCZWhhdmlvcjogQ2FjaGVDb29raWVCZWhhdmlvci5ub25lKCksXG4gICAgICAgIGVuYWJsZUFjY2VwdEVuY29kaW5nQnJvdGxpOiB0cnVlLFxuICAgICAgICBlbmFibGVBY2NlcHRFbmNvZGluZ0d6aXA6IHRydWUsXG4gICAgICAgIGNvbW1lbnQ6IHRoaXMuZ2V0Q29tbWVudChcbiAgICAgICAgICBcIk5leHRKUyBJbWFnZSBDYWNoZSBQb2xpY3lcIixcbiAgICAgICAgICBTdGFjay5vZih0aGlzKS5zdGFja05hbWUsXG4gICAgICAgICksXG4gICAgICAgIC4uLnRoaXMucHJvcHMub3ZlcnJpZGVzPy5pbWFnZUNhY2hlUG9saWN5UHJvcHMsXG4gICAgICB9KTtcbiAgICAvLyBhZGQgZGVmYXVsdCByZXNwb25zZSBoZWFkZXJzIHBvbGljeSBpZiBub3QgcHJvdmlkZWRcbiAgICBjb25zdCByZXNwb25zZUhlYWRlcnNQb2xpY3kgPVxuICAgICAgaW1hZ2VCZWhhdmlvck9wdGlvbnM/LnJlc3BvbnNlSGVhZGVyc1BvbGljeSA/P1xuICAgICAgbmV3IFJlc3BvbnNlSGVhZGVyc1BvbGljeSh0aGlzLCBcIkltYWdlUmVzcG9uc2VIZWFkZXJzUG9saWN5XCIsIHtcbiAgICAgICAgc2VjdXJpdHlIZWFkZXJzQmVoYXZpb3I6IHRoaXMuY29tbW9uU2VjdXJpdHlIZWFkZXJzQmVoYXZpb3IsXG4gICAgICAgIGNvbW1lbnQ6IHRoaXMuZ2V0Q29tbWVudChcbiAgICAgICAgICBcIk5leHRKUyBJbWFnZSBSZXNwb25zZSBIZWFkZXJzIFBvbGljeVwiLFxuICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmltYWdlUmVzcG9uc2VIZWFkZXJzUG9saWN5UHJvcHMsXG4gICAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgYWxsb3dlZE1ldGhvZHM6IEFsbG93ZWRNZXRob2RzLkFMTE9XX0dFVF9IRUFEX09QVElPTlMsXG4gICAgICBjYWNoZWRNZXRob2RzOiBDYWNoZWRNZXRob2RzLkNBQ0hFX0dFVF9IRUFEX09QVElPTlMsXG4gICAgICBvcmlnaW46IHRoaXMuZHluYW1pY09yaWdpbixcbiAgICAgIG9yaWdpblJlcXVlc3RQb2xpY3k6IHRoaXMuZHluYW1pY09yaWdpblJlc3BvbnNlUG9saWN5LFxuICAgICAgY2FjaGVQb2xpY3ksXG4gICAgICByZXNwb25zZUhlYWRlcnNQb2xpY3ksXG4gICAgICB2aWV3ZXJQcm90b2NvbFBvbGljeTogVmlld2VyUHJvdG9jb2xQb2xpY3kuUkVESVJFQ1RfVE9fSFRUUFMsXG4gICAgICAuLi5pbWFnZUJlaGF2aW9yT3B0aW9ucyxcbiAgICAgIGZ1bmN0aW9uQXNzb2NpYXRpb25zOiB0aGlzLndpdGhEeW5hbWljRnVuY3Rpb25Bc3NvY2lhdGlvbnMoXG4gICAgICAgIFwiaW1hZ2VCZWhhdmlvck9wdGlvbnNcIixcbiAgICAgICAgaW1hZ2VCZWhhdmlvck9wdGlvbnM/LmZ1bmN0aW9uQXNzb2NpYXRpb25zLFxuICAgICAgKSxcbiAgICB9O1xuICB9XG4gIC8qKlxuICAgKiBDcmVhdGVzIG9yIHVzZXMgdXNlciBzcGVjaWZpZWQgQ2xvdWRGcm9udCBEaXN0cmlidXRpb25cbiAgICovXG4gIHByaXZhdGUgZ2V0RGlzdHJpYnV0aW9uKCk6IERpc3RyaWJ1dGlvbiB7XG4gICAgbGV0IGRpc3RyaWJ1dGlvbjogRGlzdHJpYnV0aW9uO1xuICAgIGlmICh0aGlzLnByb3BzLmRpc3RyaWJ1dGlvbikge1xuICAgICAgZGlzdHJpYnV0aW9uID0gdGhpcy5wcm9wcy5kaXN0cmlidXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpc3RyaWJ1dGlvbiA9IG5ldyBEaXN0cmlidXRpb24odGhpcywgXCJEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBtaW5pbXVtUHJvdG9jb2xWZXJzaW9uOiBTZWN1cml0eVBvbGljeVByb3RvY29sLlRMU19WMV8yXzIwMjEsXG4gICAgICAgIGRlZmF1bHRCZWhhdmlvcjogdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zLFxuICAgICAgICAvLyBiZXN0IHRvIHVzZSBIVFRQIDIgYW5kIDMgZm9yIGNvbXBhdGFiaWxpdHkgKEhUVFAgMikgYW5kIHBlcmZvcm1hbmNlIChIVFRQMylcbiAgICAgICAgLy8gQ2xvdWRGcm9udCB3aWxsIGNob29zZSBiZXN0IG9wdGlvbiBmb3IgY2xpZW50XG4gICAgICAgIGh0dHBWZXJzaW9uOiBIdHRwVmVyc2lvbi5IVFRQMl9BTkRfMyxcbiAgICAgICAgY29tbWVudDogdGhpcy5nZXRDb21tZW50KFxuICAgICAgICAgIFwiTmV4dEpTIERpc3RyaWJ1dGlvblwiLFxuICAgICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgLi4udGhpcy5wcm9wcy5vdmVycmlkZXM/LmRpc3RyaWJ1dGlvblByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBkaXN0cmlidXRpb247XG4gIH1cbiAgcHJpdmF0ZSBhZGREeW5hbWljQmVoYXZpb3JzKCkge1xuICAgIC8vIEltYWdlIEJlaGF2aW9yXG4gICAgdGhpcy5kaXN0cmlidXRpb24uYWRkQmVoYXZpb3IoXG4gICAgICB0aGlzLmdldFBhdGhQYXR0ZXJuKFwiX25leHQvaW1hZ2UqXCIpLFxuICAgICAgdGhpcy5pbWFnZUJlaGF2aW9yT3B0aW9ucy5vcmlnaW4sXG4gICAgICB0aGlzLmltYWdlQmVoYXZpb3JPcHRpb25zLFxuICAgICk7XG4gICAgLy8gRnVuY3Rpb24gZ3JvdXAgYmVoYXZpb3JzLCBiZWZvcmUgdGhlIGJhc2VQYXRoIGNhdGNoLWFsbCBiZWxvdyBhbmQgYWZ0ZXJcbiAgICAvLyBgX25leHQvaW1hZ2UqYCAobm8gZ3JvdXAgcGF0dGVybiBjYW4gbWF0Y2ggYW4gaW1hZ2UgcmVxdWVzdCwgYW5kIGtlZXBpbmdcbiAgICAvLyB0aGUgb3JkZXIgb2YgdGhlIHVuc3BsaXQgY2FzZSBieXRlLWlkZW50aWNhbCBpcyB3b3J0aCBtb3JlIHRoYW4gc3ltbWV0cnkpLlxuICAgIHRoaXMuYWRkRnVuY3Rpb25Hcm91cEJlaGF2aW9ycygpO1xuICAgIC8vIFJvb3QgUGF0aCBCZWhhdmlvcnNcbiAgICBpZiAodGhpcy5iYXNlUGF0aCkge1xuICAgICAgLy8gYmVjYXVzZSB3ZSBhbHJlYWR5IGhhdmUgYSBiYXNlUGF0aCB3ZSBkb24ndCB1c2UgLyBpbnN0ZWFkIHdlIHVzZSAvYmFzZS1wYXRoXG4gICAgICB0aGlzLmRpc3RyaWJ1dGlvbi5hZGRCZWhhdmlvcihcbiAgICAgICAgYC8ke3RoaXMuYmFzZVBhdGh9YCxcbiAgICAgICAgdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zLm9yaWdpbixcbiAgICAgICAgdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zLFxuICAgICAgKTtcbiAgICAgIC8vIHdoZW4gYmFzZVBhdGggaXMgc2V0LCB3ZSBlbXVsYXRlIHRoZSBcImRlZmF1bHQgYmVoYXZpb3JcIiAoKikgZm9yIHRoZSBzaXRlIGFzIGAvYmFzZS1wYXRoLypgXG4gICAgICB0aGlzLmRpc3RyaWJ1dGlvbi5hZGRCZWhhdmlvcihcbiAgICAgICAgdGhpcy5nZXRQYXRoUGF0dGVybihcIipcIiksXG4gICAgICAgIHRoaXMuZHluYW1pY0JlaGF2aW9yT3B0aW9ucy5vcmlnaW4sXG4gICAgICAgIHRoaXMuZHluYW1pY0JlaGF2aW9yT3B0aW9ucyxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIG5vIGJhc2UgcGF0aCwgdGhlbiBkZWZhdWx0IGJlaGF2aW9yIHdpbGwgaGFuZGxlIGFsbCBvdGhlciBwYXRoc1xuICAgIH1cbiAgfVxuICAvKipcbiAgICogQmVmb3JlIGFueSBiZWhhdmlvciBpcyBjb21wdXRlZDogdGhlIGJ1ZGdldCBhbmQgdGhlIGBwdWJsaWMvYCBjaGVja3MgYm90aFxuICAgKiBnZW5lcmF0ZSB0aGUgZ3JvdXAgcGF0dGVybnMsIGFuZCB3b3VsZCBvdGhlcndpc2UgZmFpbCBmaXJzdCB3aXRoIGEgbGVzc1xuICAgKiB1c2VmdWwgbWVzc2FnZS5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVGdW5jdGlvbkdyb3VwUHJvcHMoKSB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMucHJvcHMuZnVuY3Rpb25Hcm91cHM/Lmxlbmd0aCAmJlxuICAgICAgIXRoaXMucHJvcHMuZnVuY3Rpb25Hcm91cEJlaGF2aW9ycz8ubGVuZ3RoXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5pc0Z1bmN0aW9uQ29tcHV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcImBmdW5jdGlvbkdyb3Vwc2AgaXMgb25seSBzdXBwb3J0ZWQgYnkgTmV4dGpzR2xvYmFsRnVuY3Rpb25zLlwiLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIEV2ZXJ5IGdyb3VwIGJlaGF2aW9yLCBmaW5hbCBwYXRoIHBhdHRlcm4gaW5jbHVkZWQsIGluIHRoZSBvcmRlclxuICAgKiB7QGxpbmsgYWRkRnVuY3Rpb25Hcm91cEJlaGF2aW9yc30gYWRkcyB0aGVtLlxuICAgKi9cbiAgcHJpdmF0ZSBmdW5jdGlvbkdyb3VwQmVoYXZpb3JzKCkge1xuICAgIHJldHVybiAodGhpcy5wcm9wcy5mdW5jdGlvbkdyb3VwQmVoYXZpb3JzID8/IFtdKS5tYXAoKGJlaGF2aW9yKSA9PiB7XG4gICAgICBjb25zdCBncm91cCA9IHRoaXMucHJvcHMuZnVuY3Rpb25Hcm91cHM/LmZpbmQoXG4gICAgICAgIChpdCkgPT4gaXQubmFtZSA9PT0gYmVoYXZpb3IuZ3JvdXAsXG4gICAgICApO1xuICAgICAgaWYgKCFncm91cCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYCR7TE9HX1BSRUZJWH0gXFxgZnVuY3Rpb25Hcm91cEJlaGF2aW9yc1xcYCByb3V0ZXMgdG8gZnVuY3Rpb24gZ3JvdXAgYCArXG4gICAgICAgICAgICBgXCIke2JlaGF2aW9yLmdyb3VwfVwiLCB3aGljaCBpcyBub3QgaW4gXFxgZnVuY3Rpb25Hcm91cHNcXGAuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmJlaGF2aW9yLFxuICAgICAgICBncm91cCxcbiAgICAgICAgcGF0aFBhdHRlcm46IHRoaXMuZ2V0UGF0aFBhdHRlcm4oYmVoYXZpb3IucGF0dGVybiksXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBPbmUgYmVoYXZpb3IgcGVyIGdyb3VwIHBhdHRlcm4sIG1vc3Qgc3BlY2lmaWMgZmlyc3QuXG4gICAqXG4gICAqIFRoZSBvcmRlciBpcyB0aGUgd2hvbGUgbWVjaGFuaXNtLiBDbG91ZEZyb250IGV2YWx1YXRlcyBiZWhhdmlvcnMgaW4gb3JkZXJcbiAgICogYW5kIHN0b3BzIGF0IHRoZSBmaXJzdCB3aG9zZSBwYXRoIHBhdHRlcm4gbWF0Y2hlcywgYW5kIGBhZGRCZWhhdmlvcmBcbiAgICogYXBwZW5kcyDigJQgc28gYGFwaS8qYCBhZGRlZCBiZWZvcmUgYGFwaS9yZXBvcnRzLypgIHdvdWxkIHN3YWxsb3cgZXZlcnlcbiAgICogcmVwb3J0IHJlcXVlc3QgYW5kIHNlbmQgaXQgdG8gYSBmdW5jdGlvbiB3aG9zZSBwYWNrYWdlIGhhcyBubyByZXBvcnRcbiAgICogZW50cnlwb2ludC4gVGhlIGFkYXB0ZXIgc29ydGVkIHRoZSBsaXN0IHdoZW4gaXQgY2hlY2tlZCBpdCBhZ2FpbnN0IGhvd1xuICAgKiBgYXNzaWduUm91dGVzVG9Hcm91cHNgIHBhY2thZ2VkIHRoZSBzYW1lIHJvdXRlcywgc28gaXQgaXMgYWRkZWQgYXMgaXQgaXMuXG4gICAqL1xuICBwcml2YXRlIGFkZEZ1bmN0aW9uR3JvdXBCZWhhdmlvcnMoKSB7XG4gICAgY29uc3Qgb3JpZ2luUGVyR3JvdXAgPSBuZXcgTWFwPHN0cmluZywgSU9yaWdpbj4oKTtcbiAgICBmb3IgKGNvbnN0IHsgZ3JvdXAsIHBhdGhQYXR0ZXJuIH0gb2YgdGhpcy5mdW5jdGlvbkdyb3VwQmVoYXZpb3JzKCkpIHtcbiAgICAgIGxldCBvcmlnaW4gPSBvcmlnaW5QZXJHcm91cC5nZXQoZ3JvdXAubmFtZSk7XG4gICAgICBpZiAoIW9yaWdpbikge1xuICAgICAgICBvcmlnaW4gPSBGdW5jdGlvblVybE9yaWdpbi53aXRoT3JpZ2luQWNjZXNzQ29udHJvbChcbiAgICAgICAgICBncm91cC5mdW5jdGlvblVybCxcbiAgICAgICAgICB0aGlzLnByb3BzLm92ZXJyaWRlcz8uZHluYW1pY0Z1bmN0aW9uVXJsT3JpZ2luV2l0aE9BQ1Byb3BzLFxuICAgICAgICApO1xuICAgICAgICBvcmlnaW5QZXJHcm91cC5zZXQoZ3JvdXAubmFtZSwgb3JpZ2luKTtcbiAgICAgICAgdGhpcy5ncmFudEludm9rZShncm91cC5uYW1lLCBncm91cC5mdW5jdGlvblVybCk7XG4gICAgICB9XG4gICAgICAvLyBTYW1lIGJlaGF2aW9yIG9wdGlvbnMgYXMgZXZlcnkgb3RoZXIgZHluYW1pYyByb3V0ZSDigJQgb25seSB0aGUgb3JpZ2luXG4gICAgICAvLyBkaWZmZXJzLCBhbmQgaXQgaXMgcGFzc2VkIHNlcGFyYXRlbHkuXG4gICAgICBjb25zdCB7IG9yaWdpbjogX2lnbm9yZWQsIC4uLmJlaGF2aW9yT3B0aW9ucyB9ID1cbiAgICAgICAgdGhpcy5keW5hbWljQmVoYXZpb3JPcHRpb25zO1xuICAgICAgdGhpcy5kaXN0cmlidXRpb24uYWRkQmVoYXZpb3IocGF0aFBhdHRlcm4sIG9yaWdpbiwgYmVoYXZpb3JPcHRpb25zKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIGBsYW1iZGE6SW52b2tlRnVuY3Rpb25gIGZvciBDbG91ZEZyb250LCB3aGljaCBhIEZ1bmN0aW9uIFVSTCBiZWhpbmQgT0FDXG4gICAqIG5lZWRzIGJlc2lkZXMgdGhlIGBsYW1iZGE6SW52b2tlRnVuY3Rpb25VcmxgIGBGdW5jdGlvblVybE9yaWdpbmAgZ3JhbnRzLFxuICAgKiBhbmQgc2NvcGVkIHRoZSBzYW1lIHdheTogdG8gdGhpcyBkaXN0cmlidXRpb24sIGFuZCB0byBjYWxscyB0aGF0IGNvbWVcbiAgICogdGhyb3VnaCB0aGUgRnVuY3Rpb24gVVJMLlxuICAgKi9cbiAgcHJpdmF0ZSBncmFudEludm9rZShncm91cDogc3RyaW5nLCBmdW5jdGlvblVybDogSUZ1bmN0aW9uVXJsKSB7XG4gICAgbmV3IENmblBlcm1pc3Npb24odGhpcywgYEludm9rZUZ1bmN0aW9uLSR7Z3JvdXB9YCwge1xuICAgICAgYWN0aW9uOiBcImxhbWJkYTpJbnZva2VGdW5jdGlvblwiLFxuICAgICAgcHJpbmNpcGFsOiBcImNsb3VkZnJvbnQuYW1hem9uYXdzLmNvbVwiLFxuICAgICAgZnVuY3Rpb25OYW1lOiBmdW5jdGlvblVybC5mdW5jdGlvbkFybixcbiAgICAgIHNvdXJjZUFybjogdGhpcy5kaXN0cmlidXRpb24uZGlzdHJpYnV0aW9uQXJuLFxuICAgICAgaW52b2tlZFZpYUZ1bmN0aW9uVXJsOiB0cnVlLFxuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBUaGUgYGFzc2V0UHJlZml4YCBwYXRoIHRoYXQgbmVlZHMgYSBiZWhhdmlvciBvZiBpdHMgb3duLCBvciBgXCJcImAgZm9yIG5vbmUuXG4gICAqXG4gICAqIEFuIGFic29sdXRlIHByZWZpeCBjb250cmlidXRlcyBpdHMgKnBhdGgqOiBcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tXCIgbmVlZHMgbm9cbiAgICogYmVoYXZpb3IsIGJ1dCBcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tL2NkblwiIGRvZXMsIGJlY2F1c2UgYG5leHQgYnVpbGRgXG4gICAqIGNvbXBpbGVzIGEgYC9jZG4vX25leHQvOnBhdGgrYCByZXdyaXRlIG9mIGl0cyBvd24gYW5kIGBuZXh0IHN0YXJ0YCBzZXJ2ZXNcbiAgICogZXZlcnkgYnVuZGxlIHVuZGVyIHRoYXQgcGF0aCDigJQgc28gYSBDRE4gZnJvbnRpbmcgdGhpcyBkaXN0cmlidXRpb24gdGhlcmUgaGFzXG4gICAqIHRvIGJlIGFuc3dlcmVkLiBBIHByZWZpeCBlcXVhbCB0byB0aGUgYGJhc2VQYXRoYCBwcmVmaXggaXMgZHJvcHBlZCDigJQgdGhhdCBpc1xuICAgKiB0aGUgTmV4dC5qcyBkZWZhdWx0IHdoZW4gYGJhc2VQYXRoYCBpcyBzZXQsIGFuZCBgX25leHQvc3RhdGljKmAgYWxyZWFkeVxuICAgKiByZXNvbHZlcyB1bmRlciBpdCwgc28gYWRkaW5nIGEgc2Vjb25kIGlkZW50aWNhbCBwYXR0ZXJuIHdvdWxkIG1ha2UgQ2xvdWRGcm9udFxuICAgKiByZWplY3QgdGhlIGRpc3RyaWJ1dGlvbi5cbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZUFzc2V0UHJlZml4KCk6IHN0cmluZyB7XG4gICAgY29uc3QgcHJlZml4ID0gYXNzZXRQcmVmaXhQYXRoKHRoaXMucHJvcHMuYXNzZXRQcmVmaXggPz8gXCJcIik7XG4gICAgcmV0dXJuIG5vcm1hbGl6ZUJhc2VQYXRoKHByZWZpeCkgPT09IHRoaXMuYmFzZVBhdGggPyBcIlwiIDogcHJlZml4O1xuICB9XG4gIC8qKlxuICAgKiBTZXJ2ZXMgYDxhc3NldFByZWZpeD4vX25leHQvc3RhdGljLypgIGZyb20gdGhlIHNhbWUgUzMgb2JqZWN0cyBhc1xuICAgKiBgX25leHQvc3RhdGljLypgLlxuICAgKlxuICAgKiBOZWVkZWQgYmVjYXVzZSBOZXh0LmpzIHB1dHMgYGFzc2V0UHJlZml4YCBpbiBmcm9udCBvZiBldmVyeSBidW5kbGUgVVJMIGl0XG4gICAqIGVtaXRzIHdoaWxlIHRoZSBvYmplY3RzIGtlZXAgdGhlaXIgYDxiYXNlUGF0aD4vX25leHQvc3RhdGljLy4uLmAga2V5cywgYW5kXG4gICAqIGBhc3NldFByZWZpeGAgc2l0cyBvbiB0b3Agb2YgYGJhc2VQYXRoYCByYXRoZXIgdGhhbiB1bmRlciBpdCwgc29cbiAgICogYGdldFBhdGhQYXR0ZXJuYCBpcyBkZWxpYmVyYXRlbHkgbm90IHVzZWQgaGVyZS4gV2l0aG91dCB0aGlzIGJlaGF2aW9yIHRoZVxuICAgKiByZXF1ZXN0IGZhbGxzIHRocm91Z2ggdG8gdGhlIGRlZmF1bHQgb25lLCByZWFjaGVzIHRoZSBjb21wdXRlIG9yaWdpbiwgYW5kXG4gICAqIDQwNHM6IHRoZSBkZXBsb3ltZW50IHBhY2thZ2UgY2FycmllcyBubyBgLm5leHQvc3RhdGljYCBkaXJlY3RvcnkgYXQgYWxsLlxuICAgKlxuICAgKiBBIHZpZXdlci1yZXF1ZXN0IGZ1bmN0aW9uIGRvZXMgdGhlIHJld3JpdGUgYmVjYXVzZSBhbiBTMyBvcmlnaW4ga2V5cyBvbiB0aGVcbiAgICogcmVxdWVzdCBVUkkgYW5kIGBvcmlnaW5QYXRoYCBjYW4gb25seSBwcmVwZW5kLiBUaGUgcHJlZml4IGlzIGEgc3ludGgtdGltZVxuICAgKiBsaXRlcmFsLCBzbyB0aGUgZnVuY3Rpb24gaXMgYSBmaXhlZC1sZW5ndGggc3RyaW5nIG9wZXJhdGlvbiByYXRoZXIgdGhhbiBhXG4gICAqIHBhcnNlLlxuICAgKi9cbiAgcHJpdmF0ZSBhZGRBc3NldFByZWZpeEJlaGF2aW9yKCkge1xuICAgIC8vIENsb3VkRnJvbnQgYWxsb3dzIG9uZSBmdW5jdGlvbiBwZXIgZXZlbnQgdHlwZSBwZXIgYmVoYXZpb3IsIHNvIGFuIG92ZXJyaWRlXG4gICAgLy8gdGhhdCBhbHJlYWR5IGNsYWltcyBWSUVXRVJfUkVRVUVTVCBvbiB0aGUgc3RhdGljIGJlaGF2aW9yIGNhbm5vdCBjb2V4aXN0XG4gICAgLy8gd2l0aCB0aGUgcmV3cml0ZSBiZWxvdyDigJQgdGhlIGRpc3RyaWJ1dGlvbiB3b3VsZCBzeW50aCBhbmQgdGhlbiBiZSByZWplY3RlZFxuICAgIC8vIGF0IGRlcGxveSwgbmFtaW5nIG5laXRoZXIuIFRocm93biBoZXJlIGluc3RlYWQsIHdoZXJlIGJvdGggaGFsdmVzIGFyZVxuICAgIC8vIGtub3duLlxuICAgIGNvbnN0IGNsYWltZWQgPSAoXG4gICAgICB0aGlzLnN0YXRpY0JlaGF2aW9yT3B0aW9ucy5mdW5jdGlvbkFzc29jaWF0aW9ucyA/PyBbXVxuICAgICkuc29tZShcbiAgICAgIChhc3NvY2lhdGlvbikgPT5cbiAgICAgICAgYXNzb2NpYXRpb24uZXZlbnRUeXBlID09PSBGdW5jdGlvbkV2ZW50VHlwZS5WSUVXRVJfUkVRVUVTVCxcbiAgICApO1xuICAgIGlmIChjbGFpbWVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke0xPR19QUkVGSVh9IFxcYG92ZXJyaWRlcy5zdGF0aWNCZWhhdmlvck9wdGlvbnMuZnVuY3Rpb25Bc3NvY2lhdGlvbnNcXGAgYCArXG4gICAgICAgICAgYGFscmVhZHkgYXNzb2NpYXRlcyBhIENsb3VkRnJvbnQgZnVuY3Rpb24gd2l0aCBgICtcbiAgICAgICAgICBgJHtGdW5jdGlvbkV2ZW50VHlwZS5WSUVXRVJfUkVRVUVTVH0sIGJ1dCBzZXJ2aW5nIFxcYGFzc2V0UHJlZml4XFxgIGAgK1xuICAgICAgICAgIGAoXCIke3RoaXMuYXNzZXRQcmVmaXh9XCIpIG5lZWRzIHRoYXQgZXZlbnQgdHlwZSB0byByZXdyaXRlIHRoZSByZXF1ZXN0IGAgK1xuICAgICAgICAgIGBVUkkgdG8gdGhlIG9iamVjdCdzIGtleSwgYW5kIENsb3VkRnJvbnQgcGVybWl0cyBvbmx5IG9uZSBmdW5jdGlvbiBwZXIgYCArXG4gICAgICAgICAgYGV2ZW50IHR5cGUgcGVyIGJlaGF2aW9yLiBFaXRoZXIgZHJvcCB0aGUgb3ZlcnJpZGUsIG9yIGZvbGQgaXRzIGxvZ2ljIGAgK1xuICAgICAgICAgIGBpbnRvIGEgc2luZ2xlIGZ1bmN0aW9uIGFuZCBzZXQgXFxgYXNzZXRQcmVmaXhcXGAgdG8gXCJcIiBzbyB0aGlzIGAgK1xuICAgICAgICAgIGBjb25zdHJ1Y3QgYWRkcyBubyBiZWhhdmlvciBvZiBpdHMgb3duLmAsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCByZXdyaXRlID0gbmV3IENsb3VkRnJvbnRGdW5jdGlvbih0aGlzLCBcIkFzc2V0UHJlZml4Rm5cIiwge1xuICAgICAgY29tbWVudDogdGhpcy5nZXRDb21tZW50KFxuICAgICAgICBcIk5leHRKUyBhc3NldFByZWZpeCByZXdyaXRlXCIsXG4gICAgICAgIFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICksXG4gICAgICBjb2RlOiBGdW5jdGlvbkNvZGUuZnJvbUlubGluZShgXG4gICAgICAgIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQpIHtcbiAgICAgICAgICB2YXIgcmVxdWVzdCA9IGV2ZW50LnJlcXVlc3Q7XG4gICAgICAgICAgcmVxdWVzdC51cmkgPSAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAgdGhpcy5iYXNlUGF0aCA/IGAvJHt0aGlzLmJhc2VQYXRofWAgOiBcIlwiLFxuICAgICAgICAgICl9ICsgcmVxdWVzdC51cmkuc2xpY2UoJHt0aGlzLmFzc2V0UHJlZml4Lmxlbmd0aH0pO1xuICAgICAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgICAgICB9XG4gICAgICAgIGApLFxuICAgIH0pO1xuICAgIHRoaXMuZGlzdHJpYnV0aW9uLmFkZEJlaGF2aW9yKFxuICAgICAgYCR7dGhpcy5hc3NldFByZWZpeH0vX25leHQvc3RhdGljKmAsXG4gICAgICB0aGlzLnN0YXRpY09yaWdpbixcbiAgICAgIHtcbiAgICAgICAgLi4udGhpcy5zdGF0aWNCZWhhdmlvck9wdGlvbnMsXG4gICAgICAgIGZ1bmN0aW9uQXNzb2NpYXRpb25zOiBbXG4gICAgICAgICAgLi4uKHRoaXMuc3RhdGljQmVoYXZpb3JPcHRpb25zLmZ1bmN0aW9uQXNzb2NpYXRpb25zID8/IFtdKSxcbiAgICAgICAgICB7IGV2ZW50VHlwZTogRnVuY3Rpb25FdmVudFR5cGUuVklFV0VSX1JFUVVFU1QsIGZ1bmN0aW9uOiByZXdyaXRlIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICk7XG4gIH1cbiAgcHJpdmF0ZSBhZGRTdGF0aWNCZWhhdmlvcnMoKSB7XG4gICAgdGhpcy5kaXN0cmlidXRpb24uYWRkQmVoYXZpb3IoXG4gICAgICB0aGlzLmdldFBhdGhQYXR0ZXJuKFwiX25leHQvc3RhdGljKlwiKSxcbiAgICAgIHRoaXMuc3RhdGljT3JpZ2luLFxuICAgICAgdGhpcy5zdGF0aWNCZWhhdmlvck9wdGlvbnMsXG4gICAgKTtcbiAgICBpZiAodGhpcy5hc3NldFByZWZpeCkge1xuICAgICAgdGhpcy5hZGRBc3NldFByZWZpeEJlaGF2aW9yKCk7XG4gICAgfVxuICAgIGNvbnN0IHB1YmxpY1BhdGhQYXR0ZXJucyA9IHRoaXMucHVibGljUGF0aFBhdHRlcm5zKCk7XG4gICAgdGhpcy5hc3NlcnRCZWhhdmlvckJ1ZGdldChwdWJsaWNQYXRoUGF0dGVybnMubGVuZ3RoKTtcbiAgICB0aGlzLmFzc2VydE5vUHVibGljQ29sbGlzaW9ucyhwdWJsaWNQYXRoUGF0dGVybnMpO1xuICAgIGZvciAoY29uc3QgcGF0aFBhdHRlcm4gb2YgcHVibGljUGF0aFBhdHRlcm5zKSB7XG4gICAgICB0aGlzLmRpc3RyaWJ1dGlvbi5hZGRCZWhhdmlvcihcbiAgICAgICAgcGF0aFBhdHRlcm4sXG4gICAgICAgIHRoaXMuc3RhdGljT3JpZ2luLFxuICAgICAgICB0aGlzLnN0YXRpY0JlaGF2aW9yT3B0aW9ucyxcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBUaGUgYmVoYXZpb3IgcGF0aCBwYXR0ZXJuIGZvciBlYWNoIHRvcC1sZXZlbCBgcHVibGljL2AgZW50cnksIGZpbmFsIGZvcm06XG4gICAqIGAvKmAgZm9yIGEgZGlyZWN0b3J5IGFuZCB0aGUgYmFzZVBhdGggcHJlZml4IGJvdGggYXBwbGllZC5cbiAgICpcbiAgICogQW4gZW50cnkgd2hvc2UgbmFtZSBoYXMgbm8gY2hhcmFjdGVyIENsb3VkRnJvbnQgY2FuIHNwZWxsIGlzIGxlZnQgb3V0LCB3aXRoXG4gICAqIGEgd2FybmluZywgcmF0aGVyIHRoYW4gZ2l2ZW4gYSBwYXR0ZXJuIG9mIG5vdGhpbmcgYnV0IHdpbGRjYXJkcy4gYNGE0L7RgtC+L2AgaXNcbiAgICogYD8/Pz8/Pz8/LypgIOKAlCBhbnkgOC1ieXRlIGZpcnN0IHNlZ21lbnQg4oCUIGFuZCBwdWJsaWMvIGJlaGF2aW9ycyBhcmUgYWRkZWRcbiAgICogYWhlYWQgb2YgZXZlcnkgY29tcHV0ZSBiZWhhdmlvciwgc28gaXQgd291bGQgc2VuZCBgL3Byb2R1Y3RzLzQyYCBhbmRcbiAgICogYC9zZXR0aW5ncy8qYCB0byBTMywgd2hpY2ggYW5zd2VycyA0MDMuIExlYXZpbmcgdGhlIGVudHJ5IG91dCBjb3N0cyBpdHMgb3duXG4gICAqIGZpbGVzIGluc3RlYWQ6IHRob3NlIHJlcXVlc3RzIHJlYWNoIHRoZSBjb21wdXRlLCB3aGljaCBkb2VzIG5vdCBoYXZlIHRoZW0sXG4gICAqIGFuZCA0MDQuIE9uZSBsaXRlcmFsIGNoYXJhY3RlciBpcyBlbm91Z2ggdG8ga2VlcCBhIHBhdHRlcm4gbmFycm93IOKAlFxuICAgKiBgPz8/Pz8/Pz8uanBnYCBvbmx5IG1hdGNoZXMgYC5qcGdgIHJlcXVlc3RzIOKAlCBzbyBvbmx5IHRoZSBhbGwtd2lsZGNhcmQgb25lc1xuICAgKiBnby5cbiAgICpcbiAgICogVGhlIGxlbmd0aCBsaW1pdCBpcyBjaGVja2VkIGhlcmUsIG9uIHRoZSBmaW5hbCBwYXR0ZXJuLCByYXRoZXIgdGhhbiBpblxuICAgKiB7QGxpbmsgdG9QYXRoUGF0dGVybn06IHRoZSBgLypgIGFuZCB0aGUgYmFzZVBhdGggY291bnQgYWdhaW5zdCBpdCB0b28sIGFuZCBhXG4gICAqIHBhdHRlcm4gdGhhdCBwYXNzZWQgd2l0aG91dCB0aGVtIGZhaWxlZCBhdCBkZXBsb3kgaW5zdGVhZC5cbiAgICovXG4gIHByaXZhdGUgcHVibGljUGF0aFBhdHRlcm5zKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBwYXR0ZXJuczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCB1bm1hdGNoYWJsZTogc3RyaW5nW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHB1YmxpY0ZpbGUgb2YgdGhpcy5wcm9wcy5wdWJsaWNEaXJFbnRyaWVzKSB7XG4gICAgICBjb25zdCBuYW1lID0gdG9QYXRoUGF0dGVybihwdWJsaWNGaWxlLm5hbWUpO1xuICAgICAgaWYgKCEvW14/Ki9dLy50ZXN0KG5hbWUpKSB7XG4gICAgICAgIHVubWF0Y2hhYmxlLnB1c2goYFwiJHtwdWJsaWNGaWxlLm5hbWV9XCJgKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBwYXRoUGF0dGVybiA9IHRoaXMuZ2V0UGF0aFBhdHRlcm4oXG4gICAgICAgIHB1YmxpY0ZpbGUuaXNEaXJlY3RvcnkgPyBgJHtuYW1lfS8qYCA6IG5hbWUsXG4gICAgICApO1xuICAgICAgaWYgKHBhdGhQYXR0ZXJuLmxlbmd0aCA+IE1BWF9QQVRIX1BBVFRFUk5fTEVOR1RIKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVGhlIHB1YmxpYy8gZW50cnkgXCIke3B1YmxpY0ZpbGUubmFtZX1cIiBuZWVkcyBhIGAgK1xuICAgICAgICAgICAgYCR7cGF0aFBhdHRlcm4ubGVuZ3RofS1jaGFyYWN0ZXIgQ2xvdWRGcm9udCBwYXRoIHBhdHRlcm4sIG92ZXIgYCArXG4gICAgICAgICAgICBgdGhlICR7TUFYX1BBVEhfUEFUVEVSTl9MRU5HVEh9LWNoYXJhY3RlciBgICtcbiAgICAgICAgICAgIFwibGltaXQuIFJlbmFtZSBpdCwgb3IgbW92ZSBpdCBpbnRvIGEgc3ViZGlyZWN0b3J5IG9mIHB1YmxpYy8gd2hvc2UgXCIgK1xuICAgICAgICAgICAgXCJvd24gbmFtZSBpcyBzaG9ydCBlbm91Z2guIFNlZSBcIiArXG4gICAgICAgICAgICBcImh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZEZyb250L2xhdGVzdC9EZXZlbG9wZXJHdWlkZS9Eb3dubG9hZERpc3RWYWx1ZXNDYWNoZUJlaGF2aW9yLmh0bWwjRG93bmxvYWREaXN0VmFsdWVzUGF0aFBhdHRlcm5cIixcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHBhdHRlcm5zLnB1c2gocGF0aFBhdHRlcm4pO1xuICAgIH1cbiAgICBpZiAodW5tYXRjaGFibGUubGVuZ3RoID4gMCkge1xuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkV2FybmluZyhcbiAgICAgICAgYCR7TE9HX1BSRUZJWH0gVGhlc2UgdG9wLWxldmVsIHB1YmxpYy8gZW50cmllcyBoYXZlIG5vIGNoYXJhY3RlciBhIGAgK1xuICAgICAgICAgIFwiQ2xvdWRGcm9udCBwYXRoIHBhdHRlcm4gY2FuIHNwZWxsLCBzbyB0aGVpciBwYXR0ZXJuIHdvdWxkIGJlIFwiICtcbiAgICAgICAgICBcIndpbGRjYXJkcyBhbG9uZSBhbmQgd291bGQgY2FwdHVyZSBldmVyeSBhcHAgcm91dGUgb2YgdGhlIHNhbWUgXCIgK1xuICAgICAgICAgIGBsZW5ndGguIFRoZXkgZ2V0IG5vIGJlaGF2aW9yLCBzbyB0aGVpciByZXF1ZXN0cyByZWFjaCB0aGUgc2VydmVyLCBgICtcbiAgICAgICAgICBgd2hpY2ggcmVhZHMgdGhlbSBmcm9tIFMzIGluc3RlYWQ6ICR7dW5tYXRjaGFibGUuam9pbihcIiwgXCIpfS4gVG8gc2VydmUgYCArXG4gICAgICAgICAgXCJ0aGVtIGZyb20gUzMgZGlyZWN0bHksIHJlbmFtZSB0aGVtLCBvciBtb3ZlIHRoZW0gaW50byBhIHB1YmxpYy8gXCIgK1xuICAgICAgICAgIFwic3ViZGlyZWN0b3J5IHdob3NlIG5hbWUgaGFzIGF0IGxlYXN0IG9uZSBBU0NJSSBsZXR0ZXIgb3IgZGlnaXQuXCIsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcGF0dGVybnM7XG4gIH1cbiAgLyoqXG4gICAqIFJlZnVzZSBhIGdyb3VwIGJlaGF2aW9yIHRoYXQgYSBgcHVibGljL2AgYmVoYXZpb3Igd291bGQgbWFrZSB1bnJlYWNoYWJsZS5cbiAgICpcbiAgICogYHB1YmxpYy9gIGJlaGF2aW9ycyBhcmUgYWRkZWQgZmlyc3QsIGFuZCBDbG91ZEZyb250IHN0b3BzIGF0IHRoZSBmaXJzdCBtYXRjaCxcbiAgICogc28gdHdvIGNhc2VzIHNlbmQgYSBncm91cCdzIHJvdXRlIHRvIFMzIGluc3RlYWQgb2YgaXRzIGZ1bmN0aW9uIOKAlCB3aGljaCBpc1xuICAgKiB3aHkgdGhpcyBpcyBjaGVja2VkIGF0IHN5bnRoLCB3aGVyZSBib3RoIHNpZGVzIGFyZSBrbm93bjpcbiAgICogLSB0aGUgc2FtZSBwYXR0ZXJuIHR3aWNlOiBgcHVibGljL2RvY3MvYCBhbmQgYC9kb2NzLyoqYCBib3RoIGRlcGxveSBhc1xuICAgKiAgIGBkb2NzLypgLiBUaGUgc3ludGggc3VjY2VlZGVkIGFuZCBDbG91ZEZyb250IHJlamVjdGVkIHRoZSBkZXBsb3kuXG4gICAqIC0gYSBncm91cCBwYXR0ZXJuIHVuZGVyIGEgcHVibGljIGRpcmVjdG9yeTogYC9kb2NzL2d1aWRlLyoqYCBiZWhpbmRcbiAgICogICBgZG9jcy8qYCBkZXBsb3lzIGFuZCBuZXZlciBtYXRjaGVzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3NlcnROb1B1YmxpY0NvbGxpc2lvbnMocHVibGljUGF0aFBhdHRlcm5zOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IHB1YmxpY1JlZ2V4ZXMgPSBwdWJsaWNQYXRoUGF0dGVybnMubWFwKChwYXR0ZXJuKSA9PiAoe1xuICAgICAgcGF0dGVybixcbiAgICAgIHJlZ2V4OiBjbG91ZEZyb250UGF0dGVyblJlZ2V4KGAvJHtwYXR0ZXJuLnJlcGxhY2UoL15cXC8rLywgXCJcIil9YCksXG4gICAgfSkpO1xuICAgIGZvciAoY29uc3QgeyBncm91cCwgcm91dGUsIHBhdGhQYXR0ZXJuIH0gb2YgdGhpcy5mdW5jdGlvbkdyb3VwQmVoYXZpb3JzKCkpIHtcbiAgICAgIGNvbnN0IGR1cGxpY2F0ZSA9IHB1YmxpY1BhdGhQYXR0ZXJucy5pbmNsdWRlcyhwYXRoUGF0dGVybik7XG4gICAgICAvLyBNYXRjaGluZyB0aGUgZ3JvdXAgcGF0dGVybidzIG93biB0ZXh0IGlzIGVub3VnaDogaXRzIG9ubHkgd2lsZGNhcmQgaXMgYVxuICAgICAgLy8gdHJhaWxpbmcgYCpgLCBzbyBhIHB1YmxpYyBwYXR0ZXJuIHRoYXQgbWF0Y2hlcyB0aGUgdGV4dCB1cCB0byBhbmRcbiAgICAgIC8vIGluY2x1ZGluZyBpdCBtYXRjaGVzIGV2ZXJ5IFVSTCB0aGUgZ3JvdXAgcGF0dGVybiBkb2VzLlxuICAgICAgY29uc3Qgc2hhZG93ID0gZHVwbGljYXRlXG4gICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgIDogcHVibGljUmVnZXhlcy5maW5kKCh7IHJlZ2V4IH0pID0+XG4gICAgICAgICAgICByZWdleC50ZXN0KGAvJHtwYXRoUGF0dGVybi5yZXBsYWNlKC9eXFwvKy8sIFwiXCIpfWApLFxuICAgICAgICAgICk7XG4gICAgICBpZiAoIWR1cGxpY2F0ZSAmJiAhc2hhZG93KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtMT0dfUFJFRklYfSBcXGBmdW5jdGlvbkdyb3Vwc1xcYCBwYXR0ZXJuIFwiJHtyb3V0ZX1cIiAoZ3JvdXAgYCArXG4gICAgICAgICAgYFwiJHtncm91cC5uYW1lfVwiKSBgICtcbiAgICAgICAgICAoZHVwbGljYXRlXG4gICAgICAgICAgICA/IGBkZXBsb3lzIGFzIHRoZSBwYXRoIHBhdHRlcm4gXCIke3BhdGhQYXR0ZXJufVwiLCB3aGljaCBhIHRvcC1sZXZlbCBgICtcbiAgICAgICAgICAgICAgYHB1YmxpYy8gZW50cnkgYWxyZWFkeSB1c2VzIOKAlCBDbG91ZEZyb250IHJlamVjdHMgYSBkaXN0cmlidXRpb24gYCArXG4gICAgICAgICAgICAgIGB3aXRoIHR3byBiZWhhdmlvcnMgb24gb25lIHBhdGggcGF0dGVybi4gYFxuICAgICAgICAgICAgOiBgZGVwbG95cyBhcyBcIiR7cGF0aFBhdHRlcm59XCIsIGJ1dCB0aGUgdG9wLWxldmVsIHB1YmxpYy8gZW50cnkgYCArXG4gICAgICAgICAgICAgIGBiZWhpbmQgXCIke3NoYWRvdyEucGF0dGVybn1cIiBpcyBtYXRjaGVkIGZpcnN0IGFuZCBzZW5kcyBldmVyeSBgICtcbiAgICAgICAgICAgICAgYHN1Y2ggcmVxdWVzdCB0byBTMywgc28gdGhlIGdyb3VwJ3MgZnVuY3Rpb24gd291bGQgbmV2ZXIgc2VlIGAgK1xuICAgICAgICAgICAgICBgdGhlbS4gYCkgK1xuICAgICAgICAgIGBNb3ZlIHRob3NlIHB1YmxpYy8gZmlsZXMgdW5kZXIgYSBkaXJlY3Rvcnkgbm8gcm91dGUgdXNlcywgb3IgYCArXG4gICAgICAgICAgYGdyb3VwIGEgZGlmZmVyZW50IHBhdGguYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBDbG91ZEZyb250IGhhcyBhIHBlci1kaXN0cmlidXRpb24gY2FjaGUgYmVoYXZpb3IgcXVvdGEsIGNvdW50aW5nIHRoZSBkZWZhdWx0XG4gICAqIG9uZSDigJQgNzUgdW5sZXNzIHJhaXNlZCwgYW5kIGBtYXhDYWNoZUJlaGF2aW9yc2Agc2F5cyB3aGljaCDigJQgYW5kIHRoZXJlIGFyZVxuICAgKiB0aHJlZSB0aGluZ3MgY29tcGV0aW5nIGZvciBpdDogYHB1YmxpYy9gIGVudHJpZXMsIGZ1bmN0aW9uIGdyb3VwcywgYW5kXG4gICAqIGNkay1uZXh0anMncyBvd24gZml4ZWQgc2V0LlxuICAgKiBDaGVja2VkIGluIG9uZSBwbGFjZSBzbyB0aGUgZXJyb3IgY2FuIHNheSB3aGljaCB0byBjdXQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkRnJvbnQvbGF0ZXN0L0RldmVsb3Blckd1aWRlL2Nsb3VkZnJvbnQtbGltaXRzLmh0bWwjbGltaXRzLXdlYi1kaXN0cmlidXRpb25zXG4gICAqL1xuICBwcml2YXRlIGFzc2VydEJlaGF2aW9yQnVkZ2V0KHB1YmxpY1BhdHRlcm5zOiBudW1iZXIpIHtcbiAgICBjb25zdCBsaW1pdCA9IHRoaXMucHJvcHMubWF4Q2FjaGVCZWhhdmlvcnMgPz8gREVGQVVMVF9NQVhfQ0FDSEVfQkVIQVZJT1JTO1xuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQobGltaXQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGdyb3VwUGF0dGVybnMgPSB0aGlzLmZ1bmN0aW9uR3JvdXBCZWhhdmlvcnMoKS5sZW5ndGg7XG4gICAgLy8gVGhlIGRlZmF1bHQgYmVoYXZpb3IsIGBfbmV4dC9pbWFnZSpgLCBgX25leHQvc3RhdGljKmAsIHBsdXMg4oCUIHdpdGggYVxuICAgIC8vIGJhc2VQYXRoIOKAlCB0aGUgdHdvIHRoYXQgc3RhbmQgaW4gZm9yIHRoZSBkZWZhdWx0IGJlaGF2aW9yJ3MgY292ZXJhZ2UsIGFuZFxuICAgIC8vIOKAlCB3aXRoIGEgcGF0aC1zdHlsZSBhc3NldFByZWZpeCDigJQgdGhlIG9uZSB0aGF0IHNlcnZlcyBidW5kbGVzIHVuZGVyIGl0LlxuICAgIC8vIGB0aGlzLmJhc2VQYXRoYCwgbm90IHRoZSByYXcgcHJvcDogYGJhc2VQYXRoOiBcIi9cImAgbm9ybWFsaXplcyB0byBgXCJcImAgYW5kXG4gICAgLy8gYWRkcyBubyBiZWhhdmlvcnMsIHNvIGNvdW50aW5nIGl0IGFkZGVkIDIgdG8gdGhlIHRvdGFsIGFuZCBjb3VsZCB0aHJvd1xuICAgIC8vIFwib3ZlciB0aGUgbGltaXRcIiBvbiBhbiBhcHAgdGhhdCBpcyB1bmRlciBpdC5cbiAgICBjb25zdCBmaXhlZCA9IDMgKyAodGhpcy5iYXNlUGF0aCA/IDIgOiAwKSArICh0aGlzLmFzc2V0UHJlZml4ID8gMSA6IDApO1xuICAgIGNvbnN0IHRvdGFsID0gZml4ZWQgKyBwdWJsaWNQYXR0ZXJucyArIGdyb3VwUGF0dGVybnM7XG4gICAgaWYgKHRvdGFsIDw9IGxpbWl0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHBhcnRzID0gW1xuICAgICAgYCR7Zml4ZWR9IHVzZWQgYnkgY2RrLW5leHRqcyBpdHNlbGZgLFxuICAgICAgYCR7cHVibGljUGF0dGVybnN9IGZvciB0b3AtbGV2ZWwgcHVibGljLyBlbnRyaWVzYCxcbiAgICBdO1xuICAgIGlmIChncm91cFBhdHRlcm5zKSB7XG4gICAgICBwYXJ0cy5wdXNoKGAke2dyb3VwUGF0dGVybnN9IGZvciBcXGBmdW5jdGlvbkdyb3Vwc1xcYCBwYXR0ZXJuc2ApO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgVGhpcyBOZXh0LmpzIGFwcCBuZWVkcyAke3RvdGFsfSBDbG91ZEZyb250IGNhY2hlIGJlaGF2aW9ycywgb3ZlciB0aGUgYCArXG4gICAgICAgIGBsaW1pdCBvZiAke2xpbWl0fSBwZXIgZGlzdHJpYnV0aW9uOiAke3BhcnRzLmpvaW4oXCIsIFwiKX0uIGAgK1xuICAgICAgICBgTW92ZSBwdWJsaWMvIGZpbGVzIGludG8gYSBzaW5nbGUgdG9wLWxldmVsIGRpcmVjdG9yeSAob25lIGJlaGF2aW9yIGAgK1xuICAgICAgICBgc2VydmVzIFxcYHN0YXRpYy8qXFxgKWAgK1xuICAgICAgICAoZ3JvdXBQYXR0ZXJuc1xuICAgICAgICAgID8gYCwgYW5kIHByZWZlciBvbmUgc3VidHJlZSBwYXR0ZXJuIHBlciBmdW5jdGlvbiBncm91cCBvdmVyIHNldmVyYWwgYCArXG4gICAgICAgICAgICBgZXhhY3QgcGF0aHNgXG4gICAgICAgICAgOiBgYCkgK1xuICAgICAgICBgLiBJZiB5b3VyIGFjY291bnQncyBxdW90YSBpcyBoaWdoZXIgdGhhbiAke2xpbWl0fSwgc2V0IGAgK1xuICAgICAgICBgXFxgbWF4Q2FjaGVCZWhhdmlvcnNcXGAgdG8gaXQuIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvY2xvdWRmcm9udC1saW1pdHMuaHRtbCNsaW1pdHMtd2ViLWRpc3RyaWJ1dGlvbnNgLFxuICAgICk7XG4gIH1cbiAgLyoqXG4gICAqIE9wdGlvbmFsbHkgcHJlcGVuZHMgYmFzZSBwYXRoIHRvIGdpdmVuIHBhdGggcGF0dGVybi5cbiAgICpcbiAgICogQSB0cmFpbGluZyBzbGFzaCBvbiBgcGF0aFBhdHRlcm5gIGlzIGxvYWQtYmVhcmluZyBhbmQgc3Vydml2ZXMsIHdoaWNoIGlzIHdoeVxuICAgKiB0aGlzIGNvbmNhdGVuYXRlcyByYXRoZXIgdGhhbiBnb2luZyB0aHJvdWdoIGBqb2luUGF0aGAuIFRoZSBidWlsZCdzXG4gICAqIGBmdW5jdGlvbkdyb3VwQmVoYXZpb3JzYCBob2xkIGJvdGggXCJwcmljaW5nXCIgYW5kIFwicHJpY2luZy9cIiBmb3IgYVxuICAgKiBgdHJhaWxpbmdTbGFzaGAgYXBwLCBhbmQgbm9ybWFsaXppbmcgdGhlIHNlY29uZCBvbmUgY29sbGFwc2VkIGl0IG9udG8gdGhlXG4gICAqIGZpcnN0OiBgYWRkQmVoYXZpb3JgIHdhc1xuICAgKiB0aGVuIGNhbGxlZCB0d2ljZSB3aXRoIGAvYmFzZS9wcmljaW5nYCwgd2hpY2ggQ2xvdWRGcm9udCByZWplY3RzIGF0IGRlcGxveVxuICAgKiAoXCJtb3JlIHRoYW4gb25lIGNhY2hlIGJlaGF2aW9yIGhhcyB0aGUgc2FtZSBwYXRoIHBhdHRlcm5cIiksIGFuZCB0aGVcbiAgICogY2Fub25pY2FsIGAvYmFzZS9wcmljaW5nL2Agd2FzIGxlZnQgdG8gdGhlIGAvYmFzZS8qYCBjYXRjaC1hbGwg4oCUIHRoZSBtaXNyb3V0ZVxuICAgKiB0aGUgc2Vjb25kIHBhdHRlcm4gZXhpc3RzIHRvIHByZXZlbnQuXG4gICAqL1xuICBwcml2YXRlIGdldFBhdGhQYXR0ZXJuKHBhdGhQYXR0ZXJuOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMuYmFzZVBhdGgpIHtcbiAgICAgIHJldHVybiBwYXRoUGF0dGVybjtcbiAgICB9XG4gICAgcmV0dXJuIGAvJHt0aGlzLmJhc2VQYXRofS8ke3BhdGhQYXR0ZXJuLnJlcGxhY2UoL15cXC8rLywgXCJcIil9YDtcbiAgfVxufVxuXG4vKipcbiAqIFdoZXRoZXIgYGR5bmFtaWNDYWNoZVBvbGljeVByb3BzYCB0dXJucyB0aGUgZHluYW1pYyBjYWNoZSBvZmYsIGJ5IGNhcHBpbmcgZXZlcnlcbiAqIFRUTCBhdCAwLlxuICpcbiAqIENsb3VkRnJvbnQgcmVqZWN0cyBhIHBvbGljeSB0aGF0IGNhY2hlcyBub3RoaW5nIGJ1dCBzdGlsbCBoYXMgYSBjYWNoZSBrZXlcbiAqIChcIkhlYWRlckJlaGF2aW9yIGlzIGludmFsaWQgZm9yIHBvbGljeSB3aXRoIGNhY2hpbmcgZGlzYWJsZWRcIiksIHNvIHN1Y2ggYVxuICogcG9saWN5IGhhcyB0byBkcm9wIHRoZSBrZXkuIFVudGlsIHRoZSBkZWZhdWx0IFRUTCBiZWNhbWUgMCB0aGlzIGNvdWxkIG5vdFxuICogY29tZSB1cDogQ0RLIHJhaXNlcyBgbWF4VHRsYCB0byBgZGVmYXVsdFR0bGAgd2hlbiBpdCBpcyBsb3dlciwgc28gYW4gb3ZlcnJpZGVcbiAqIG9mIGBtYXhUdGw6IDBgIHN5bnRoZXNpemVkIGFzIGEgZGF5IGFuZCBkZXBsb3llZC4gTm93IGl0IGlzIGhvbm9yZWQsIGFuZFxuICogd2l0aG91dCB0aGlzIHRoZSB1cGdyYWRlIGRlcGxveSB3b3VsZCBmYWlsLlxuICpcbiAqIFRoZSBUVExzIGFyZSByZXNvbHZlZCB0aGUgd2F5IENESyByZXNvbHZlcyB0aGVtOiBgZGVmYXVsdFR0bGAgcmFpc2VkIHRvXG4gKiBgbWluVHRsYCwgdGhlbiBgbWF4VHRsYCByYWlzZWQgdG8gYGRlZmF1bHRUdGxgLiBDaGVja2luZyBgbWF4VHRsYCBhbG9uZSBjYWxsZWRcbiAqIGB7IG1heFR0bDogMCwgZGVmYXVsdFR0bDogMWggfWAgZGlzYWJsZWQsIGRyb3BwZWQgdGhlIGtleSwgYW5kIENESyB0aGVuXG4gKiBzeW50aGVzaXplZCBhIHBvbGljeSB0aGF0IGNhY2hlcyBmb3IgYW4gaG91ciBrZXllZCBvbiBub3RoaW5nIOKAlCBvbmUgdmlld2VyJ3NcbiAqIHBhZ2Ugc2VydmVkIHRvIGV2ZXJ5IHZpZXdlci5cbiAqL1xuZnVuY3Rpb24gaXNDYWNoaW5nRGlzYWJsZWQocHJvcHM6IENhY2hlUG9saWN5UHJvcHMgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgY29uc3QgdHRscyA9IFtwcm9wcz8ubWF4VHRsLCBwcm9wcz8uZGVmYXVsdFR0bCwgcHJvcHM/Lm1pblR0bF07XG4gIGlmIChwcm9wcz8ubWF4VHRsID09PSB1bmRlZmluZWQpIHJldHVybiBmYWxzZTsgLy8gQ0RLJ3MgZGVmYXVsdCBpcyBhIHllYXJcbiAgcmV0dXJuIHR0bHMuZXZlcnkoXG4gICAgKHR0bCkgPT5cbiAgICAgIHR0bCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAoIVRva2VuLmlzVW5yZXNvbHZlZCh0dGwudG9TdHJpbmcoKSkgJiYgdHRsLnRvU2Vjb25kcygpID09PSAwKSxcbiAgKTtcbn1cblxuLyoqIFRoZSBjYWNoZS1rZXkgaGFsZiBvZiB7QGxpbmsgQ2FjaGVQb2xpY3lQcm9wc30uICovXG5pbnRlcmZhY2UgQ2FjaGVLZXlQcm9wcyB7XG4gIHJlYWRvbmx5IHF1ZXJ5U3RyaW5nQmVoYXZpb3I6IENhY2hlUXVlcnlTdHJpbmdCZWhhdmlvcjtcbiAgcmVhZG9ubHkgaGVhZGVyQmVoYXZpb3I6IENhY2hlSGVhZGVyQmVoYXZpb3I7XG4gIHJlYWRvbmx5IGNvb2tpZUJlaGF2aW9yOiBDYWNoZUNvb2tpZUJlaGF2aW9yO1xuICByZWFkb25seSBlbmFibGVBY2NlcHRFbmNvZGluZ0Jyb3RsaTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZW5hYmxlQWNjZXB0RW5jb2RpbmdHemlwOiBib29sZWFuO1xufVxuXG4vKipcbiAqIFdoYXQgdGhlIGR5bmFtaWMgY2FjaGUgcG9saWN5IGtleXMgb246IGV2ZXJ5IHJlcXVlc3QgaW5wdXQgYSBOZXh0LmpzIHJlc3BvbnNlXG4gKiB2YXJpZXMgYnkuXG4gKi9cbmNvbnN0IERZTkFNSUNfQ0FDSEVfS0VZOiBDYWNoZUtleVByb3BzID0ge1xuICBxdWVyeVN0cmluZ0JlaGF2aW9yOiBDYWNoZVF1ZXJ5U3RyaW5nQmVoYXZpb3IuYWxsKCksXG4gIGhlYWRlckJlaGF2aW9yOiBDYWNoZUhlYWRlckJlaGF2aW9yLmFsbG93TGlzdChcbiAgICAvLyBOT1RFOiBDbG91ZEZyb250IEN1c3RvbSBDYWNoZSBQb2xpY2llcyBoYXZlIHNvZnQgbWF4IG9mIDEwIGhlYWRlcnNcbiAgICAvLyBjZGstbmV4dGpzIGluY2x1ZGVzIHRoZSBtb3N0IGVzc2VudGlhbCBoZWFkZXJzIGZvciBOZXh0LmpzIGZ1bmN0aW9uYWxpdHlcbiAgICAvLyBidXQgaXQncyByZWNvbW1lbmRlZCB0byByZXF1ZXN0IHF1b3RhIGluY3JlYXNlIHRvIGluY2x1ZGUgYWxsIGhlYWRlcnMgKGNvbW1lbnRlZCBvdXQgb25lcyBiZWxvdylcbiAgICAvLyBtb3JlIGhlcmU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZEZyb250L2xhdGVzdC9EZXZlbG9wZXJHdWlkZS9jbG91ZGZyb250LWxpbWl0cy5odG1sI2xpbWl0cy1wb2xpY2llc1xuICAgIFwiYWNjZXB0XCIsIC8vIGNvbnRlbnQgbmVnb3RpYXRpb24gKEhUTUwgdnMgUlNDIHBheWxvYWQpXG4gICAgXCJyc2NcIiwgLy8gUmVhY3QgU2VydmVyIENvbXBvbmVudHMgcmVxdWVzdHNcbiAgICBcIm5leHQtdXJsXCIsIC8vIE5leHQuanMgcm91dGluZ1xuICAgIFwibmV4dC1yb3V0ZXItc3RhdGUtdHJlZVwiLCAvLyBBcHAgUm91dGVyIG5hdmlnYXRpb24gc3RhdGVcbiAgICBcIm5leHQtcm91dGVyLXByZWZldGNoXCIsIC8vIHByZWZldGNoIGJlaGF2aW9yXG4gICAgXCJuZXh0LXJvdXRlci1zZWdtZW50LXByZWZldGNoXCIsIC8vIHNlZ21lbnQtbGV2ZWwgcHJlZmV0Y2hpbmdcbiAgICBcIngtcHJlcmVuZGVyLXJldmFsaWRhdGVcIiwgLy8gb24tZGVtYW5kIElTUiByZXZhbGlkYXRpb25cbiAgICBcIngtcHJlcmVuZGVyLWJ5cGFzc1wiLCAvLyBkcmFmdCBtb2RlXG4gICAgLy8gXCJ4LW5leHRqcy1zdGFsZS10aW1lXCIsIC8vIHN0YWxlLXdoaWxlLXJldmFsaWRhdGUgYmVoYXZpb3JcbiAgICAvLyBcIngtbmV4dC1jYWNoZS10YWctdG9rZW5cIiwgLy8gYXV0aCB0b2tlbiBmb3IgY2FjaGUgdGFncyAob25seSBuZWVkZWQgd2l0aCByZXZhbGlkYXRlVGFnIGF1dGgpXG4gICAgLy8gXCJ4LW5leHRqcy1wb3N0cG9uZWRcIiwgLy8gUGFydGlhbCBQcmVyZW5kZXJpbmcgKGV4cGVyaW1lbnRhbCBmZWF0dXJlKVxuICAgIC8vIFwieC1wcmVyZW5kZXItcmV2YWxpZGF0ZS1pZi1nZW5lcmF0ZWRcIiwgLy8gY29uZGl0aW9uYWwgcmV2YWxpZGF0aW9uIChuaWNoZSB1c2UgY2FzZSlcbiAgKSxcbiAgY29va2llQmVoYXZpb3I6IENhY2hlQ29va2llQmVoYXZpb3IuYWxsKCksXG4gIGVuYWJsZUFjY2VwdEVuY29kaW5nQnJvdGxpOiB0cnVlLFxuICBlbmFibGVBY2NlcHRFbmNvZGluZ0d6aXA6IHRydWUsXG59O1xuXG4vKipcbiAqIEEgY2FjaGUga2V5IG9mIG5vdGhpbmcsIGZvciBhIHBvbGljeSB0aGF0IGNhY2hlcyBub3RoaW5nLiBGb3J3YXJkaW5nIGlzXG4gKiB1bmFmZmVjdGVkOiB0aGUgZHluYW1pYyBvcmlnaW4gcmVxdWVzdCBwb2xpY3kgc2VuZHMgZXZlcnkgdmlld2VyIGhlYWRlcixcbiAqIGNvb2tpZSBhbmQgcXVlcnkgc3RyaW5nIHJlZ2FyZGxlc3MuXG4gKi9cbmNvbnN0IERJU0FCTEVEX0NBQ0hFX0tFWTogQ2FjaGVLZXlQcm9wcyA9IHtcbiAgcXVlcnlTdHJpbmdCZWhhdmlvcjogQ2FjaGVRdWVyeVN0cmluZ0JlaGF2aW9yLm5vbmUoKSxcbiAgaGVhZGVyQmVoYXZpb3I6IENhY2hlSGVhZGVyQmVoYXZpb3Iubm9uZSgpLFxuICBjb29raWVCZWhhdmlvcjogQ2FjaGVDb29raWVCZWhhdmlvci5ub25lKCksXG4gIGVuYWJsZUFjY2VwdEVuY29kaW5nQnJvdGxpOiBmYWxzZSxcbiAgZW5hYmxlQWNjZXB0RW5jb2RpbmdHemlwOiBmYWxzZSxcbn07XG5cbi8qKlxuICogQ2xvdWRGcm9udCdzIGRlZmF1bHQgXCJDYWNoZSBiZWhhdmlvcnMgcGVyIGRpc3RyaWJ1dGlvblwiIHF1b3RhLCB0aGUgZGVmYXVsdFxuICogYmVoYXZpb3IgaW5jbHVkZWQuIEFkanVzdGFibGUsIGhlbmNlIGBtYXhDYWNoZUJlaGF2aW9yc2AuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvY2xvdWRmcm9udC1saW1pdHMuaHRtbCNsaW1pdHMtd2ViLWRpc3RyaWJ1dGlvbnNcbiAqL1xuY29uc3QgREVGQVVMVF9NQVhfQ0FDSEVfQkVIQVZJT1JTID0gNzU7XG5cbi8qKlxuICogV2hldGhlciBgY2hhcmAgaXMgaW4gQ2xvdWRGcm9udCdzIHBhdGggcGF0dGVybiBhbHBoYWJldDogdGhlIGxpdGVyYWxzLCBwbHVzIHRoZVxuICogYCpgIGFuZCBgP2Agd2lsZGNhcmRzLiBObyBzcGFjZSwgbm8gYCVgLCBub3RoaW5nIG5vbi1BU0NJSS5cbiAqL1xuZnVuY3Rpb24gaXNQYXRoUGF0dGVybkNoYXIoY2hhcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBjaGFyID09PSBcIipcIiB8fCBjaGFyID09PSBcIj9cIiB8fCBQQVRIX1BBVFRFUk5fTElURVJBTC50ZXN0KGNoYXIpO1xufVxuLyoqIENsb3VkRnJvbnQncyBwYXRoIHBhdHRlcm4gbGVuZ3RoIGxpbWl0LiAqL1xuY29uc3QgTUFYX1BBVEhfUEFUVEVSTl9MRU5HVEggPSAyNTU7XG5cbi8qKlxuICogQSBgcHVibGljL2AgZW50cnkncyBuYW1lIGFzIGEgQ2xvdWRGcm9udCBwYXRoIHBhdHRlcm4uXG4gKlxuICogYHB1YmxpYy9oZWxsbyB3b3JsZC5qcGdgIGlzIGEgdmFsaWQgTmV4dC5qcyBhc3NldCDigJQgYG5leHQgc3RhcnRgIHNlcnZlcyBpdCwgYW5kXG4gKiBgbmV4dC9pbWFnZWAgcG9pbnRzIGF0IGl0IOKAlCBidXQgYSBzcGFjZSBjYW5ub3QgYXBwZWFyIGluIGEgcGF0aCBwYXR0ZXJuLCBzb1xuICogY2RrLW5leHRqcyB1c2VkIHRvIHRocm93IGF0IHN5bnRoIGFuZCB0aGUgYXBwIGNvdWxkIG5vdCBiZSBkZXBsb3llZCBhdCBhbGxcbiAqIChgbmV4dC1pbWFnZS1sZWdhY3kvdW5pY29kZWAsIHdob3NlIGBwdWJsaWMvYCBhbHNvIGhvbGRzIGDDpMO2w7zFocSNxZnDrS5wbmdgKS5cbiAqXG4gKiBDbG91ZEZyb250IFVSTC1kZWNvZGVzIHRoZSByZXF1ZXN0IHBhdGggYmVmb3JlIG1hdGNoaW5nIGl0LCBzbyB0aGUgcGF0dGVybiBpc1xuICogbWF0Y2hlZCBhZ2FpbnN0IGBoZWxsbyB3b3JsZC5qcGdgLCBub3QgdGhlIGAvaGVsbG8lMjB3b3JsZC5qcGdgIG9uIHRoZSB3aXJlLlxuICogRWFjaCBjaGFyYWN0ZXIgb3V0c2lkZSB0aGUgYWxwaGFiZXQgaXMgcmVwbGFjZWQgYnkgb25lIGA/YCBwZXIgYnl0ZSBvZiBpdHNcbiAqIFVURi04IGVuY29kaW5nLCBiZWNhdXNlIHRoYXQgaXMgd2hhdCBgP2AgbWF0Y2hlczogYGhlbGxvP3dvcmxkLmpwZ2AgZm9yIHRoZVxuICogc3BhY2UsIGFuZCB0d28gYD9gIGZvciBlYWNoIGNoYXJhY3RlciBvZiBgw6TDtsO8xaHEjcWZw60ucG5nYC4gTWVhc3VyZWQgYWdhaW5zdCBhXG4gKiBkZXBsb3llZCBkaXN0cmlidXRpb247IGEgYD9gIHBlciAqcGVyY2VudC1lbmNvZGVkKiBjaGFyYWN0ZXIgKGBoZWxsbz8/P3dvcmxkYClcbiAqIHN5bnRoZXNpemVzIGZpbmUgYW5kIG5ldmVyIG1hdGNoZXMuIEEgYCpgIHdvdWxkIGJlIHNob3J0ZXIgYW5kIG11Y2ggd2lkZXI6XG4gKiBgw6TDtsO8xaHEjcWZw60ucG5nYCB3b3VsZCBiZWNvbWUgYCoucG5nYCwgd2hpY2ggd291bGQgcHVsbCBldmVyeSBgLnBuZ2AgcmVxdWVzdCBpblxuICogdGhlIGFwcCBvbnRvIHRoZSBzdGF0aWMgb3JpZ2luLlxuICovXG5mdW5jdGlvbiB0b1BhdGhQYXR0ZXJuKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBbLi4ubmFtZV1cbiAgICAubWFwKChjaGFyKSA9PlxuICAgICAgaXNQYXRoUGF0dGVybkNoYXIoY2hhcilcbiAgICAgICAgPyBjaGFyXG4gICAgICAgIDogXCI/XCIucmVwZWF0KEJ1ZmZlci5ieXRlTGVuZ3RoKGNoYXIsIFwidXRmOFwiKSksXG4gICAgKVxuICAgIC5qb2luKFwiXCIpO1xufVxuIl19