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
@@ -0,0 +1,852 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeBuildOutputs = writeBuildOutputs;
4
+ exports.buildAdapterManifest = buildAdapterManifest;
5
+ /* eslint-disable import/no-extraneous-dependencies */
6
+ const node_fs_1 = require("node:fs");
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_module_1 = require("node:module");
9
+ const node_path_1 = require("node:path");
10
+ const function_groups_1 = require("./function-groups");
11
+ const constants_1 = require("../constants");
12
+ const manifest_1 = require("../runtime/manifest");
13
+ /**
14
+ * Env files `writeStandaloneDirectory` copies into the standalone tree and that
15
+ * `onBuildComplete` has no equivalent for. Dropping `output: "standalone"`
16
+ * silently drops these unless we stage them ourselves.
17
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/output
18
+ */
19
+ const ENV_FILES = [".env", ".env.production"];
20
+ /**
21
+ * `next` submodules the *runtime* requires that no app ever reaches, so
22
+ * `next build`'s own trace never covers them. They are required from the app's
23
+ * `next` rather than bundled, deliberately — see `src/runtime/next-modules.ts`
24
+ * — which makes staging their closure this module's job.
25
+ *
26
+ * `serve-static` is in every group: `serveStaticFile`
27
+ * (`src/runtime/static-files.ts`) serves prerendered and static results with it
28
+ * wherever they land.
29
+ */
30
+ const RUNTIME_NEXT_MODULES = ["next/dist/server/serve-static.js"];
31
+ /**
32
+ * next's image optimizer and the config helpers around it
33
+ * (`src/runtime/image.ts`), whose closure is what brings `sharp` in. Only the
34
+ * `default` group gets them: the edge sends every `/_next/image` request there.
35
+ */
36
+ const IMAGE_NEXT_MODULES = [
37
+ "next/dist/server/config-shared.js",
38
+ "next/dist/shared/lib/image-config.js",
39
+ "next/dist/server/image-optimizer.js",
40
+ ];
41
+ /**
42
+ * The file tracer `next build` itself uses, reached through the app's own `next`
43
+ * so that it is the version that matches the files being traced. Not a
44
+ * dependency of cdk-nextjs: bundling a second copy of `@vercel/nft` into the
45
+ * published adapter would add megabytes to every install to do the same job.
46
+ */
47
+ const NEXT_FILE_TRACER = "next/dist/compiled/@vercel/nft";
48
+ /**
49
+ * Build the manifest and staging plan, stage the files, and write the manifest.
50
+ * Called from `onBuildComplete`, which is the only place that holds the build
51
+ * outputs.
52
+ */
53
+ async function writeBuildOutputs(ctx, options = {}) {
54
+ const adapterDir = (0, node_path_1.join)(ctx.distDir, manifest_1.ADAPTER_DIR_NAME);
55
+ const manifestPath = (0, node_path_1.join)(adapterDir, manifest_1.MANIFEST_FILE_NAME);
56
+ const { manifest, groups } = buildAdapterManifest(ctx, options);
57
+ // Traced once, here: the trace is async, which is why it cannot happen inside
58
+ // `buildAdapterManifest`. `runtimeClosure` is merged into every group, and
59
+ // `imageClosure` into `default` only, the one group `/_next/image` reaches.
60
+ const runtimeClosure = new Map();
61
+ const imageClosure = new Map();
62
+ await addRuntimeNextClosure(ctx, runtimeClosure, imageClosure);
63
+ addRequiredServerFiles(ctx, runtimeClosure);
64
+ // A previous build's tree is never additive with this one's: a removed route
65
+ // leaves behind an entrypoint the manifest no longer mentions, a renamed chunk
66
+ // leaves dead bytes inside the 250 MB budget, and a regrouped build leaves a
67
+ // whole deployment root nothing deploys.
68
+ await (0, promises_1.rm)(adapterDir, { recursive: true, force: true });
69
+ const stagedGroups = [];
70
+ for (const group of groups) {
71
+ const groupStaging = merged(merged(group.staging, runtimeClosure), group.name === function_groups_1.DEFAULT_FUNCTION_GROUP ? imageClosure : new Map());
72
+ const path = (0, node_path_1.join)(adapterDir, ...group.dirName.split("/"));
73
+ await (0, promises_1.mkdir)(path, { recursive: true });
74
+ await stageFiles(groupStaging, path);
75
+ stagedGroups.push({ name: group.name, path, fileCount: groupStaging.size });
76
+ }
77
+ await (0, promises_1.writeFile)(manifestPath, JSON.stringify(manifest, null, 2));
78
+ return {
79
+ manifest,
80
+ groups,
81
+ adapterDir,
82
+ manifestPath,
83
+ stagedGroups,
84
+ };
85
+ }
86
+ /** Left wins, as everywhere else in this module: first writer of a key keeps it. */
87
+ function merged(base, additions) {
88
+ const result = new Map(base);
89
+ for (const [key, source] of additions) {
90
+ if (!result.has(key)) {
91
+ result.set(key, source);
92
+ }
93
+ }
94
+ return result;
95
+ }
96
+ /**
97
+ * The pure half of {@link writeBuildOutputs}: everything derived from the build
98
+ * outputs, with no writes. Split out so it can be unit tested against committed
99
+ * `onBuildComplete` fixtures.
100
+ *
101
+ * Throws on any non-Node output and on any staging key two outputs map to
102
+ * different content.
103
+ */
104
+ function buildAdapterManifest(ctx, options = {}) {
105
+ const { outputs, repoRoot } = ctx;
106
+ const basePath = ctx.config.basePath || "";
107
+ assertBuildCwd(ctx, options.buildCwd ?? process.cwd());
108
+ const invocable = [
109
+ ...outputs.pages,
110
+ ...outputs.pagesApi,
111
+ ...outputs.appPages,
112
+ ...outputs.appRoutes,
113
+ ...(outputs.middleware ? [outputs.middleware] : []),
114
+ ];
115
+ assertNodeRuntimes(invocable, outputs.middleware);
116
+ warnOnDroppedRouteConfig(invocable);
117
+ const staticFiles = collectStaticFiles(ctx);
118
+ const entrypoints = {};
119
+ for (const { outputs: group, type } of [
120
+ { outputs: outputs.pages, type: "page" },
121
+ { outputs: outputs.pagesApi, type: "page-api" },
122
+ { outputs: outputs.appPages, type: "app-page" },
123
+ { outputs: outputs.appRoutes, type: "app-route" },
124
+ ]) {
125
+ for (const output of group) {
126
+ addEntrypoint(entrypoints, repoRoot, output, type, basePath);
127
+ }
128
+ }
129
+ addPrerenderPathnames(entrypoints, outputs.prerenders, ctx.routing.dynamicRoutes, basePath, `${basePath}/_next/data/${ctx.buildId}/`);
130
+ const pathnames = sortedUnique([
131
+ ...Object.keys(entrypoints),
132
+ ...Object.keys(staticFiles),
133
+ ]);
134
+ const functionGroups = options.functionGroups ??
135
+ (0, function_groups_1.parseFunctionGroupsEnv)(process.env[function_groups_1.FUNCTION_GROUPS_ENV_VAR]);
136
+ // i18n is checked first: it rejects the combination outright, and running it
137
+ // after the assignment meant an i18n app got the assignment's "pattern matches
138
+ // no route" error instead — true, but about the wrong thing, since a localized
139
+ // template never matches an unlocalized pattern.
140
+ if (functionGroups) {
141
+ (0, function_groups_1.assertNoI18nSplitting)(ctx.config.i18n ?? null);
142
+ }
143
+ const assignment = functionGroups
144
+ ? (0, function_groups_1.assignRoutesToGroups)(functionGroups,
145
+ // Keyed on the file, not the output `id`: a Pages Router page and its
146
+ // `/_next/data/<buildId>/<page>.json` route are separate outputs with
147
+ // separate ids backed by one file, and only the page's template matches
148
+ // a group pattern.
149
+ Object.entries(entrypoints).map(([template, entrypoint]) => ({
150
+ template,
151
+ entrypointId: entrypoint.filePath,
152
+ type: entrypoint.type,
153
+ })), {
154
+ basePath: ctx.config.basePath || "",
155
+ buildId: ctx.buildId,
156
+ trailingSlash: ctx.config.trailingSlash === true,
157
+ routing: ctx.routing,
158
+ })
159
+ : undefined;
160
+ const manifest = {
161
+ version: manifest_1.ADAPTER_MANIFEST_VERSION,
162
+ buildId: ctx.buildId,
163
+ relativeProjectDir: toPosix((0, node_path_1.relative)(repoRoot, ctx.projectDir)),
164
+ config: {
165
+ basePath: ctx.config.basePath || "",
166
+ trailingSlash: ctx.config.trailingSlash === true,
167
+ assetPrefix: ctx.config.assetPrefix || "",
168
+ distDir: toPosix((0, node_path_1.relative)(ctx.projectDir, ctx.distDir)),
169
+ compress: ctx.config.compress !== false,
170
+ generateEtags: ctx.config.generateEtags !== false,
171
+ i18n: ctx.config.i18n ?? null,
172
+ deploymentId: (ctx.config.deploymentId ?? "").replace(/[^A-Za-z0-9_-]/g, "-"),
173
+ },
174
+ routing: ctx.routing,
175
+ pathnames,
176
+ entrypoints,
177
+ middleware: buildMiddleware(repoRoot, outputs.middleware),
178
+ staticFiles,
179
+ ...(assignment
180
+ ? {
181
+ groups: assignment.templates,
182
+ behaviors: assignment.behaviors,
183
+ functionGroups: functionGroups.map(({ name, routes }) => ({
184
+ name,
185
+ routes,
186
+ })),
187
+ }
188
+ : {}),
189
+ };
190
+ const groups = assignment
191
+ ? Object.entries(assignment.templates).map(([name, templates]) => ({
192
+ name,
193
+ dirName: (0, manifest_1.groupStagingDirName)(name),
194
+ staging: collectGroupStagingPlan(ctx, invocable, entrypoints, templates),
195
+ }))
196
+ : [
197
+ {
198
+ name: function_groups_1.DEFAULT_FUNCTION_GROUP,
199
+ dirName: (0, manifest_1.groupStagingDirName)(),
200
+ staging: servedStagingPlan(ctx, invocable),
201
+ },
202
+ ];
203
+ return { manifest, groups };
204
+ }
205
+ /**
206
+ * One group's slice of the staging plan: the assets of the outputs it owns, and
207
+ * nothing else.
208
+ *
209
+ * Middleware is in every group, not just the default one — it runs on every
210
+ * request wherever that request lands, so it is duplicated by design, as is the
211
+ * `next` closure the entrypoints share. The same goes for the static files the
212
+ * runtime serves itself (`404.html`, `favicon.ico.body`): any group can be asked
213
+ * for them. And so are the not-found and error pages: the runtime renders a
214
+ * 404 or a 500 with whichever of them the shared manifest names
215
+ * (`statusTargets` in `runtime/dispatch.ts`), in whichever group the
216
+ * request reached, so a group without them answered a URL under its own
217
+ * pattern that matches no route with "the deployment package is incomplete".
218
+ *
219
+ * Ownership is matched on the entrypoint's `filePath`, not its `id` or
220
+ * pathname: the manifest's entrypoints are keyed by *template*, an output may
221
+ * back several templates, and {@link addPrerenderPathnames} synthesizes
222
+ * entrypoints that carry the *prerender's* id, which no invocable output has (the
223
+ * root-params app: entrypoint `/en` with `id: "/en"` backed by the output
224
+ * `/[locale]`). The synthesized entrypoint's `filePath` is the owning output's.
225
+ */
226
+ function collectGroupStagingPlan(ctx, invocable, entrypoints, templates) {
227
+ const basePath = ctx.config.basePath || "";
228
+ const ownedEntrypoints = [
229
+ ...templates,
230
+ ...manifest_1.ERROR_PAGE_SUFFIXES.map((suffix) => `${basePath}${suffix}`),
231
+ ]
232
+ .map((template) => entrypoints[template])
233
+ .filter((entry) => entry !== undefined);
234
+ const ownedFiles = new Set(ownedEntrypoints.map((entry) => entry.filePath));
235
+ const middleware = ctx.outputs.middleware;
236
+ const owned = invocable.filter((output) => ownedFiles.has(toPosix((0, node_path_1.relative)(ctx.repoRoot, output.filePath))) ||
237
+ output === middleware);
238
+ return servedStagingPlan(ctx, owned);
239
+ }
240
+ /** {@link collectStagingPlan} for `outputs`, plus the files the runtime serves. */
241
+ function servedStagingPlan(ctx, outputs) {
242
+ const staging = collectStagingPlan(ctx, outputs);
243
+ stageServedStaticFiles(ctx, staging);
244
+ return staging;
245
+ }
246
+ /**
247
+ * Job 1: reject non-Node outputs, everywhere.
248
+ *
249
+ * `export const runtime = 'edge'` on a page or route handler lands in
250
+ * `appPages`/`appRoutes`/`pages`/`pagesApi` with `runtime: 'edge'`,
251
+ * `assets: {}`, and an `edgeRuntime` descriptor needing `globalThis._ENTRIES`
252
+ * and a sandbox. Guarding middleware alone would leave a silent failure mode
253
+ * for edge pages: an entrypoint we can't invoke and no assets to invoke it
254
+ * with.
255
+ */
256
+ function assertNodeRuntimes(invocable, middleware) {
257
+ const offending = invocable.filter((output) => output.runtime !== "nodejs");
258
+ if (offending.length === 0) {
259
+ return;
260
+ }
261
+ // Middleware is reported separately from routes. Its `sourcePage` is `/`, so
262
+ // folding it in with the routes produces the actively misleading advice to
263
+ // remove `export const runtime = "edge"` from the home page - which is where
264
+ // the edge runtime is not, and may not even exist.
265
+ const offendingMiddleware = middleware && offending.includes(middleware);
266
+ // `.rsc` variants share a `sourcePage` with their HTML sibling, so dedupe.
267
+ const routes = sortedUnique(offending
268
+ .filter((output) => output !== middleware)
269
+ .map((output) => `${output.sourcePage} (runtime: "${output.runtime}")`));
270
+ const reasons = [];
271
+ if (routes.length > 0) {
272
+ reasons.push(`cdk-nextjs cannot deploy routes built for the edge runtime. ` +
273
+ `Remove \`export const runtime = "edge"\` from:\n` +
274
+ routes.map((route) => ` - ${route}`).join("\n"));
275
+ }
276
+ if (offendingMiddleware) {
277
+ reasons.push(`cdk-nextjs cannot deploy middleware built for the edge runtime ` +
278
+ `(${middleware.filePath}, runtime: "${middleware.runtime}"). ` +
279
+ `Rename it to \`proxy.ts\` (Next.js 16 runs proxy on the Node ` +
280
+ `runtime), or keep \`middleware.ts\` and add ` +
281
+ `\`export const config = { runtime: "nodejs" }\` to it — ` +
282
+ `\`middleware.ts\` defaults to the edge runtime, but does not require it.`);
283
+ }
284
+ throw new Error(`${constants_1.LOG_PREFIX} ${reasons.join("\n")}\n` +
285
+ `The edge runtime is deprecated in Next.js: ` +
286
+ `https://nextjs.org/docs/messages/edge-runtime-deprecated`);
287
+ }
288
+ /**
289
+ * Warn on route config cdk-nextjs does not honor. An author who set these asked
290
+ * for something explicitly, so say so rather than ignoring it silently; never
291
+ * throw, because route-level `maxDuration` is valid Next.js.
292
+ *
293
+ * `NextjsBuild` runs `next build` with `stdio: "inherit"`, so this reaches the
294
+ * user's terminal. See the plan's "Decisions" for why neither is honored.
295
+ */
296
+ function warnOnDroppedRouteConfig(invocable) {
297
+ const dropped = {
298
+ maxDuration: [],
299
+ preferredRegion: [],
300
+ };
301
+ for (const output of invocable) {
302
+ if (output.config?.maxDuration !== undefined) {
303
+ dropped.maxDuration.push(output.sourcePage);
304
+ }
305
+ if (output.config?.preferredRegion !== undefined) {
306
+ dropped.preferredRegion.push(output.sourcePage);
307
+ }
308
+ }
309
+ const remedy = {
310
+ maxDuration: "Set the function timeout with the construct's `overrides` prop instead (e.g. `overrides: { nextjsFunctions: { functionProps: { timeout: Duration.seconds(30) } } }`); a Lambda timeout is per-function while `maxDuration` is per-route.",
311
+ preferredRegion: "Honoring it would require a multi-region deployment, which this construct does not model.",
312
+ };
313
+ for (const key of ["maxDuration", "preferredRegion"]) {
314
+ const routes = sortedUnique(dropped[key]);
315
+ if (routes.length === 0) {
316
+ continue;
317
+ }
318
+ console.warn(`${constants_1.LOG_PREFIX} \`${key}\` is not honored by cdk-nextjs. ` +
319
+ `${routes.length} route(s) set it, including: ${routes.slice(0, 5).join(", ")}` +
320
+ `${routes.length > 5 ? `, and ${routes.length - 5} more` : ""}. ` +
321
+ remedy[key]);
322
+ }
323
+ }
324
+ /**
325
+ * Jobs 2, 3 and 6: the deduped union of every shipped output's traced `assets`,
326
+ * plus each entrypoint file itself, plus the env files, with `assetsHashes` used
327
+ * as a conflict check.
328
+ *
329
+ * Dedup is by key: the traced `next` closure is merged into every output's
330
+ * `assets` (`getSharedNodeAssets` → `sharedNodeAssets`), so N outputs
331
+ * overwhelmingly repeat keys. What the hashes buy is detecting two outputs
332
+ * mapping the **same key to different content**, which is unpackageable into
333
+ * one Lambda — fail the build loudly rather than letting last-write-wins pick.
334
+ */
335
+ function collectStagingPlan(ctx, invocable) {
336
+ const { repoRoot } = ctx;
337
+ const staging = new Map();
338
+ const hashes = new Map();
339
+ const add = (key, source, hash) => {
340
+ assertStagingKey(key, source);
341
+ const existingHash = hashes.get(key);
342
+ if (hash !== undefined &&
343
+ existingHash !== undefined &&
344
+ existingHash !== hash) {
345
+ throw new Error(`${constants_1.LOG_PREFIX} Two build outputs map "${key}" to different content ` +
346
+ `(hashes ${existingHash} and ${hash}). One deployment package cannot ` +
347
+ `hold both. This usually means two Next.js projects in the same repo ` +
348
+ `write the same repo-root-relative path.`);
349
+ }
350
+ if (hash !== undefined) {
351
+ hashes.set(key, hash);
352
+ }
353
+ if (!staging.has(key)) {
354
+ staging.set(key, source);
355
+ }
356
+ };
357
+ for (const output of invocable) {
358
+ for (const [key, source] of Object.entries(output.assets)) {
359
+ add(key, source, output.assetsHashes[key]);
360
+ }
361
+ // The entrypoint's own file is deliberately absent from its `assets` — the
362
+ // NFT trace covers the closure it requires, not itself. `assetsHashes` does
363
+ // carry it (keyed the same way), which is also what pins the key format.
364
+ const entryKey = toPosix((0, node_path_1.relative)(repoRoot, output.filePath));
365
+ add(entryKey, output.filePath, output.assetsHashes[entryKey]);
366
+ }
367
+ // Job 2, second half: `writeStandaloneDirectory` filters `loadedEnvFiles` to
368
+ // exactly these two and copies them; `build-complete.js` has no env-file
369
+ // handling at all, so they are not in any `assets` map.
370
+ for (const envFile of ENV_FILES) {
371
+ const source = (0, node_path_1.join)(ctx.projectDir, envFile);
372
+ if ((0, node_fs_1.existsSync)(source)) {
373
+ add(toPosix((0, node_path_1.relative)(repoRoot, source)), source);
374
+ }
375
+ }
376
+ return staging;
377
+ }
378
+ /**
379
+ * Job 2, third part: the static files the *runtime* has to serve, and their
380
+ * sources.
381
+ *
382
+ * `outputs.staticFiles` mixes two populations with the same `STATIC_FILE` type:
383
+ *
384
+ * - **`<distDir>/static/**` and `public/**`** — uploaded to S3 by
385
+ * `NextjsStaticAssets`, and CloudFront / API Gateway answer them before the
386
+ * request ever reaches the compute. Not staged: `public/` alone can be
387
+ * hundreds of megabytes against a 250 MB unzipped Lambda cap, and it would be
388
+ * a second copy of bytes already in S3. `public/` is not in
389
+ * `outputs.staticFiles` at all — Next.js lists it only for `output: "export"`
390
+ * — and it is deliberately not added here: the container runtime lists it off
391
+ * disk at cold start instead, as `next start` does (`readPublicFiles` in
392
+ * `src/runtime/public-files.ts`), because only the disk knows what an app's
393
+ * `postbuild` wrote into it after this hook ran.
394
+ * - **everything else**, all of it under `<distDir>/server/` — `404.html`,
395
+ * `500.html`, `favicon.ico.body`, and fully-static Pages Router HTML. Nothing
396
+ * in front of the compute serves these, so they are staged. Bounded by route
397
+ * count and small.
398
+ *
399
+ * The pathname → key map is returned for *all* of them, because dispatch has to
400
+ * resolve a pathname to "static file, not a 404" either way; the runtime 404s if
401
+ * the file turns out not to be in the package, which is only reachable when the
402
+ * distribution is misrouted.
403
+ *
404
+ * Staging is {@link stageServedStaticFiles}, applied once per deployment root.
405
+ */
406
+ function collectStaticFiles(ctx) {
407
+ const { repoRoot } = ctx;
408
+ const basePath = ctx.config.basePath || "";
409
+ const staticFiles = new Map();
410
+ const pagesDir = (0, node_path_1.join)(ctx.distDir, "server", "pages") + node_path_1.sep;
411
+ for (const output of ctx.outputs.staticFiles) {
412
+ const key = toPosix((0, node_path_1.relative)(repoRoot, output.filePath));
413
+ const pathnames = routablePathnames(output.pathname, basePath, output.filePath.startsWith(pagesDir));
414
+ for (const pathname of pathnames) {
415
+ const existing = staticFiles.get(pathname);
416
+ if (existing !== undefined && existing !== key) {
417
+ throw new Error(`${constants_1.LOG_PREFIX} Two static files claim the pathname ` +
418
+ `"${pathname}" ("${existing}" and "${key}"). Dispatch cannot ` +
419
+ `choose between them.`);
420
+ }
421
+ staticFiles.set(pathname, key);
422
+ }
423
+ }
424
+ // Sorted because object keys keep insertion order, and a byte-stable
425
+ // `manifest.json` is what keeps it diffable and the CDK asset hash from
426
+ // churning.
427
+ return Object.fromEntries([...staticFiles].sort(([a], [b]) => (a < b ? -1 : 1)));
428
+ }
429
+ /**
430
+ * The pathnames an output answers, which for one shape is not the pathname
431
+ * `next build` reported.
432
+ *
433
+ * **A Pages Router home page arrives as `/index`.** The adapter hook derives every
434
+ * Pages pathname with `normalizePagePath(page)`, and `normalizePagePath("/")` is
435
+ * `"/index"` (`next/dist/shared/lib/page-path/normalize-page-path.js`) — for the
436
+ * `PAGES` output of an SSG or SSR home page and for the `STATIC_FILE` of a
437
+ * fully-static one alike. `/index` is not a URL anyone requests, and nothing else
438
+ * in the outputs carries `/` for that page, so without this the home page is in
439
+ * neither `manifest.pathnames` nor `manifest.entrypoints`/`staticFiles`, and every
440
+ * request to `/` 404s while every other page of the same app serves. Measured
441
+ * against next.js's `test/e2e/new-link-behavior` (`/` returned the built-in 404,
442
+ * the six other pages were fine) and `test/e2e/prerender-preview` (the one case
443
+ * that fetches `/` got the 404 page's HTML, the eight that hit API routes passed).
444
+ *
445
+ * Pages Router outputs only, which is what `fromPagesRouter` says. App Router
446
+ * reports its home page as `/` and only the RSC sibling as `/index.rsc`, so an
447
+ * App Router `/index` is `app/index/page.tsx` — a real route at `/index`, and
448
+ * mapping it to `/` made an app with both pages fail the build on a pathname
449
+ * collision, and an app with only the second serve it at `/`. The same goes for
450
+ * a `public/index` file.
451
+ *
452
+ * Both pathnames are registered. `/` because it is the real one; `/index` because
453
+ * next's own minimal mode — the mode our runtime runs in — accepts it, rewriting
454
+ * `req.url` and `x-matched-path` from `/index` to `/` before matching
455
+ * (`base-server.ts`, "in minimal mode"), so dropping it would be a divergence in
456
+ * the other direction.
457
+ *
458
+ * Unambiguous within the Pages Router despite the collision it looks like:
459
+ * `normalizePagePath("/index")` is `"/index/index"`, so a reported `/index` can
460
+ * only have come from the page `/`.
461
+ * The data route of the same page, `/_next/data/<buildId>/index.json`, and an App
462
+ * Router `/index.rsc` are both real URLs and are left alone by the exact match.
463
+ */
464
+ function routablePathnames(pathname, basePath, fromPagesRouter) {
465
+ if (!fromPagesRouter || pathname !== `${basePath}/index`) {
466
+ return [pathname];
467
+ }
468
+ // `basePath || "/"`, not `${basePath}/`: with `basePath: "/prod"` the home page
469
+ // is `/prod`, which is how the App Router fixtures report theirs.
470
+ return [basePath || "/", pathname];
471
+ }
472
+ /**
473
+ * Add the static files the *runtime* serves to a staging plan — the "everything
474
+ * else" population described on {@link collectStaticFiles}, all of it under
475
+ * `<distDir>/server/`.
476
+ *
477
+ * Separate from building the manifest's `staticFiles` map because the map is the
478
+ * same for every group while the staging is applied once per deployment root:
479
+ * any group can be asked for `/404`, so every group ships these.
480
+ */
481
+ function stageServedStaticFiles(ctx, staging) {
482
+ const { repoRoot, distDir } = ctx;
483
+ const clientStaticDir = (0, node_path_1.join)(distDir, "static") + node_path_1.sep;
484
+ for (const output of ctx.outputs.staticFiles) {
485
+ const servedByS3 = output.filePath.startsWith(clientStaticDir) ||
486
+ !output.filePath.startsWith(distDir + node_path_1.sep);
487
+ if (servedByS3) {
488
+ continue;
489
+ }
490
+ const key = toPosix((0, node_path_1.relative)(repoRoot, output.filePath));
491
+ assertStagingKey(key, output.filePath);
492
+ staging.set(key, output.filePath);
493
+ }
494
+ }
495
+ /**
496
+ * The invariant behind `manifest.relativeProjectDir`: `next build` must run from
497
+ * the project directory.
498
+ *
499
+ * Next inlines `relative(process.cwd(), projectDir)` into every entrypoint
500
+ * (`define-env.js`) and the built code resolves it against the *runtime*
501
+ * `process.cwd()`. Keeping build cwd and project dir equal makes that inlined
502
+ * value `""`, so the runtime only has to `chdir` to the staged project dir. A
503
+ * build run from elsewhere would inline a non-empty relative path — often one
504
+ * pointing outside the staging tree — and every entrypoint would fail to find
505
+ * `required-server-files.json` at runtime with no hint as to why.
506
+ */
507
+ function assertBuildCwd(ctx, buildCwd) {
508
+ const cwd = (0, node_path_1.resolve)(buildCwd);
509
+ if (cwd === (0, node_path_1.resolve)(ctx.projectDir)) {
510
+ return;
511
+ }
512
+ throw new Error(`${constants_1.LOG_PREFIX} \`next build\` must run from the Next.js project ` +
513
+ `directory. It ran from "${cwd}" with the project at ` +
514
+ `"${ctx.projectDir}". Next.js bakes the relative path between those two ` +
515
+ `into every built entrypoint, and cdk-nextjs cannot reproduce that layout ` +
516
+ `in the deployment package. Change directory first (\`cd ` +
517
+ `${(0, node_path_1.relative)(cwd, ctx.projectDir) || "."} && next build\`) instead of ` +
518
+ `passing the directory as an argument; in a monorepo, run the app's own ` +
519
+ `build script from its directory (e.g. \`pnpm --filter <app> build\`, ` +
520
+ `which runs in the package directory).`);
521
+ }
522
+ function addEntrypoint(entrypoints, repoRoot, output, type, basePath) {
523
+ const filePath = toPosix((0, node_path_1.relative)(repoRoot, output.filePath));
524
+ const pathnames = routablePathnames(output.pathname, basePath, type === "page");
525
+ for (const pathname of pathnames) {
526
+ const existing = entrypoints[pathname];
527
+ if (existing && existing.filePath !== filePath) {
528
+ throw new Error(`${constants_1.LOG_PREFIX} Two build outputs claim the pathname "${pathname}" ` +
529
+ `("${existing.filePath}" and "${filePath}"). Dispatch cannot choose ` +
530
+ `between them.`);
531
+ }
532
+ entrypoints[pathname] = { id: output.id, filePath, type };
533
+ }
534
+ }
535
+ /**
536
+ * Add the *prerender* pathnames that no invocable output claims and that routing
537
+ * cannot otherwise reach.
538
+ *
539
+ * `resolveRoutes` can only match a pathname present in `manifest.pathnames`, and
540
+ * for a dynamic match it returns the **template** it matched. Routes and static
541
+ * files cover most of that; two shapes they miss:
542
+ *
543
+ * 1. **Templates.** A request for `/_next/data/<buildId>/fr/blog/hello.json` only
544
+ * resolves if `/_next/data/<buildId>/fr/blog/[slug].json` is listed, and that
545
+ * pathname exists solely as a `prerenders` entry.
546
+ * 1b. **A static `getStaticProps` page's data route.** `/_next/data/<buildId>/gsp.json`
547
+ * has no template to match and no rule of its own: `next build` only emits a
548
+ * `dynamicRoutes` rule for a data route when the page is dynamic *or* the app has
549
+ * middleware (`build-complete.ts`, `needsMiddlewareResolveRoutes`, which is also
550
+ * what `routing.shouldNormalizeNextData` reports). Without middleware Next.js
551
+ * expects the platform to serve the data route as an output, by pathname — so a
552
+ * concrete data-route prerender is registered whatever the rules say. Missing it
553
+ * turned every client-side navigation into such a page into a full page load,
554
+ * because the router's `.json` fetch 404'd: measured against
555
+ * `test/e2e/no-page-props`. Only when no *ungated* rule matches, for the reason
556
+ * below — a dynamic page's `/…/blog/hello.json` must keep resolving to its
557
+ * `[slug].json` template, which is where `nxtPslug` comes from.
558
+ * 2. **Concrete pathnames whose dynamic route rule is gated.** A route whose params
559
+ * can never be filled at request time — root params are the case that produced
560
+ * this, `app/[locale]/page.tsx` with `generateStaticParams()` and no
561
+ * `app/layout.tsx` — gets its `dynamicRoutes` rule emitted with a draft-mode
562
+ * `has` on `__prerender_bypass`. Next.js is saying: invoke the function only in
563
+ * draft mode, and otherwise serve the prerender you were handed. Vercel's CDN
564
+ * does that from the output itself; we route the request to the owning
565
+ * entrypoint, which answers it out of the seeded cache. Without this, `/en` is a
566
+ * 404 while `next start` renders it — and so is every `.rsc`/`.segments`
567
+ * variant, which is why a client-side navigation into such an app never
568
+ * completes.
569
+ *
570
+ * A concrete pathname is added only when a gated rule matches it and no ungated
571
+ * one does — the set that would 404 today *and* that routing can still produce.
572
+ * Adding them unconditionally was measured to be actively wrong twice over:
573
+ * `/isr/1` resolves to itself rather than to `/isr/[id]`, losing the `nxtPid`
574
+ * query param the route needs, and pathnames no rule matches at all (a static
575
+ * route's `.segments/…` outputs, which `resolveRoutes` never asks for) are dead
576
+ * manifest weight. Matching mirrors `resolveRoutes`, which is case-insensitive by
577
+ * default.
578
+ *
579
+ * The owning entrypoint comes from `prerender.route`, which is the unprefixed and
580
+ * unlocalized source route (`/blog/[slug]`), hence the basePath-then-bare ladder.
581
+ * Locale variants of one page share a `filePath`, so any locale's entrypoint is
582
+ * the right target. An RSC or segment-prefetch pathname prefers the route's `.rsc`
583
+ * entrypoint, because that is the key `resolveRoutes` resolves such a request to.
584
+ */
585
+ function addPrerenderPathnames(entrypoints, prerenders, dynamicRoutes, basePath, dataRoutePrefix) {
586
+ const matchers = dynamicRoutes.map((route) => ({
587
+ regex: new RegExp(route.sourceRegex, "i"),
588
+ gated: Boolean(route.has?.length || route.missing?.length),
589
+ }));
590
+ const matchingRules = (pathname) => matchers.filter(({ regex }) => regex.test(pathname));
591
+ const onlyGatedRulesMatch = (pathname) => {
592
+ const matched = matchingRules(pathname);
593
+ return matched.length > 0 && matched.every(({ gated }) => gated);
594
+ };
595
+ /**
596
+ * Nothing reaches this pathname at request time: either no rule matches it or
597
+ * every rule that does is gated. The gated half is {@link onlyGatedRulesMatch};
598
+ * the "no rule at all" half only ever holds for a data route, because a page's
599
+ * own pathname is an output.
600
+ */
601
+ const nothingUngatedMatches = (pathname) => matchingRules(pathname).every(({ gated }) => gated);
602
+ const orphans = [];
603
+ for (const prerender of prerenders) {
604
+ const { pathname } = prerender;
605
+ if (entrypoints[pathname]) {
606
+ continue;
607
+ }
608
+ const isTemplate = pathname.includes("[");
609
+ const isDataRoute = pathname.startsWith(dataRoutePrefix) && pathname.endsWith(".json");
610
+ const reachable = isDataRoute
611
+ ? nothingUngatedMatches(pathname)
612
+ : onlyGatedRulesMatch(pathname);
613
+ if (!isTemplate && !reachable) {
614
+ continue;
615
+ }
616
+ const suffixes = pathname.endsWith(".rsc") ? [".rsc", ""] : [""];
617
+ const owner = suffixes
618
+ .flatMap((suffix) => [
619
+ `${basePath}${prerender.route}${suffix}`,
620
+ `${prerender.route}${suffix}`,
621
+ ])
622
+ .map((key) => entrypoints[key])
623
+ .find(Boolean);
624
+ if (!owner) {
625
+ orphans.push(`${pathname} (route: "${prerender.route}")`);
626
+ continue;
627
+ }
628
+ entrypoints[pathname] = {
629
+ id: prerender.id,
630
+ filePath: owner.filePath,
631
+ type: owner.type,
632
+ };
633
+ }
634
+ if (orphans.length > 0) {
635
+ // Warn rather than throw: an unmapped pathname degrades one URL shape to a
636
+ // 404, which is what would happen without this function at all. A throw
637
+ // would break the build outright on an output shape a future `next` minor
638
+ // might introduce.
639
+ console.warn(`${constants_1.LOG_PREFIX} ${orphans.length} prerender pathname(s) have no ` +
640
+ `matching route entrypoint and will 404: ` +
641
+ `${orphans.slice(0, 5).join(", ")}` +
642
+ `${orphans.length > 5 ? `, and ${orphans.length - 5} more` : ""}.`);
643
+ }
644
+ }
645
+ function buildMiddleware(repoRoot, middleware) {
646
+ if (!middleware) {
647
+ return null;
648
+ }
649
+ // `config.matchers` is deliberately not copied here: it arrives inside
650
+ // `ctx.routing.middlewareMatchers`, which `@next/routing` consumes directly.
651
+ return {
652
+ id: middleware.id,
653
+ filePath: toPosix((0, node_path_1.relative)(repoRoot, middleware.filePath)),
654
+ };
655
+ }
656
+ /**
657
+ * Copy the staging plan into `stagingDir`.
658
+ *
659
+ * **Symlinks are recreated as symlinks, not dereferenced**, which is what
660
+ * Next.js's own `copyTracedFiles` does (`next/dist/build/utils.js`: `readlink`
661
+ * then `symlink`, with a Windows junction fallback). Under pnpm a traced asset
662
+ * key is frequently a *directory* symlink into the store
663
+ * (`node_modules/.pnpm/next@…/node_modules/react` → `../../react@19.2.3/…`), so
664
+ * `copyFile` fails outright with `ENOTSUP`. Dereferencing instead would triple
665
+ * the tree — `examples/app-playground` measures 32 MB staged versus 96 MB with
666
+ * `du -shL`, against a 250 MB unzipped Lambda cap — because whole packages are
667
+ * reachable through several such links. The link targets are themselves staged
668
+ * keys, so relative links resolve inside the deployment root.
669
+ *
670
+ * Regular files are staged first so that a symlink whose path was already
671
+ * materialized as a real directory is skipped rather than clobbering it.
672
+ *
673
+ * Nothing may dereference them afterwards: the Functions zip keeps them as
674
+ * links (`zipDirectory`), and the Containers `COPY` does too.
675
+ */
676
+ /** Bounded so a large app doesn't exhaust file descriptors. */
677
+ const STAGING_CONCURRENCY = 32;
678
+ async function stageFiles(staging, stagingDir) {
679
+ const planned = [...staging];
680
+ // Links land by plan index, so the pass below creates them in the plan's
681
+ // order whatever order the workers finished in.
682
+ const links = new Array(planned.length);
683
+ let nextEntry = 0;
684
+ const worker = async () => {
685
+ while (nextEntry < planned.length) {
686
+ const index = nextEntry++;
687
+ const [key, source] = planned[index];
688
+ const linkTarget = await (0, promises_1.readlink)(source).catch(() => null);
689
+ if (linkTarget !== null) {
690
+ links[index] = [key, source, linkTarget];
691
+ continue;
692
+ }
693
+ const dest = (0, node_path_1.join)(stagingDir, key);
694
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(dest), { recursive: true });
695
+ await (0, promises_1.copyFile)(source, dest);
696
+ }
697
+ };
698
+ await Promise.all(Array.from({ length: Math.min(STAGING_CONCURRENCY, planned.length) }, worker));
699
+ for (const link of links) {
700
+ if (link === undefined) {
701
+ continue;
702
+ }
703
+ const [key, source, linkTarget] = link;
704
+ const dest = (0, node_path_1.join)(stagingDir, key);
705
+ if ((0, node_fs_1.existsSync)(dest)) {
706
+ // Already staged as real content by the pool above; the link would add
707
+ // nothing and would replace a directory we need.
708
+ continue;
709
+ }
710
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(dest), { recursive: true });
711
+ const resolved = (0, node_path_1.resolve)((0, node_path_1.dirname)(dest), linkTarget);
712
+ if (resolved === stagingDir || resolved.startsWith(stagingDir + node_path_1.sep)) {
713
+ await (0, promises_1.symlink)(linkTarget, dest);
714
+ }
715
+ else {
716
+ // Points outside the deployment root, so the link would dangle in Lambda.
717
+ // Absolute store paths are the realistic case here.
718
+ await (0, promises_1.cp)(source, dest, { recursive: true, dereference: true });
719
+ }
720
+ }
721
+ }
722
+ /**
723
+ * Adds {@link RUNTIME_NEXT_MODULES}, `@next/env`, and everything they require to
724
+ * `staging`, and {@link IMAGE_NEXT_MODULES} and theirs to `imageStaging`.
725
+ *
726
+ * Without this the deployment is complete for every route the app has and broken
727
+ * for `/_next/image`: the traced `assets` of a build output cover what the *app*
728
+ * reaches, and an app never reaches next's image optimizer, so
729
+ * `next/dist/server/image-optimizer.js` and its closure are simply absent and
730
+ * every image request 500s with a `MODULE_NOT_FOUND` from `nextModule`.
731
+ *
732
+ * Resolution is anchored inside `ctx.projectDir` for the same reason
733
+ * `useNextFrom` anchors there at runtime: it is the directory whose
734
+ * `node_modules` walk finds the app's `next`. A repo where that resolution fails
735
+ * is not a real `next build` — nothing else would have run — so it warns and
736
+ * continues rather than failing a build for a package it could not have needed.
737
+ * A missing *tracer* is different: `next` is right there and image optimization
738
+ * would silently 500 in production, so that throws.
739
+ */
740
+ async function addRuntimeNextClosure(ctx, staging, imageStaging) {
741
+ // The anchor file needn't exist; `createRequire` only reads its directory.
742
+ const nextRequire = (0, node_module_1.createRequire)((0, node_path_1.join)(ctx.projectDir, "cdk-nextjs-next-resolver.cjs"));
743
+ let entries;
744
+ let imageEntries;
745
+ try {
746
+ entries = RUNTIME_NEXT_MODULES.map((specifier) => nextRequire.resolve(specifier));
747
+ imageEntries = IMAGE_NEXT_MODULES.map((specifier) => nextRequire.resolve(specifier));
748
+ }
749
+ catch (cause) {
750
+ console.warn(`${constants_1.LOG_PREFIX} Could not resolve next's image optimizer from ` +
751
+ `"${ctx.projectDir}" (${cause.message}). Requests to ` +
752
+ `/_next/image will fail at runtime.`);
753
+ return;
754
+ }
755
+ // `loadEnvFiles` (runtime `next-modules.ts`) loads the staged env files with
756
+ // `@next/env`, which is `next`'s dependency, so resolved from `next`'s dir.
757
+ // An app never requires it, so no output's trace has it either.
758
+ const nextPackage = nextRequire.resolve("next/package.json");
759
+ try {
760
+ entries.push((0, node_module_1.createRequire)(nextPackage).resolve("@next/env"));
761
+ }
762
+ catch (cause) {
763
+ throw new Error(`${constants_1.LOG_PREFIX} Could not resolve "@next/env" from the app's \`next\`, ` +
764
+ `which the cdk-nextjs runtime uses to load .env files.`, { cause });
765
+ }
766
+ let nodeFileTrace;
767
+ try {
768
+ ({ nodeFileTrace } = nextRequire(NEXT_FILE_TRACER));
769
+ }
770
+ catch (cause) {
771
+ throw new Error(`${constants_1.LOG_PREFIX} Could not load "${NEXT_FILE_TRACER}", which cdk-nextjs uses ` +
772
+ `to stage the \`next\` files its image optimizer requires. This Next.js ` +
773
+ `version may have moved it; please open an issue.`, { cause });
774
+ }
775
+ const add = (fileList, target) => {
776
+ for (const traced of fileList) {
777
+ const key = toPosix(traced);
778
+ if (target.has(key)) {
779
+ continue;
780
+ }
781
+ const source = (0, node_path_1.join)(ctx.repoRoot, traced);
782
+ assertStagingKey(key, source);
783
+ target.set(key, source);
784
+ }
785
+ };
786
+ add((await nodeFileTrace(imageEntries, { base: ctx.repoRoot })).fileList, imageStaging);
787
+ const { fileList } = await nodeFileTrace(entries, { base: ctx.repoRoot });
788
+ // The trace starts from `@next/env`'s real path, so under pnpm it never
789
+ // passes through the `.pnpm/next@…/node_modules/@next/env` link that `next`
790
+ // resolves it by. Without the link, every request fails at cold start with
791
+ // "Cannot find module '@next/env'".
792
+ const nextEnvLink = (0, node_path_1.join)((0, node_path_1.dirname)(nextPackage), "..", "@next", "env");
793
+ if ((0, node_fs_1.lstatSync)(nextEnvLink, { throwIfNoEntry: false })?.isSymbolicLink()) {
794
+ // `resolve` returns real paths, so relative to the real repo root.
795
+ fileList.add((0, node_path_1.relative)((0, node_fs_1.realpathSync)(ctx.repoRoot), nextEnvLink));
796
+ }
797
+ add(fileList, staging);
798
+ }
799
+ /**
800
+ * Add `<distDir>/required-server-files.json` to a plan every group is merged with.
801
+ *
802
+ * It reaches a group otherwise only as a traced `asset` of some invocable output,
803
+ * which is not a guarantee: a group whose templates are all assigned elsewhere
804
+ * owns no outputs at all. That is reachable — a Pages-Router-only app whose every
805
+ * page falls under the configured `functionGroups` leaves the *default* group
806
+ * template-empty, and the default group is still what serves `/_next/image`, the
807
+ * static files, and the distribution's catch-all.
808
+ *
809
+ * Its absence is not a partial failure: `loadRuntime` probes for exactly this file
810
+ * before it will serve anything, and `image.ts` reads the image config out of it,
811
+ * so the whole root answers "the deployment package is incomplete". Cheap to make
812
+ * unconditional, so make it unconditional.
813
+ *
814
+ * Not traced like {@link RUNTIME_NEXT_MODULES}, because it is data rather than a
815
+ * module: nothing `require`s it, so no file tracer can find it.
816
+ *
817
+ * Absence is left to `loadRuntime`, which names the file and the layout contract
818
+ * it belongs to. `next build` always writes it, so there is no build-time error
819
+ * worth inventing here for a file this step does not own.
820
+ */
821
+ function addRequiredServerFiles(ctx, staging) {
822
+ const source = (0, node_path_1.join)(ctx.distDir, "required-server-files.json");
823
+ const key = toPosix((0, node_path_1.relative)(ctx.repoRoot, source));
824
+ if (staging.has(key) || !(0, node_fs_1.existsSync)(source)) {
825
+ return;
826
+ }
827
+ assertStagingKey(key, source);
828
+ staging.set(key, source);
829
+ }
830
+ /**
831
+ * Every staged path must land inside the staging tree and must not shadow the
832
+ * reserved directory cdk-nextjs copies its own runtime into at synth.
833
+ */
834
+ function assertStagingKey(key, source) {
835
+ if (key === "" || key.startsWith("/") || key.startsWith("..")) {
836
+ throw new Error(`${constants_1.LOG_PREFIX} Build output asset "${source}" resolves to the staging key ` +
837
+ `"${key}", which is outside the deployment root. Set ` +
838
+ `\`outputFileTracingRoot\` so all traced files live under one root.`);
839
+ }
840
+ if (key === manifest_1.RUNTIME_DIR_NAME || key.startsWith(`${manifest_1.RUNTIME_DIR_NAME}/`)) {
841
+ throw new Error(`${constants_1.LOG_PREFIX} Build output asset "${source}" resolves to the staging key ` +
842
+ `"${key}", but "${manifest_1.RUNTIME_DIR_NAME}/" is reserved for cdk-nextjs's own ` +
843
+ `runtime files.`);
844
+ }
845
+ }
846
+ function toPosix(path) {
847
+ return node_path_1.sep === "/" ? path : path.split(node_path_1.sep).join("/");
848
+ }
849
+ function sortedUnique(values) {
850
+ return [...new Set(values)].sort();
851
+ }
852
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtb3V0cHV0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL2J1aWxkLW91dHB1dHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFzS0EsOENBNENDO0FBd0JELG9EQWtJQztBQTVXRCxzREFBc0Q7QUFDdEQscUNBQThEO0FBQzlELCtDQVEwQjtBQUMxQiw2Q0FBNEM7QUFDNUMseUNBQWtFO0FBRWxFLHVEQU8yQjtBQUMzQiw0Q0FBMEM7QUFDMUMsa0RBVzZCO0FBbUI3Qjs7Ozs7R0FLRztBQUNILE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBTSxFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFFOUM7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7QUFFbEU7Ozs7R0FJRztBQUNILE1BQU0sa0JBQWtCLEdBQUc7SUFDekIsbUNBQW1DO0lBQ25DLHNDQUFzQztJQUN0QyxxQ0FBcUM7Q0FDdEMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxnQ0FBZ0MsQ0FBQztBQXVFMUQ7Ozs7R0FJRztBQUNJLEtBQUssVUFBVSxpQkFBaUIsQ0FDckMsR0FBeUIsRUFDekIsVUFBK0IsRUFBRTtJQUVqQyxNQUFNLFVBQVUsR0FBRyxJQUFBLGdCQUFJLEVBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSwyQkFBZ0IsQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sWUFBWSxHQUFHLElBQUEsZ0JBQUksRUFBQyxVQUFVLEVBQUUsNkJBQWtCLENBQUMsQ0FBQztJQUUxRCxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxHQUFHLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUVoRSw4RUFBOEU7SUFDOUUsMkVBQTJFO0lBQzNFLDRFQUE0RTtJQUM1RSxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUNqRCxNQUFNLFlB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QUFZO0lBQzNCLE9BQU8sZUFBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN4RCxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsTUFBZ0I7SUFDcEMsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5pbXBvcnQgeyBleGlzdHNTeW5jLCBsc3RhdFN5bmMsIHJlYWxwYXRoU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQge1xuICBjb3B5RmlsZSxcbiAgY3AsXG4gIG1rZGlyLFxuICByZWFkbGluayxcbiAgcm0sXG4gIHN5bWxpbmssXG4gIHdyaXRlRmlsZSxcbn0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4sIHJlbGF0aXZlLCByZXNvbHZlLCBzZXAgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBOZXh0QWRhcHRlciB9IGZyb20gXCJuZXh0XCI7XG5pbXBvcnQge1xuICBERUZBVUxUX0ZVTkNUSU9OX0dST1VQLFxuICBGVU5DVElPTl9HUk9VUFNfRU5WX1ZBUixcbiAgRnVuY3Rpb25Hcm91cFNwZWMsXG4gIGFzc2VydE5vSTE4blNwbGl0dGluZyxcbiAgYXNzaWduUm91dGVzVG9Hcm91cHMsXG4gIHBhcnNlRnVuY3Rpb25Hcm91cHNFbnYsXG59IGZyb20gXCIuL2Z1bmN0aW9uLWdyb3Vwc1wiO1xuaW1wb3J0IHsgTE9HX1BSRUZJWCB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIEFEQVBURVJfRElSX05BTUUsXG4gIEFEQVBURVJfTUFOSUZFU1RfVkVSU0lPTixcbiAgQWRhcHRlckVudHJ5cG9pbnQsXG4gIEFkYXB0ZXJFbnRyeXBvaW50VHlwZSxcbiAgQWRhcHRlck1hbmlmZXN0LFxuICBBZGFwdGVyTWlkZGxld2FyZSxcbiAgRVJST1JfUEFHRV9TVUZGSVhFUyxcbiAgTUFOSUZFU1RfRklMRV9OQU1FLFxuICBSVU5USU1FX0RJUl9OQU1FLFxuICBncm91cFN0YWdpbmdEaXJOYW1lLFxufSBmcm9tIFwiLi4vcnVudGltZS9tYW5pZmVzdFwiO1xuXG4vKipcbiAqIFRoZSBgb25CdWlsZENvbXBsZXRlYCBhcmd1bWVudC4gRGVyaXZlZCBmcm9tIHRoZSBgbmV4dGAgdHlwaW5ncyByYXRoZXIgdGhhblxuICogcmVzdGF0ZWQgc28gYSBgbmV4dGAgYnVtcCBzdXJmYWNlcyBhcyBhIGNvbXBpbGUgZXJyb3IgaGVyZS5cbiAqL1xuZXhwb3J0IHR5cGUgQnVpbGRDb21wbGV0ZUNvbnRleHQgPSBQYXJhbWV0ZXJzPFxuICBOb25OdWxsYWJsZTxOZXh0QWRhcHRlcltcIm9uQnVpbGRDb21wbGV0ZVwiXT5cbj5bMF07XG5cbnR5cGUgQWRhcHRlck91dHB1dHMgPSBCdWlsZENvbXBsZXRlQ29udGV4dFtcIm91dHB1dHNcIl07XG4vKiogQW55IG91dHB1dCB0aGF0IHdlIGludm9rZSBhdCByZXF1ZXN0IHRpbWUsIGkuZS4gbm90IGEgcHJlcmVuZGVyL3N0YXRpYyBmaWxlLiAqL1xudHlwZSBJbnZvY2FibGVPdXRwdXQgPVxuICB8IEFkYXB0ZXJPdXRwdXRzW1wicGFnZXNcIl1bbnVtYmVyXVxuICB8IEFkYXB0ZXJPdXRwdXRzW1wicGFnZXNBcGlcIl1bbnVtYmVyXVxuICB8IEFkYXB0ZXJPdXRwdXRzW1wiYXBwUGFnZXNcIl1bbnVtYmVyXVxuICB8IEFkYXB0ZXJPdXRwdXRzW1wiYXBwUm91dGVzXCJdW251bWJlcl1cbiAgfCBOb25OdWxsYWJsZTxBZGFwdGVyT3V0cHV0c1tcIm1pZGRsZXdhcmVcIl0+O1xuXG4vKipcbiAqIEVudiBmaWxlcyBgd3JpdGVTdGFuZGFsb25lRGlyZWN0b3J5YCBjb3BpZXMgaW50byB0aGUgc3RhbmRhbG9uZSB0cmVlIGFuZCB0aGF0XG4gKiBgb25CdWlsZENvbXBsZXRlYCBoYXMgbm8gZXF1aXZhbGVudCBmb3IuIERyb3BwaW5nIGBvdXRwdXQ6IFwic3RhbmRhbG9uZVwiYFxuICogc2lsZW50bHkgZHJvcHMgdGhlc2UgdW5sZXNzIHdlIHN0YWdlIHRoZW0gb3Vyc2VsdmVzLlxuICogQHNlZSBodHRwczovL25leHRqcy5vcmcvZG9jcy9hcHAvYXBpLXJlZmVyZW5jZS9jb25maWcvbmV4dC1jb25maWctanMvb3V0cHV0XG4gKi9cbmNvbnN0IEVOVl9GSUxFUyA9IFtcIi5lbnZcIiwgXCIuZW52LnByb2R1Y3Rpb25cIl07XG5cbi8qKlxuICogYG5leHRgIHN1Ym1vZHVsZXMgdGhlICpydW50aW1lKiByZXF1aXJlcyB0aGF0IG5vIGFwcCBldmVyIHJlYWNoZXMsIHNvXG4gKiBgbmV4dCBidWlsZGAncyBvd24gdHJhY2UgbmV2ZXIgY292ZXJzIHRoZW0uIFRoZXkgYXJlIHJlcXVpcmVkIGZyb20gdGhlIGFwcCdzXG4gKiBgbmV4dGAgcmF0aGVyIHRoYW4gYnVuZGxlZCwgZGVsaWJlcmF0ZWx5IOKAlCBzZWUgYHNyYy9ydW50aW1lL25leHQtbW9kdWxlcy50c2BcbiAqIOKAlCB3aGljaCBtYWtlcyBzdGFnaW5nIHRoZWlyIGNsb3N1cmUgdGhpcyBtb2R1bGUncyBqb2IuXG4gKlxuICogYHNlcnZlLXN0YXRpY2AgaXMgaW4gZXZlcnkgZ3JvdXA6IGBzZXJ2ZVN0YXRpY0ZpbGVgXG4gKiAoYHNyYy9ydW50aW1lL3N0YXRpYy1maWxlcy50c2ApIHNlcnZlcyBwcmVyZW5kZXJlZCBhbmQgc3RhdGljIHJlc3VsdHMgd2l0aCBpdFxuICogd2hlcmV2ZXIgdGhleSBsYW5kLlxuICovXG5jb25zdCBSVU5USU1FX05FWFRfTU9EVUxFUyA9IFtcIm5leHQvZGlzdC9zZXJ2ZXIvc2VydmUtc3RhdGljLmpzXCJdO1xuXG4vKipcbiAqIG5leHQncyBpbWFnZSBvcHRpbWl6ZXIgYW5kIHRoZSBjb25maWcgaGVscGVycyBhcm91bmQgaXRcbiAqIChgc3JjL3J1bnRpbWUvaW1hZ2UudHNgKSwgd2hvc2UgY2xvc3VyZSBpcyB3aGF0IGJyaW5ncyBgc2hhcnBgIGluLiBPbmx5IHRoZVxuICogYGRlZmF1bHRgIGdyb3VwIGdldHMgdGhlbTogdGhlIGVkZ2Ugc2VuZHMgZXZlcnkgYC9fbmV4dC9pbWFnZWAgcmVxdWVzdCB0aGVyZS5cbiAqL1xuY29uc3QgSU1BR0VfTkVYVF9NT0RVTEVTID0gW1xuICBcIm5leHQvZGlzdC9zZXJ2ZXIvY29uZmlnLXNoYXJlZC5qc1wiLFxuICBcIm5leHQvZGlzdC9zaGFyZWQvbGliL2ltYWdlLWNvbmZpZy5qc1wiLFxuICBcIm5leHQvZGlzdC9zZXJ2ZXIvaW1hZ2Utb3B0aW1pemVyLmpzXCIsXG5dO1xuXG4vKipcbiAqIFRoZSBmaWxlIHRyYWNlciBgbmV4dCBidWlsZGAgaXRzZWxmIHVzZXMsIHJlYWNoZWQgdGhyb3VnaCB0aGUgYXBwJ3Mgb3duIGBuZXh0YFxuICogc28gdGhhdCBpdCBpcyB0aGUgdmVyc2lvbiB0aGF0IG1hdGNoZXMgdGhlIGZpbGVzIGJlaW5nIHRyYWNlZC4gTm90IGFcbiAqIGRlcGVuZGVuY3kgb2YgY2RrLW5leHRqczogYnVuZGxpbmcgYSBzZWNvbmQgY29weSBvZiBgQHZlcmNlbC9uZnRgIGludG8gdGhlXG4gKiBwdWJsaXNoZWQgYWRhcHRlciB3b3VsZCBhZGQgbWVnYWJ5dGVzIHRvIGV2ZXJ5IGluc3RhbGwgdG8gZG8gdGhlIHNhbWUgam9iLlxuICovXG5jb25zdCBORVhUX0ZJTEVfVFJBQ0VSID0gXCJuZXh0L2Rpc3QvY29tcGlsZWQvQHZlcmNlbC9uZnRcIjtcblxuLyoqIFRoZSBzdWJzZXQgb2YgYG5vZGVGaWxlVHJhY2VgIHRoaXMgbW9kdWxlIHVzZXMuICovXG50eXBlIE5vZGVGaWxlVHJhY2UgPSAoXG4gIGZpbGVzOiBzdHJpbmdbXSxcbiAgb3B0aW9uczogeyBiYXNlOiBzdHJpbmcgfSxcbikgPT4gUHJvbWlzZTx7IGZpbGVMaXN0OiBTZXQ8c3RyaW5nPiB9PjtcblxuLyoqXG4gKiBTdGFnaW5nIGtleSAocmVwby1yb290LXJlbGF0aXZlIFBPU0lYKSDihpIgYWJzb2x1dGUgc291cmNlIHBhdGggb24gdGhlIGJ1aWxkXG4gKiBtYWNoaW5lLiBUaGUgZGVkdXBlZCB1bmlvbiB0aGF0IHJlcGxhY2VzIHRoZSBzdGFuZGFsb25lIHRyZWUuXG4gKi9cbmV4cG9ydCB0eXBlIFN0YWdpbmdQbGFuID0gUmVhZG9ubHlNYXA8c3RyaW5nLCBzdHJpbmc+O1xuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkT3V0cHV0c09wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGRpcmVjdG9yeSBgbmV4dCBidWlsZGAgd2FzIGludm9rZWQgZnJvbS4gRGVmYXVsdHMgdG8gYHByb2Nlc3MuY3dkKClgLFxuICAgKiB3aGljaCBpcyB0aGUgcmVhbCBhbnN3ZXIgaW5zaWRlIGBvbkJ1aWxkQ29tcGxldGVgOyBhIHBhcmFtZXRlciBvbmx5IHNvIHRoZVxuICAgKiB1bml0IHRlc3RzIGNhbiBkcml2ZSB0aGUgZml4dHVyZXMnIHN5bnRoZXRpYyBwcm9qZWN0IGRpcnMuXG4gICAqL1xuICByZWFkb25seSBidWlsZEN3ZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFJlc29sdmVkIGBmdW5jdGlvbkdyb3Vwc2AuIERlZmF1bHRzIHRvIHtAbGluayBGVU5DVElPTl9HUk9VUFNfRU5WX1ZBUn0sXG4gICAqIHdoaWNoIGlzIGhvdyB0aGUgY29uc3RydWN0cyBnZXQgdGhlbSBoZXJlOiBgb25CdWlsZENvbXBsZXRlYCBydW5zIGluc2lkZVxuICAgKiBgbmV4dCBidWlsZGAgYW5kIGNhbm5vdCByZWFkIENESyBwcm9wcy5cbiAgICpcbiAgICogYHVuZGVmaW5lZGAgbWVhbnMgb25lIGRlcGxveW1lbnQgcm9vdCBob2xkaW5nIGV2ZXJ5IHJvdXRlLCB3aGljaCBpcyB0aGVcbiAgICogZGVmYXVsdCBhbmQgdGhlIG9ubHkgdGhpbmcgdGhlIENvbnRhaW5lcnMgdHlwZXMgZXZlciBkby5cbiAgICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uR3JvdXBzPzogRnVuY3Rpb25Hcm91cFNwZWNbXTtcbn1cblxuLyoqIE9uZSBkZXBsb3ltZW50IHJvb3Q6IHRoZSBzdGFnaW5nIHBsYW4gZm9yIGl0LCBhbmQgd2hlcmUgaXQgZ29lcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhZ2VkR3JvdXAge1xuICAvKipcbiAgICogR3JvdXAgbmFtZSwgYGRlZmF1bHRgIGZvciB0aGUgaW1wbGljaXQgZ3JvdXAuIEFsd2F5cyBwcmVzZW50IOKAlCBhIGJ1aWxkIHdpdGhcbiAgICogbm8gYGZ1bmN0aW9uR3JvdXBzYCBwcm9kdWNlcyBleGFjdGx5IG9uZSB7QGxpbmsgU3RhZ2VkR3JvdXB9IG5hbWVkIGBkZWZhdWx0YCxcbiAgICogc28gY2FsbGVycyBuZXZlciBicmFuY2ggb24gXCJpcyB0aGlzIHNwbGl0XCIuXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBEaXJlY3RvcnkgaW5zaWRlIGBjZGstbmV4dGpzLWFkYXB0ZXJgLCBQT1NJWDogYGFwcGAgd2hlbiBub3Qgc3BsaXR0aW5nLFxuICAgKiBgZ3JvdXBzLzxuYW1lPmAgd2hlbiBzcGxpdHRpbmcuXG4gICAqL1xuICByZWFkb25seSBkaXJOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0YWdpbmc6IFN0YWdpbmdQbGFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkQWRhcHRlck1hbmlmZXN0UmVzdWx0IHtcbiAgcmVhZG9ubHkgbWFuaWZlc3Q6IEFkYXB0ZXJNYW5pZmVzdDtcbiAgLyoqIE9uZSBlbnRyeSBwZXIgZGVwbG95bWVudCByb290IHRvIHN0YWdlLiBMZW5ndGggMSB1bmxlc3Mgc3BsaXR0aW5nLiAqL1xuICByZWFkb25seSBncm91cHM6IFN0YWdlZEdyb3VwW107XG59XG5cbi8qKiBBIHN0YWdlZCBkZXBsb3ltZW50IHJvb3Qgb24gZGlzay4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhZ2VkR3JvdXBSZXN1bHQge1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIC8qKiBBYnNvbHV0ZSBwYXRoIHRvIHRoZSBkZXBsb3ltZW50IHJvb3QuICovXG4gIHJlYWRvbmx5IHBhdGg6IHN0cmluZztcbiAgcmVhZG9ubHkgZmlsZUNvdW50OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV3JpdGVCdWlsZE91dHB1dHNSZXN1bHQgZXh0ZW5kcyBCdWlsZEFkYXB0ZXJNYW5pZmVzdFJlc3VsdCB7XG4gIC8qKiBBYnNvbHV0ZSBwYXRoIHRvIGA8ZGlzdERpcj4vY2RrLW5leHRqcy1hZGFwdGVyYC4gKi9cbiAgcmVhZG9ubHkgYWRhcHRlckRpcjogc3RyaW5nO1xuICAvKiogQWJzb2x1dGUgcGF0aCB0byB0aGUgd3JpdHRlbiBtYW5pZmVzdC4gKi9cbiAgcmVhZG9ubHkgbWFuaWZlc3RQYXRoOiBzdHJpbmc7XG4gIC8qKiBPbmUgcGVyIGRlcGxveW1lbnQgcm9vdCwgaW4gdGhlIG9yZGVyIHRoZXkgd2VyZSBzdGFnZWQuICovXG4gIHJlYWRvbmx5IHN0YWdlZEdyb3VwczogU3RhZ2VkR3JvdXBSZXN1bHRbXTtcbn1cblxuLyoqXG4gKiBCdWlsZCB0aGUgbWFuaWZlc3QgYW5kIHN0YWdpbmcgcGxhbiwgc3RhZ2UgdGhlIGZpbGVzLCBhbmQgd3JpdGUgdGhlIG1hbmlmZXN0LlxuICogQ2FsbGVkIGZyb20gYG9uQnVpbGRDb21wbGV0ZWAsIHdoaWNoIGlzIHRoZSBvbmx5IHBsYWNlIHRoYXQgaG9sZHMgdGhlIGJ1aWxkXG4gKiBvdXRwdXRzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVCdWlsZE91dHB1dHMoXG4gIGN0eDogQnVpbGRDb21wbGV0ZUNvbnRleHQsXG4gIG9wdGlvbnM6IEJ1aWxkT3V0cHV0c09wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8V3JpdGVCdWlsZE91dHB1dHNSZXN1bHQ+IHtcbiAgY29uc3QgYWRhcHRlckRpciA9IGpvaW4oY3R4LmRpc3REaXIsIEFEQVBURVJfRElSX05BTUUpO1xuICBjb25zdCBtYW5pZmVzdFBhdGggPSBqb2luKGFkYXB0ZXJEaXIsIE1BTklGRVNUX0ZJTEVfTkFNRSk7XG5cbiAgY29uc3QgeyBtYW5pZmVzdCwgZ3JvdXBzIH0gPSBidWlsZEFkYXB0ZXJNYW5pZmVzdChjdHgsIG9wdGlvbnMpO1xuXG4gIC8vIFRyYWNlZCBvbmNlLCBoZXJlOiB0aGUgdHJhY2UgaXMgYXN5bmMsIHdoaWNoIGlzIHdoeSBpdCBjYW5ub3QgaGFwcGVuIGluc2lkZVxuICAvLyBgYnVpbGRBZGFwdGVyTWFuaWZlc3RgLiBgcnVudGltZUNsb3N1cmVgIGlzIG1lcmdlZCBpbnRvIGV2ZXJ5IGdyb3VwLCBhbmRcbiAgLy8gYGltYWdlQ2xvc3VyZWAgaW50byBgZGVmYXVsdGAgb25seSwgdGhlIG9uZSBncm91cCBgL19uZXh0L2ltYWdlYCByZWFjaGVzLlxuICBjb25zdCBydW50aW1lQ2xvc3VyZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIGNvbnN0IGltYWdlQ2xvc3VyZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIGF3YWl0IGFkZFJ1bnRpbWVOZXh0Q2xvc3VyZShjdHgsIHJ1bnRpbWVDbG9zdXJlLCBpbWFnZUNsb3N1cmUpO1xuICBhZGRSZXF1aXJlZFNlcnZlckZpbGVzKGN0eCwgcnVudGltZUNsb3N1cmUpO1xuXG4gIC8vIEEgcHJldmlvdXMgYnVpbGQncyB0cmVlIGlzIG5ldmVyIGFkZGl0aXZlIHdpdGggdGhpcyBvbmUnczogYSByZW1vdmVkIHJvdXRlXG4gIC8vIGxlYXZlcyBiZWhpbmQgYW4gZW50cnlwb2ludCB0aGUgbWFuaWZlc3Qgbm8gbG9uZ2VyIG1lbnRpb25zLCBhIHJlbmFtZWQgY2h1bmtcbiAgLy8gbGVhdmVzIGRlYWQgYnl0ZXMgaW5zaWRlIHRoZSAyNTAgTUIgYnVkZ2V0LCBhbmQgYSByZWdyb3VwZWQgYnVpbGQgbGVhdmVzIGFcbiAgLy8gd2hvbGUgZGVwbG95bWVudCByb290IG5vdGhpbmcgZGVwbG95cy5cbiAgYXdhaXQgcm0oYWRhcHRlckRpciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHN0YWdlZEdyb3VwczogU3RhZ2VkR3JvdXBSZXN1bHRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGdyb3VwIG9mIGdyb3Vwcykge1xuICAgIGNvbnN0IGdyb3VwU3RhZ2luZyA9IG1lcmdlZChcbiAgICAgIG1lcmdlZChncm91cC5zdGFnaW5nLCBydW50aW1lQ2xvc3VyZSksXG4gICAgICBncm91cC5uYW1lID09PSBERUZBVUxUX0ZVTkNUSU9OX0dST1VQID8gaW1hZ2VDbG9zdXJlIDogbmV3IE1hcCgpLFxuICAgICk7XG4gICAgY29uc3QgcGF0aCA9IGpvaW4oYWRhcHRlckRpciwgLi4uZ3JvdXAuZGlyTmFtZS5zcGxpdChcIi9cIikpO1xuICAgIGF3YWl0IG1rZGlyKHBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGF3YWl0IHN0YWdlRmlsZXMoZ3JvdXBTdGFnaW5nLCBwYXRoKTtcbiAgICBzdGFnZWRHcm91cHMucHVzaCh7IG5hbWU6IGdyb3VwLm5hbWUsIHBhdGgsIGZpbGVDb3VudDogZ3JvdXBTdGFnaW5nLnNpemUgfSk7XG4gIH1cblxuICBhd2FpdCB3cml0ZUZpbGUobWFuaWZlc3RQYXRoLCBKU09OLnN0cmluZ2lmeShtYW5pZmVzdCwgbnVsbCwgMikpO1xuXG4gIHJldHVybiB7XG4gICAgbWFuaWZlc3QsXG4gICAgZ3JvdXBzLFxuICAgIGFkYXB0ZXJEaXIsXG4gICAgbWFuaWZlc3RQYXRoLFxuICAgIHN0YWdlZEdyb3VwcyxcbiAgfTtcbn1cblxuLyoqIExlZnQgd2lucywgYXMgZXZlcnl3aGVyZSBlbHNlIGluIHRoaXMgbW9kdWxlOiBmaXJzdCB3cml0ZXIgb2YgYSBrZXkga2VlcHMgaXQuICovXG5mdW5jdGlvbiBtZXJnZWQoXG4gIGJhc2U6IFN0YWdpbmdQbGFuLFxuICBhZGRpdGlvbnM6IFJlYWRvbmx5TWFwPHN0cmluZywgc3RyaW5nPixcbik6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCByZXN1bHQgPSBuZXcgTWFwKGJhc2UpO1xuICBmb3IgKGNvbnN0IFtrZXksIHNvdXJjZV0gb2YgYWRkaXRpb25zKSB7XG4gICAgaWYgKCFyZXN1bHQuaGFzKGtleSkpIHtcbiAgICAgIHJlc3VsdC5zZXQoa2V5LCBzb3VyY2UpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFRoZSBwdXJlIGhhbGYgb2Yge0BsaW5rIHdyaXRlQnVpbGRPdXRwdXRzfTogZXZlcnl0aGluZyBkZXJpdmVkIGZyb20gdGhlIGJ1aWxkXG4gKiBvdXRwdXRzLCB3aXRoIG5vIHdyaXRlcy4gU3BsaXQgb3V0IHNvIGl0IGNhbiBiZSB1bml0IHRlc3RlZCBhZ2FpbnN0IGNvbW1pdHRlZFxuICogYG9uQnVpbGRDb21wbGV0ZWAgZml4dHVyZXMuXG4gKlxuICogVGhyb3dzIG9uIGFueSBub24tTm9kZSBvdXRwdXQgYW5kIG9uIGFueSBzdGFnaW5nIGtleSB0d28gb3V0cHV0cyBtYXAgdG9cbiAqIGRpZmZlcmVudCBjb250ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRBZGFwdGVyTWFuaWZlc3QoXG4gIGN0eDogQnVpbGRDb21wbGV0ZUNvbnRleHQsXG4gIG9wdGlvbnM6IEJ1aWxkT3V0cHV0c09wdGlvbnMgPSB7fSxcbik6IEJ1aWxkQWRhcHRlck1hbmlmZXN0UmVzdWx0IHtcbiAgY29uc3QgeyBvdXRwdXRzLCByZXBvUm9vdCB9ID0gY3R4O1xuICBjb25zdCBiYXNlUGF0aCA9IGN0eC5jb25maWcuYmFzZVBhdGggfHwgXCJcIjtcbiAgYXNzZXJ0QnVpbGRDd2QoY3R4LCBvcHRpb25zLmJ1aWxkQ3dkID8/IHByb2Nlc3MuY3dkKCkpO1xuICBjb25zdCBpbnZvY2FibGU6IEludm9jYWJsZU91dHB1dFtdID0gW1xuICAgIC4uLm91dHB1dHMucGFnZXMsXG4gICAgLi4ub3V0cHV0cy5wYWdlc0FwaSxcbiAgICAuLi5vdXRwdXRzLmFwcFBhZ2VzLFxuICAgIC4uLm91dHB1dHMuYXBwUm91dGVzLFxuICAgIC4uLihvdXRwdXRzLm1pZGRsZXdhcmUgPyBbb3V0cHV0cy5taWRkbGV3YXJlXSA6IFtdKSxcbiAgXTtcblxuICBhc3NlcnROb2RlUnVudGltZXMoaW52b2NhYmxlLCBvdXRwdXRzLm1pZGRsZXdhcmUpO1xuICB3YXJuT25Ecm9wcGVkUm91dGVDb25maWcoaW52b2NhYmxlKTtcblxuICBjb25zdCBzdGF0aWNGaWxlcyA9IGNvbGxlY3RTdGF0aWNGaWxlcyhjdHgpO1xuXG4gIGNvbnN0IGVudHJ5cG9pbnRzOiBSZWNvcmQ8c3RyaW5nLCBBZGFwdGVyRW50cnlwb2ludD4gPSB7fTtcbiAgZm9yIChjb25zdCB7IG91dHB1dHM6IGdyb3VwLCB0eXBlIH0gb2YgW1xuICAgIHsgb3V0cHV0czogb3V0cHV0cy5wYWdlcywgdHlwZTogXCJwYWdlXCIgYXMgY29uc3QgfSxcbiAgICB7IG91dHB1dHM6IG91dHB1dHMucGFnZXNBcGksIHR5cGU6IFwicGFnZS1hcGlcIiBhcyBjb25zdCB9LFxuICAgIHsgb3V0cHV0czogb3V0cHV0cy5hcHBQYWdlcywgdHlwZTogXCJhcHAtcGFnZVwiIGFzIGNvbnN0IH0sXG4gICAgeyBvdXRwdXRzOiBvdXRwdXRzLmFwcFJvdXRlcywgdHlwZTogXCJhcHAtcm91dGVcIiBhcyBjb25zdCB9LFxuICBdKSB7XG4gICAgZm9yIChjb25zdCBvdXRwdXQgb2YgZ3JvdXApIHtcbiAgICAgIGFkZEVudHJ5cG9pbnQoZW50cnlwb2ludHMsIHJlcG9Sb290LCBvdXRwdXQsIHR5cGUsIGJhc2VQYXRoKTtcbiAgICB9XG4gIH1cblxuICBhZGRQcmVyZW5kZXJQYXRobmFtZXMoXG4gICAgZW50cnlwb2ludHMsXG4gICAgb3V0cHV0cy5wcmVyZW5kZXJzLFxuICAgIGN0eC5yb3V0aW5nLmR5bmFtaWNSb3V0ZXMsXG4gICAgYmFzZVBhdGgsXG4gICAgYCR7YmFzZVBhdGh9L19uZXh0L2RhdGEvJHtjdHguYnVpbGRJZH0vYCxcbiAgKTtcblxuICBjb25zdCBwYXRobmFtZXMgPSBzb3J0ZWRVbmlxdWUoW1xuICAgIC4uLk9iamVjdC5rZXlzKGVudHJ5cG9pbnRzKSxcbiAgICAuLi5PYmplY3Qua2V5cyhzdGF0aWNGaWxlcyksXG4gIF0pO1xuXG4gIGNvbnN0IGZ1bmN0aW9uR3JvdXBzID1cbiAgICBvcHRpb25zLmZ1bmN0aW9uR3JvdXBzID8/XG4gICAgcGFyc2VGdW5jdGlvbkdyb3Vwc0Vudihwcm9jZXNzLmVudltGVU5DVElPTl9HUk9VUFNfRU5WX1ZBUl0pO1xuICAvLyBpMThuIGlzIGNoZWNrZWQgZmlyc3Q6IGl0IHJlamVjdHMgdGhlIGNvbWJpbmF0aW9uIG91dHJpZ2h0LCBhbmQgcnVubmluZyBpdFxuICAvLyBhZnRlciB0aGUgYXNzaWdubWVudCBtZWFudCBhbiBpMThuIGFwcCBnb3QgdGhlIGFzc2lnbm1lbnQncyBcInBhdHRlcm4gbWF0Y2hlc1xuICAvLyBubyByb3V0ZVwiIGVycm9yIGluc3RlYWQg4oCUIHRydWUsIGJ1dCBhYm91dCB0aGUgd3JvbmcgdGhpbmcsIHNpbmNlIGEgbG9jYWxpemVkXG4gIC8vIHRlbXBsYXRlIG5ldmVyIG1hdGNoZXMgYW4gdW5sb2NhbGl6ZWQgcGF0dGVybi5cbiAgaWYgKGZ1bmN0aW9uR3JvdXBzKSB7XG4gICAgYXNzZXJ0Tm9JMThuU3BsaXR0aW5nKGN0eC5jb25maWcuaTE4biA/PyBudWxsKTtcbiAgfVxuICBjb25zdCBhc3NpZ25tZW50ID0gZnVuY3Rpb25Hcm91cHNcbiAgICA/IGFzc2lnblJvdXRlc1RvR3JvdXBzKFxuICAgICAgICBmdW5jdGlvbkdyb3VwcyxcbiAgICAgICAgLy8gS2V5ZWQgb24gdGhlIGZpbGUsIG5vdCB0aGUgb3V0cHV0IGBpZGA6IGEgUGFnZXMgUm91dGVyIHBhZ2UgYW5kIGl0c1xuICAgICAgICAvLyBgL19uZXh0L2RhdGEvPGJ1aWxkSWQ+LzxwYWdlPi5qc29uYCByb3V0ZSBhcmUgc2VwYXJhdGUgb3V0cHV0cyB3aXRoXG4gICAgICAgIC8vIHNlcGFyYXRlIGlkcyBiYWNrZWQgYnkgb25lIGZpbGUsIGFuZCBvbmx5IHRoZSBwYWdlJ3MgdGVtcGxhdGUgbWF0Y2hlc1xuICAgICAgICAvLyBhIGdyb3VwIHBhdHRlcm4uXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGVudHJ5cG9pbnRzKS5tYXAoKFt0ZW1wbGF0ZSwgZW50cnlwb2ludF0pID0+ICh7XG4gICAgICAgICAgdGVtcGxhdGUsXG4gICAgICAgICAgZW50cnlwb2ludElkOiBlbnRyeXBvaW50LmZpbGVQYXRoLFxuICAgICAgICAgIHR5cGU6IGVudHJ5cG9pbnQudHlwZSxcbiAgICAgICAgfSkpLFxuICAgICAgICB7XG4gICAgICAgICAgYmFzZVBhdGg6IGN0eC5jb25maWcuYmFzZVBhdGggfHwgXCJcIixcbiAgICAgICAgICBidWlsZElkOiBjdHguYnVpbGRJZCxcbiAgICAgICAgICB0cmFpbGluZ1NsYXNoOiBjdHguY29uZmlnLnRyYWlsaW5nU2xhc2ggPT09IHRydWUsXG4gICAgICAgICAgcm91dGluZzogY3R4LnJvdXRpbmcsXG4gICAgICAgIH0sXG4gICAgICApXG4gICAgOiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgbWFuaWZlc3Q6IEFkYXB0ZXJNYW5pZmVzdCA9IHtcbiAgICB2ZXJzaW9uOiBBREFQVEVSX01BTklGRVNUX1ZFUlNJT04gYXMgMSxcbiAgICBidWlsZElkOiBjdHguYnVpbGRJZCxcbiAgICByZWxhdGl2ZVByb2plY3REaXI6IHRvUG9zaXgocmVsYXRpdmUocmVwb1Jvb3QsIGN0eC5wcm9qZWN0RGlyKSksXG4gICAgY29uZmlnOiB7XG4gICAgICBiYXNlUGF0aDogY3R4LmNvbmZpZy5iYXNlUGF0aCB8fCBcIlwiLFxuICAgICAgdHJhaWxpbmdTbGFzaDogY3R4LmNvbmZpZy50cmFpbGluZ1NsYXNoID09PSB0cnVlLFxuICAgICAgYXNzZXRQcmVmaXg6IGN0eC5jb25maWcuYXNzZXRQcmVmaXggfHwgXCJcIixcbiAgICAgIGRpc3REaXI6IHRvUG9zaXgocmVsYXRpdmUoY3R4LnByb2plY3REaXIsIGN0eC5kaXN0RGlyKSksXG4gICAgICBjb21wcmVzczogY3R4LmNvbmZpZy5jb21wcmVzcyAhPT0gZmFsc2UsXG4gICAgICBnZW5lcmF0ZUV0YWdzOiBjdHguY29uZmlnLmdlbmVyYXRlRXRhZ3MgIT09IGZhbHNlLFxuICAgICAgaTE4bjogY3R4LmNvbmZpZy5pMThuID8/IG51bGwsXG4gICAgICBkZXBsb3ltZW50SWQ6IChjdHguY29uZmlnLmRlcGxveW1lbnRJZCA/PyBcIlwiKS5yZXBsYWNlKFxuICAgICAgICAvW15BLVphLXowLTlfLV0vZyxcbiAgICAgICAgXCItXCIsXG4gICAgICApLFxuICAgIH0sXG4gICAgcm91dGluZzogY3R4LnJvdXRpbmcsXG4gICAgcGF0aG5hbWVzLFxuICAgIGVudHJ5cG9pbnRzLFxuICAgIG1pZGRsZXdhcmU6IGJ1aWxkTWlkZGxld2FyZShyZXBvUm9vdCwgb3V0cHV0cy5taWRkbGV3YXJlKSxcbiAgICBzdGF0aWNGaWxlcyxcbiAgICAuLi4oYXNzaWdubWVudFxuICAgICAgPyB7XG4gICAgICAgICAgZ3JvdXBzOiBhc3NpZ25tZW50LnRlbXBsYXRlcyxcbiAgICAgICAgICBiZWhhdmlvcnM6IGFzc2lnbm1lbnQuYmVoYXZpb3JzLFxuICAgICAgICAgIGZ1bmN0aW9uR3JvdXBzOiBmdW5jdGlvbkdyb3VwcyEubWFwKCh7IG5hbWUsIHJvdXRlcyB9KSA9PiAoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIHJvdXRlcyxcbiAgICAgICAgICB9KSksXG4gICAgICAgIH1cbiAgICAgIDoge30pLFxuICB9O1xuXG4gIGNvbnN0IGdyb3VwczogU3RhZ2VkR3JvdXBbXSA9IGFzc2lnbm1lbnRcbiAgICA/IE9iamVjdC5lbnRyaWVzKGFzc2lnbm1lbnQudGVtcGxhdGVzKS5tYXAoKFtuYW1lLCB0ZW1wbGF0ZXNdKSA9PiAoe1xuICAgICAgICBuYW1lLFxuICAgICAgICBkaXJOYW1lOiBncm91cFN0YWdpbmdEaXJOYW1lKG5hbWUpLFxuICAgICAgICBzdGFnaW5nOiBjb2xsZWN0R3JvdXBTdGFnaW5nUGxhbihcbiAgICAgICAgICBjdHgsXG4gICAgICAgICAgaW52b2NhYmxlLFxuICAgICAgICAgIGVudHJ5cG9pbnRzLFxuICAgICAgICAgIHRlbXBsYXRlcyxcbiAgICAgICAgKSxcbiAgICAgIH0pKVxuICAgIDogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogREVGQVVMVF9GVU5DVElPTl9HUk9VUCxcbiAgICAgICAgICBkaXJOYW1lOiBncm91cFN0YWdpbmdEaXJOYW1lKCksXG4gICAgICAgICAgc3RhZ2luZzogc2VydmVkU3RhZ2luZ1BsYW4oY3R4LCBpbnZvY2FibGUpLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICByZXR1cm4geyBtYW5pZmVzdCwgZ3JvdXBzIH07XG59XG5cbi8qKlxuICogT25lIGdyb3VwJ3Mgc2xpY2Ugb2YgdGhlIHN0YWdpbmcgcGxhbjogdGhlIGFzc2V0cyBvZiB0aGUgb3V0cHV0cyBpdCBvd25zLCBhbmRcbiAqIG5vdGhpbmcgZWxzZS5cbiAqXG4gKiBNaWRkbGV3YXJlIGlzIGluIGV2ZXJ5IGdyb3VwLCBub3QganVzdCB0aGUgZGVmYXVsdCBvbmUg4oCUIGl0IHJ1bnMgb24gZXZlcnlcbiAqIHJlcXVlc3Qgd2hlcmV2ZXIgdGhhdCByZXF1ZXN0IGxhbmRzLCBzbyBpdCBpcyBkdXBsaWNhdGVkIGJ5IGRlc2lnbiwgYXMgaXMgdGhlXG4gKiBgbmV4dGAgY2xvc3VyZSB0aGUgZW50cnlwb2ludHMgc2hhcmUuIFRoZSBzYW1lIGdvZXMgZm9yIHRoZSBzdGF0aWMgZmlsZXMgdGhlXG4gKiBydW50aW1lIHNlcnZlcyBpdHNlbGYgKGA0MDQuaHRtbGAsIGBmYXZpY29uLmljby5ib2R5YCk6IGFueSBncm91cCBjYW4gYmUgYXNrZWRcbiAqIGZvciB0aGVtLiBBbmQgc28gYXJlIHRoZSBub3QtZm91bmQgYW5kIGVycm9yIHBhZ2VzOiB0aGUgcnVudGltZSByZW5kZXJzIGFcbiAqIDQwNCBvciBhIDUwMCB3aXRoIHdoaWNoZXZlciBvZiB0aGVtIHRoZSBzaGFyZWQgbWFuaWZlc3QgbmFtZXNcbiAqIChgc3RhdHVzVGFyZ2V0c2AgaW4gYHJ1bnRpbWUvZGlzcGF0Y2gudHNgKSwgaW4gd2hpY2hldmVyIGdyb3VwIHRoZVxuICogcmVxdWVzdCByZWFjaGVkLCBzbyBhIGdyb3VwIHdpdGhvdXQgdGhlbSBhbnN3ZXJlZCBhIFVSTCB1bmRlciBpdHMgb3duXG4gKiBwYXR0ZXJuIHRoYXQgbWF0Y2hlcyBubyByb3V0ZSB3aXRoIFwidGhlIGRlcGxveW1lbnQgcGFja2FnZSBpcyBpbmNvbXBsZXRlXCIuXG4gKlxuICogT3duZXJzaGlwIGlzIG1hdGNoZWQgb24gdGhlIGVudHJ5cG9pbnQncyBgZmlsZVBhdGhgLCBub3QgaXRzIGBpZGAgb3JcbiAqIHBhdGhuYW1lOiB0aGUgbWFuaWZlc3QncyBlbnRyeXBvaW50cyBhcmUga2V5ZWQgYnkgKnRlbXBsYXRlKiwgYW4gb3V0cHV0IG1heVxuICogYmFjayBzZXZlcmFsIHRlbXBsYXRlcywgYW5kIHtAbGluayBhZGRQcmVyZW5kZXJQYXRobmFtZXN9IHN5bnRoZXNpemVzXG4gKiBlbnRyeXBvaW50cyB0aGF0IGNhcnJ5IHRoZSAqcHJlcmVuZGVyJ3MqIGlkLCB3aGljaCBubyBpbnZvY2FibGUgb3V0cHV0IGhhcyAodGhlXG4gKiByb290LXBhcmFtcyBhcHA6IGVudHJ5cG9pbnQgYC9lbmAgd2l0aCBgaWQ6IFwiL2VuXCJgIGJhY2tlZCBieSB0aGUgb3V0cHV0XG4gKiBgL1tsb2NhbGVdYCkuIFRoZSBzeW50aGVzaXplZCBlbnRyeXBvaW50J3MgYGZpbGVQYXRoYCBpcyB0aGUgb3duaW5nIG91dHB1dCdzLlxuICovXG5mdW5jdGlvbiBjb2xsZWN0R3JvdXBTdGFnaW5nUGxhbihcbiAgY3R4OiBCdWlsZENvbXBsZXRlQ29udGV4dCxcbiAgaW52b2NhYmxlOiBJbnZvY2FibGVPdXRwdXRbXSxcbiAgZW50cnlwb2ludHM6IFJlY29yZDxzdHJpbmcsIEFkYXB0ZXJFbnRyeXBvaW50PixcbiAgdGVtcGxhdGVzOiBzdHJpbmdbXSxcbik6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBiYXNlUGF0aCA9IGN0eC5jb25maWcuYmFzZVBhdGggfHwgXCJcIjtcbiAgY29uc3Qgb3duZWRFbnRyeXBvaW50cyA9IFtcbiAgICAuLi50ZW1wbGF0ZXMsXG4gICAgLi4uRVJST1JfUEFHRV9TVUZGSVhFUy5tYXAoKHN1ZmZpeCkgPT4gYCR7YmFzZVBhdGh9JHtzdWZmaXh9YCksXG4gIF1cbiAgICAubWFwKCh0ZW1wbGF0ZSkgPT4gZW50cnlwb2ludHNbdGVtcGxhdGVdKVxuICAgIC5maWx0ZXIoKGVudHJ5KTogZW50cnkgaXMgQWRhcHRlckVudHJ5cG9pbnQgPT4gZW50cnkgIT09IHVuZGVmaW5lZCk7XG4gIGNvbnN0IG93bmVkRmlsZXMgPSBuZXcgU2V0KG93bmVkRW50cnlwb2ludHMubWFwKChlbnRyeSkgPT4gZW50cnkuZmlsZVBhdGgpKTtcbiAgY29uc3QgbWlkZGxld2FyZSA9IGN0eC5vdXRwdXRzLm1pZGRsZXdhcmU7XG4gIGNvbnN0IG93bmVkID0gaW52b2NhYmxlLmZpbHRlcihcbiAgICAob3V0cHV0KSA9PlxuICAgICAgb3duZWRGaWxlcy5oYXModG9Qb3NpeChyZWxhdGl2ZShjdHgucmVwb1Jvb3QsIG91dHB1dC5maWxlUGF0aCkpKSB8fFxuICAgICAgb3V0cHV0ID09PSBtaWRkbGV3YXJlLFxuICApO1xuICByZXR1cm4gc2VydmVkU3RhZ2luZ1BsYW4oY3R4LCBvd25lZCk7XG59XG5cbi8qKiB7QGxpbmsgY29sbGVjdFN0YWdpbmdQbGFufSBmb3IgYG91dHB1dHNgLCBwbHVzIHRoZSBmaWxlcyB0aGUgcnVudGltZSBzZXJ2ZXMuICovXG5mdW5jdGlvbiBzZXJ2ZWRTdGFnaW5nUGxhbihcbiAgY3R4OiBCdWlsZENvbXBsZXRlQ29udGV4dCxcbiAgb3V0cHV0czogSW52b2NhYmxlT3V0cHV0W10sXG4pOiBNYXA8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3Qgc3RhZ2luZyA9IGNvbGxlY3RTdGFnaW5nUGxhbihjdHgsIG91dHB1dHMpO1xuICBzdGFnZVNlcnZlZFN0YXRpY0ZpbGVzKGN0eCwgc3RhZ2luZyk7XG4gIHJldHVybiBzdGFnaW5nO1xufVxuXG4vKipcbiAqIEpvYiAxOiByZWplY3Qgbm9uLU5vZGUgb3V0cHV0cywgZXZlcnl3aGVyZS5cbiAqXG4gKiBgZXhwb3J0IGNvbnN0IHJ1bnRpbWUgPSAnZWRnZSdgIG9uIGEgcGFnZSBvciByb3V0ZSBoYW5kbGVyIGxhbmRzIGluXG4gKiBgYXBwUGFnZXNgL2BhcHBSb3V0ZXNgL2BwYWdlc2AvYHBhZ2VzQXBpYCB3aXRoIGBydW50aW1lOiAnZWRnZSdgLFxuICogYGFzc2V0czoge31gLCBhbmQgYW4gYGVkZ2VSdW50aW1lYCBkZXNjcmlwdG9yIG5lZWRpbmcgYGdsb2JhbFRoaXMuX0VOVFJJRVNgXG4gKiBhbmQgYSBzYW5kYm94LiBHdWFyZGluZyBtaWRkbGV3YXJlIGFsb25lIHdvdWxkIGxlYXZlIGEgc2lsZW50IGZhaWx1cmUgbW9kZVxuICogZm9yIGVkZ2UgcGFnZXM6IGFuIGVudHJ5cG9pbnQgd2UgY2FuJ3QgaW52b2tlIGFuZCBubyBhc3NldHMgdG8gaW52b2tlIGl0XG4gKiB3aXRoLlxuICovXG5mdW5jdGlvbiBhc3NlcnROb2RlUnVudGltZXMoXG4gIGludm9jYWJsZTogSW52b2NhYmxlT3V0cHV0W10sXG4gIG1pZGRsZXdhcmU6IEFkYXB0ZXJPdXRwdXRzW1wibWlkZGxld2FyZVwiXSxcbik6IHZvaWQge1xuICBjb25zdCBvZmZlbmRpbmcgPSBpbnZvY2FibGUuZmlsdGVyKChvdXRwdXQpID0+IG91dHB1dC5ydW50aW1lICE9PSBcIm5vZGVqc1wiKTtcbiAgaWYgKG9mZmVuZGluZy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBNaWRkbGV3YXJlIGlzIHJlcG9ydGVkIHNlcGFyYXRlbHkgZnJvbSByb3V0ZXMuIEl0cyBgc291cmNlUGFnZWAgaXMgYC9gLCBzb1xuICAvLyBmb2xkaW5nIGl0IGluIHdpdGggdGhlIHJvdXRlcyBwcm9kdWNlcyB0aGUgYWN0aXZlbHkgbWlzbGVhZGluZyBhZHZpY2UgdG9cbiAgLy8gcmVtb3ZlIGBleHBvcnQgY29uc3QgcnVudGltZSA9IFwiZWRnZVwiYCBmcm9tIHRoZSBob21lIHBhZ2UgLSB3aGljaCBpcyB3aGVyZVxuICAvLyB0aGUgZWRnZSBydW50aW1lIGlzIG5vdCwgYW5kIG1heSBub3QgZXZlbiBleGlzdC5cbiAgY29uc3Qgb2ZmZW5kaW5nTWlkZGxld2FyZSA9IG1pZGRsZXdhcmUgJiYgb2ZmZW5kaW5nLmluY2x1ZGVzKG1pZGRsZXdhcmUpO1xuICAvLyBgLnJzY2AgdmFyaWFudHMgc2hhcmUgYSBgc291cmNlUGFnZWAgd2l0aCB0aGVpciBIVE1MIHNpYmxpbmcsIHNvIGRlZHVwZS5cbiAgY29uc3Qgcm91dGVzID0gc29ydGVkVW5pcXVlKFxuICAgIG9mZmVuZGluZ1xuICAgICAgLmZpbHRlcigob3V0cHV0KSA9PiBvdXRwdXQgIT09IG1pZGRsZXdhcmUpXG4gICAgICAubWFwKChvdXRwdXQpID0+IGAke291dHB1dC5zb3VyY2VQYWdlfSAocnVudGltZTogXCIke291dHB1dC5ydW50aW1lfVwiKWApLFxuICApO1xuXG4gIGNvbnN0IHJlYXNvbnM6IHN0cmluZ1tdID0gW107XG4gIGlmIChyb3V0ZXMubGVuZ3RoID4gMCkge1xuICAgIHJlYXNvbnMucHVzaChcbiAgICAgIGBjZGstbmV4dGpzIGNhbm5vdCBkZXBsb3kgcm91dGVzIGJ1aWx0IGZvciB0aGUgZWRnZSBydW50aW1lLiBgICtcbiAgICAgICAgYFJlbW92ZSBcXGBleHBvcnQgY29uc3QgcnVudGltZSA9IFwiZWRnZVwiXFxgIGZyb206XFxuYCArXG4gICAgICAgIHJvdXRlcy5tYXAoKHJvdXRlKSA9PiBgICAtICR7cm91dGV9YCkuam9pbihcIlxcblwiKSxcbiAgICApO1xuICB9XG4gIGlmIChvZmZlbmRpbmdNaWRkbGV3YXJlKSB7XG4gICAgcmVhc29ucy5wdXNoKFxuICAgICAgYGNkay1uZXh0anMgY2Fubm90IGRlcGxveSBtaWRkbGV3YXJlIGJ1aWx0IGZvciB0aGUgZWRnZSBydW50aW1lIGAgK1xuICAgICAgICBgKCR7bWlkZGxld2FyZS5maWxlUGF0aH0sIHJ1bnRpbWU6IFwiJHttaWRkbGV3YXJlLnJ1bnRpbWV9XCIpLiBgICtcbiAgICAgICAgYFJlbmFtZSBpdCB0byBcXGBwcm94eS50c1xcYCAoTmV4dC5qcyAxNiBydW5zIHByb3h5IG9uIHRoZSBOb2RlIGAgK1xuICAgICAgICBgcnVudGltZSksIG9yIGtlZXAgXFxgbWlkZGxld2FyZS50c1xcYCBhbmQgYWRkIGAgK1xuICAgICAgICBgXFxgZXhwb3J0IGNvbnN0IGNvbmZpZyA9IHsgcnVudGltZTogXCJub2RlanNcIiB9XFxgIHRvIGl0IOKAlCBgICtcbiAgICAgICAgYFxcYG1pZGRsZXdhcmUudHNcXGAgZGVmYXVsdHMgdG8gdGhlIGVkZ2UgcnVudGltZSwgYnV0IGRvZXMgbm90IHJlcXVpcmUgaXQuYCxcbiAgICApO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIGAke0xPR19QUkVGSVh9ICR7cmVhc29ucy5qb2luKFwiXFxuXCIpfVxcbmAgK1xuICAgICAgYFRoZSBlZGdlIHJ1bnRpbWUgaXMgZGVwcmVjYXRlZCBpbiBOZXh0LmpzOiBgICtcbiAgICAgIGBodHRwczovL25leHRqcy5vcmcvZG9jcy9tZXNzYWdlcy9lZGdlLXJ1bnRpbWUtZGVwcmVjYXRlZGAsXG4gICk7XG59XG5cbi8qKlxuICogV2FybiBvbiByb3V0ZSBjb25maWcgY2RrLW5leHRqcyBkb2VzIG5vdCBob25vci4gQW4gYXV0aG9yIHdobyBzZXQgdGhlc2UgYXNrZWRcbiAqIGZvciBzb21ldGhpbmcgZXhwbGljaXRseSwgc28gc2F5IHNvIHJhdGhlciB0aGFuIGlnbm9yaW5nIGl0IHNpbGVudGx5OyBuZXZlclxuICogdGhyb3csIGJlY2F1c2Ugcm91dGUtbGV2ZWwgYG1heER1cmF0aW9uYCBpcyB2YWxpZCBOZXh0LmpzLlxuICpcbiAqIGBOZXh0anNCdWlsZGAgcnVucyBgbmV4dCBidWlsZGAgd2l0aCBgc3RkaW86IFwiaW5oZXJpdFwiYCwgc28gdGhpcyByZWFjaGVzIHRoZVxuICogdXNlcidzIHRlcm1pbmFsLiBTZWUgdGhlIHBsYW4ncyBcIkRlY2lzaW9uc1wiIGZvciB3aHkgbmVpdGhlciBpcyBob25vcmVkLlxuICovXG5mdW5jdGlvbiB3YXJuT25Ecm9wcGVkUm91dGVDb25maWcoaW52b2NhYmxlOiBJbnZvY2FibGVPdXRwdXRbXSk6IHZvaWQge1xuICBjb25zdCBkcm9wcGVkOiBSZWNvcmQ8XCJtYXhEdXJhdGlvblwiIHwgXCJwcmVmZXJyZWRSZWdpb25cIiwgc3RyaW5nW10+ID0ge1xuICAgIG1heER1cmF0aW9uOiBbXSxcbiAgICBwcmVmZXJyZWRSZWdpb246IFtdLFxuICB9O1xuICBmb3IgKGNvbnN0IG91dHB1dCBvZiBpbnZvY2FibGUpIHtcbiAgICBpZiAob3V0cHV0LmNvbmZpZz8ubWF4RHVyYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgZHJvcHBlZC5tYXhEdXJhdGlvbi5wdXNoKG91dHB1dC5zb3VyY2VQYWdlKTtcbiAgICB9XG4gICAgaWYgKG91dHB1dC5jb25maWc/LnByZWZlcnJlZFJlZ2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkcm9wcGVkLnByZWZlcnJlZFJlZ2lvbi5wdXNoKG91dHB1dC5zb3VyY2VQYWdlKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCByZW1lZHk6IFJlY29yZDxcIm1heER1cmF0aW9uXCIgfCBcInByZWZlcnJlZFJlZ2lvblwiLCBzdHJpbmc+ID0ge1xuICAgIG1heER1cmF0aW9uOlxuICAgICAgXCJTZXQgdGhlIGZ1bmN0aW9uIHRpbWVvdXQgd2l0aCB0aGUgY29uc3RydWN0J3MgYG92ZXJyaWRlc2AgcHJvcCBpbnN0ZWFkIChlLmcuIGBvdmVycmlkZXM6IHsgbmV4dGpzRnVuY3Rpb25zOiB7IGZ1bmN0aW9uUHJvcHM6IHsgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygzMCkgfSB9IH1gKTsgYSBMYW1iZGEgdGltZW91dCBpcyBwZXItZnVuY3Rpb24gd2hpbGUgYG1heER1cmF0aW9uYCBpcyBwZXItcm91dGUuXCIsXG4gICAgcHJlZmVycmVkUmVnaW9uOlxuICAgICAgXCJIb25vcmluZyBpdCB3b3VsZCByZXF1aXJlIGEgbXVsdGktcmVnaW9uIGRlcGxveW1lbnQsIHdoaWNoIHRoaXMgY29uc3RydWN0IGRvZXMgbm90IG1vZGVsLlwiLFxuICB9O1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIFtcIm1heER1cmF0aW9uXCIsIFwicHJlZmVycmVkUmVnaW9uXCJdIGFzIGNvbnN0KSB7XG4gICAgY29uc3Qgcm91dGVzID0gc29ydGVkVW5pcXVlKGRyb3BwZWRba2V5XSk7XG4gICAgaWYgKHJvdXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBgJHtMT0dfUFJFRklYfSBcXGAke2tleX1cXGAgaXMgbm90IGhvbm9yZWQgYnkgY2RrLW5leHRqcy4gYCArXG4gICAgICAgIGAke3JvdXRlcy5sZW5ndGh9IHJvdXRlKHMpIHNldCBpdCwgaW5jbHVkaW5nOiAke3JvdXRlcy5zbGljZSgwLCA1KS5qb2luKFwiLCBcIil9YCArXG4gICAgICAgIGAke3JvdXRlcy5sZW5ndGggPiA1ID8gYCwgYW5kICR7cm91dGVzLmxlbmd0aCAtIDV9IG1vcmVgIDogXCJcIn0uIGAgK1xuICAgICAgICByZW1lZHlba2V5XSxcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogSm9icyAyLCAzIGFuZCA2OiB0aGUgZGVkdXBlZCB1bmlvbiBvZiBldmVyeSBzaGlwcGVkIG91dHB1dCdzIHRyYWNlZCBgYXNzZXRzYCxcbiAqIHBsdXMgZWFjaCBlbnRyeXBvaW50IGZpbGUgaXRzZWxmLCBwbHVzIHRoZSBlbnYgZmlsZXMsIHdpdGggYGFzc2V0c0hhc2hlc2AgdXNlZFxuICogYXMgYSBjb25mbGljdCBjaGVjay5cbiAqXG4gKiBEZWR1cCBpcyBieSBrZXk6IHRoZSB0cmFjZWQgYG5leHRgIGNsb3N1cmUgaXMgbWVyZ2VkIGludG8gZXZlcnkgb3V0cHV0J3NcbiAqIGBhc3NldHNgIChgZ2V0U2hhcmVkTm9kZUFzc2V0c2Ag4oaSIGBzaGFyZWROb2RlQXNzZXRzYCksIHNvIE4gb3V0cHV0c1xuICogb3ZlcndoZWxtaW5nbHkgcmVwZWF0IGtleXMuIFdoYXQgdGhlIGhhc2hlcyBidXkgaXMgZGV0ZWN0aW5nIHR3byBvdXRwdXRzXG4gKiBtYXBwaW5nIHRoZSAqKnNhbWUga2V5IHRvIGRpZmZlcmVudCBjb250ZW50KiosIHdoaWNoIGlzIHVucGFja2FnZWFibGUgaW50b1xuICogb25lIExhbWJkYSDigJQgZmFpbCB0aGUgYnVpbGQgbG91ZGx5IHJhdGhlciB0aGFuIGxldHRpbmcgbGFzdC13cml0ZS13aW5zIHBpY2suXG4gKi9cbmZ1bmN0aW9uIGNvbGxlY3RTdGFnaW5nUGxhbihcbiAgY3R4OiBCdWlsZENvbXBsZXRlQ29udGV4dCxcbiAgaW52b2NhYmxlOiBJbnZvY2FibGVPdXRwdXRbXSxcbik6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCB7IHJlcG9Sb290IH0gPSBjdHg7XG4gIGNvbnN0IHN0YWdpbmcgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICBjb25zdCBoYXNoZXMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuXG4gIGNvbnN0IGFkZCA9IChrZXk6IHN0cmluZywgc291cmNlOiBzdHJpbmcsIGhhc2g/OiBzdHJpbmcpID0+IHtcbiAgICBhc3NlcnRTdGFnaW5nS2V5KGtleSwgc291cmNlKTtcbiAgICBjb25zdCBleGlzdGluZ0hhc2ggPSBoYXNoZXMuZ2V0KGtleSk7XG4gICAgaWYgKFxuICAgICAgaGFzaCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBleGlzdGluZ0hhc2ggIT09IHVuZGVmaW5lZCAmJlxuICAgICAgZXhpc3RpbmdIYXNoICE9PSBoYXNoXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke0xPR19QUkVGSVh9IFR3byBidWlsZCBvdXRwdXRzIG1hcCBcIiR7a2V5fVwiIHRvIGRpZmZlcmVudCBjb250ZW50IGAgK1xuICAgICAgICAgIGAoaGFzaGVzICR7ZXhpc3RpbmdIYXNofSBhbmQgJHtoYXNofSkuIE9uZSBkZXBsb3ltZW50IHBhY2thZ2UgY2Fubm90IGAgK1xuICAgICAgICAgIGBob2xkIGJvdGguIFRoaXMgdXN1YWxseSBtZWFucyB0d28gTmV4dC5qcyBwcm9qZWN0cyBpbiB0aGUgc2FtZSByZXBvIGAgK1xuICAgICAgICAgIGB3cml0ZSB0aGUgc2FtZSByZXBvLXJvb3QtcmVsYXRpdmUgcGF0aC5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKGhhc2ggIT09IHVuZGVmaW5lZCkge1xuICAgICAgaGFzaGVzLnNldChrZXksIGhhc2gpO1xuICAgIH1cbiAgICBpZiAoIXN0YWdpbmcuaGFzKGtleSkpIHtcbiAgICAgIHN0YWdpbmcuc2V0KGtleSwgc291cmNlKTtcbiAgICB9XG4gIH07XG5cbiAgZm9yIChjb25zdCBvdXRwdXQgb2YgaW52b2NhYmxlKSB7XG4gICAgZm9yIChjb25zdCBba2V5LCBzb3VyY2VdIG9mIE9iamVjdC5lbnRyaWVzKG91dHB1dC5hc3NldHMpKSB7XG4gICAgICBhZGQoa2V5LCBzb3VyY2UsIG91dHB1dC5hc3NldHNIYXNoZXNba2V5XSk7XG4gICAgfVxuICAgIC8vIFRoZSBlbnRyeXBvaW50J3Mgb3duIGZpbGUgaXMgZGVsaWJlcmF0ZWx5IGFic2VudCBmcm9tIGl0cyBgYXNzZXRzYCDigJQgdGhlXG4gICAgLy8gTkZUIHRyYWNlIGNvdmVycyB0aGUgY2xvc3VyZSBpdCByZXF1aXJlcywgbm90IGl0c2VsZi4gYGFzc2V0c0hhc2hlc2AgZG9lc1xuICAgIC8vIGNhcnJ5IGl0IChrZXllZCB0aGUgc2FtZSB3YXkpLCB3aGljaCBpcyBhbHNvIHdoYXQgcGlucyB0aGUga2V5IGZvcm1hdC5cbiAgICBjb25zdCBlbnRyeUtleSA9IHRvUG9zaXgocmVsYXRpdmUocmVwb1Jvb3QsIG91dHB1dC5maWxlUGF0aCkpO1xuICAgIGFkZChlbnRyeUtleSwgb3V0cHV0LmZpbGVQYXRoLCBvdXRwdXQuYXNzZXRzSGFzaGVzW2VudHJ5S2V5XSk7XG4gIH1cblxuICAvLyBKb2IgMiwgc2Vjb25kIGhhbGY6IGB3cml0ZVN0YW5kYWxvbmVEaXJlY3RvcnlgIGZpbHRlcnMgYGxvYWRlZEVudkZpbGVzYCB0b1xuICAvLyBleGFjdGx5IHRoZXNlIHR3byBhbmQgY29waWVzIHRoZW07IGBidWlsZC1jb21wbGV0ZS5qc2AgaGFzIG5vIGVudi1maWxlXG4gIC8vIGhhbmRsaW5nIGF0IGFsbCwgc28gdGhleSBhcmUgbm90IGluIGFueSBgYXNzZXRzYCBtYXAuXG4gIGZvciAoY29uc3QgZW52RmlsZSBvZiBFTlZfRklMRVMpIHtcbiAgICBjb25zdCBzb3VyY2UgPSBqb2luKGN0eC5wcm9qZWN0RGlyLCBlbnZGaWxlKTtcbiAgICBpZiAoZXhpc3RzU3luYyhzb3VyY2UpKSB7XG4gICAgICBhZGQodG9Qb3NpeChyZWxhdGl2ZShyZXBvUm9vdCwgc291cmNlKSksIHNvdXJjZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN0YWdpbmc7XG59XG5cbi8qKlxuICogSm9iIDIsIHRoaXJkIHBhcnQ6IHRoZSBzdGF0aWMgZmlsZXMgdGhlICpydW50aW1lKiBoYXMgdG8gc2VydmUsIGFuZCB0aGVpclxuICogc291cmNlcy5cbiAqXG4gKiBgb3V0cHV0cy5zdGF0aWNGaWxlc2AgbWl4ZXMgdHdvIHBvcHVsYXRpb25zIHdpdGggdGhlIHNhbWUgYFNUQVRJQ19GSUxFYCB0eXBlOlxuICpcbiAqIC0gKipgPGRpc3REaXI+L3N0YXRpYy8qKmAgYW5kIGBwdWJsaWMvKipgKiog4oCUIHVwbG9hZGVkIHRvIFMzIGJ5XG4gKiAgIGBOZXh0anNTdGF0aWNBc3NldHNgLCBhbmQgQ2xvdWRGcm9udCAvIEFQSSBHYXRld2F5IGFuc3dlciB0aGVtIGJlZm9yZSB0aGVcbiAqICAgcmVxdWVzdCBldmVyIHJlYWNoZXMgdGhlIGNvbXB1dGUuIE5vdCBzdGFnZWQ6IGBwdWJsaWMvYCBhbG9uZSBjYW4gYmVcbiAqICAgaHVuZHJlZHMgb2YgbWVnYWJ5dGVzIGFnYWluc3QgYSAyNTAgTUIgdW56aXBwZWQgTGFtYmRhIGNhcCwgYW5kIGl0IHdvdWxkIGJlXG4gKiAgIGEgc2Vjb25kIGNvcHkgb2YgYnl0ZXMgYWxyZWFkeSBpbiBTMy4gYHB1YmxpYy9gIGlzIG5vdCBpblxuICogICBgb3V0cHV0cy5zdGF0aWNGaWxlc2AgYXQgYWxsIOKAlCBOZXh0LmpzIGxpc3RzIGl0IG9ubHkgZm9yIGBvdXRwdXQ6IFwiZXhwb3J0XCJgXG4gKiAgIOKAlCBhbmQgaXQgaXMgZGVsaWJlcmF0ZWx5IG5vdCBhZGRlZCBoZXJlOiB0aGUgY29udGFpbmVyIHJ1bnRpbWUgbGlzdHMgaXQgb2ZmXG4gKiAgIGRpc2sgYXQgY29sZCBzdGFydCBpbnN0ZWFkLCBhcyBgbmV4dCBzdGFydGAgZG9lcyAoYHJlYWRQdWJsaWNGaWxlc2AgaW5cbiAqICAgYHNyYy9ydW50aW1lL3B1YmxpYy1maWxlcy50c2ApLCBiZWNhdXNlIG9ubHkgdGhlIGRpc2sga25vd3Mgd2hhdCBhbiBhcHAnc1xuICogICBgcG9zdGJ1aWxkYCB3cm90ZSBpbnRvIGl0IGFmdGVyIHRoaXMgaG9vayByYW4uXG4gKiAtICoqZXZlcnl0aGluZyBlbHNlKiosIGFsbCBvZiBpdCB1bmRlciBgPGRpc3REaXI+L3NlcnZlci9gIOKAlCBgNDA0Lmh0bWxgLFxuICogICBgNTAwLmh0bWxgLCBgZmF2aWNvbi5pY28uYm9keWAsIGFuZCBmdWxseS1zdGF0aWMgUGFnZXMgUm91dGVyIEhUTUwuIE5vdGhpbmdcbiAqICAgaW4gZnJvbnQgb2YgdGhlIGNvbXB1dGUgc2VydmVzIHRoZXNlLCBzbyB0aGV5IGFyZSBzdGFnZWQuIEJvdW5kZWQgYnkgcm91dGVcbiAqICAgY291bnQgYW5kIHNtYWxsLlxuICpcbiAqIFRoZSBwYXRobmFtZSDihpIga2V5IG1hcCBpcyByZXR1cm5lZCBmb3IgKmFsbCogb2YgdGhlbSwgYmVjYXVzZSBkaXNwYXRjaCBoYXMgdG9cbiAqIHJlc29sdmUgYSBwYXRobmFtZSB0byBcInN0YXRpYyBmaWxlLCBub3QgYSA0MDRcIiBlaXRoZXIgd2F5OyB0aGUgcnVudGltZSA0MDRzIGlmXG4gKiB0aGUgZmlsZSB0dXJucyBvdXQgbm90IHRvIGJlIGluIHRoZSBwYWNrYWdlLCB3aGljaCBpcyBvbmx5IHJlYWNoYWJsZSB3aGVuIHRoZVxuICogZGlzdHJpYnV0aW9uIGlzIG1pc3JvdXRlZC5cbiAqXG4gKiBTdGFnaW5nIGlzIHtAbGluayBzdGFnZVNlcnZlZFN0YXRpY0ZpbGVzfSwgYXBwbGllZCBvbmNlIHBlciBkZXBsb3ltZW50IHJvb3QuXG4gKi9cbmZ1bmN0aW9uIGNvbGxlY3RTdGF0aWNGaWxlcyhjdHg6IEJ1aWxkQ29tcGxldGVDb250ZXh0KTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHsgcmVwb1Jvb3QgfSA9IGN0eDtcbiAgY29uc3QgYmFzZVBhdGggPSBjdHguY29uZmlnLmJhc2VQYXRoIHx8IFwiXCI7XG4gIGNvbnN0IHN0YXRpY0ZpbGVzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgY29uc3QgcGFnZXNEaXIgPSBqb2luKGN0eC5kaXN0RGlyLCBcInNlcnZlclwiLCBcInBhZ2VzXCIpICsgc2VwO1xuXG4gIGZvciAoY29uc3Qgb3V0cHV0IG9mIGN0eC5vdXRwdXRzLnN0YXRpY0ZpbGVzKSB7XG4gICAgY29uc3Qga2V5ID0gdG9Qb3NpeChyZWxhdGl2ZShyZXBvUm9vdCwgb3V0cHV0LmZpbGVQYXRoKSk7XG4gICAgY29uc3QgcGF0aG5hbWVzID0gcm91dGFibGVQYXRobmFtZXMoXG4gICAgICBvdXRwdXQucGF0aG5hbWUsXG4gICAgICBiYXNlUGF0aCxcbiAgICAgIG91dHB1dC5maWxlUGF0aC5zdGFydHNXaXRoKHBhZ2VzRGlyKSxcbiAgICApO1xuICAgIGZvciAoY29uc3QgcGF0aG5hbWUgb2YgcGF0aG5hbWVzKSB7XG4gICAgICBjb25zdCBleGlzdGluZyA9IHN0YXRpY0ZpbGVzLmdldChwYXRobmFtZSk7XG4gICAgICBpZiAoZXhpc3RpbmcgIT09IHVuZGVmaW5lZCAmJiBleGlzdGluZyAhPT0ga2V5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgJHtMT0dfUFJFRklYfSBUd28gc3RhdGljIGZpbGVzIGNsYWltIHRoZSBwYXRobmFtZSBgICtcbiAgICAgICAgICAgIGBcIiR7cGF0aG5hbWV9XCIgKFwiJHtleGlzdGluZ31cIiBhbmQgXCIke2tleX1cIikuIERpc3BhdGNoIGNhbm5vdCBgICtcbiAgICAgICAgICAgIGBjaG9vc2UgYmV0d2VlbiB0aGVtLmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzdGF0aWNGaWxlcy5zZXQocGF0aG5hbWUsIGtleSk7XG4gICAgfVxuICB9XG5cbiAgLy8gU29ydGVkIGJlY2F1c2Ugb2JqZWN0IGtleXMga2VlcCBpbnNlcnRpb24gb3JkZXIsIGFuZCBhIGJ5dGUtc3RhYmxlXG4gIC8vIGBtYW5pZmVzdC5qc29uYCBpcyB3aGF0IGtlZXBzIGl0IGRpZmZhYmxlIGFuZCB0aGUgQ0RLIGFzc2V0IGhhc2ggZnJvbVxuICAvLyBjaHVybmluZy5cbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICBbLi4uc3RhdGljRmlsZXNdLnNvcnQoKFthXSwgW2JdKSA9PiAoYSA8IGIgPyAtMSA6IDEpKSxcbiAgKTtcbn1cblxuLyoqXG4gKiBUaGUgcGF0aG5hbWVzIGFuIG91dHB1dCBhbnN3ZXJzLCB3aGljaCBmb3Igb25lIHNoYXBlIGlzIG5vdCB0aGUgcGF0aG5hbWVcbiAqIGBuZXh0IGJ1aWxkYCByZXBvcnRlZC5cbiAqXG4gKiAqKkEgUGFnZXMgUm91dGVyIGhvbWUgcGFnZSBhcnJpdmVzIGFzIGAvaW5kZXhgLioqIFRoZSBhZGFwdGVyIGhvb2sgZGVyaXZlcyBldmVyeVxuICogUGFnZXMgcGF0aG5hbWUgd2l0aCBgbm9ybWFsaXplUGFnZVBhdGgocGFnZSlgLCBhbmQgYG5vcm1hbGl6ZVBhZ2VQYXRoKFwiL1wiKWAgaXNcbiAqIGBcIi9pbmRleFwiYCAoYG5leHQvZGlzdC9zaGFyZWQvbGliL3BhZ2UtcGF0aC9ub3JtYWxpemUtcGFnZS1wYXRoLmpzYCkg4oCUIGZvciB0aGVcbiAqIGBQQUdFU2Agb3V0cHV0IG9mIGFuIFNTRyBvciBTU1IgaG9tZSBwYWdlIGFuZCBmb3IgdGhlIGBTVEFUSUNfRklMRWAgb2YgYVxuICogZnVsbHktc3RhdGljIG9uZSBhbGlrZS4gYC9pbmRleGAgaXMgbm90IGEgVVJMIGFueW9uZSByZXF1ZXN0cywgYW5kIG5vdGhpbmcgZWxzZVxuICogaW4gdGhlIG91dHB1dHMgY2FycmllcyBgL2AgZm9yIHRoYXQgcGFnZSwgc28gd2l0aG91dCB0aGlzIHRoZSBob21lIHBhZ2UgaXMgaW5cbiAqIG5laXRoZXIgYG1hbmlmZXN0LnBhdGhuYW1lc2Agbm9yIGBtYW5pZmVzdC5lbnRyeXBvaW50c2AvYHN0YXRpY0ZpbGVzYCwgYW5kIGV2ZXJ5XG4gKiByZXF1ZXN0IHRvIGAvYCA0MDRzIHdoaWxlIGV2ZXJ5IG90aGVyIHBhZ2Ugb2YgdGhlIHNhbWUgYXBwIHNlcnZlcy4gTWVhc3VyZWRcbiAqIGFnYWluc3QgbmV4dC5qcydzIGB0ZXN0L2UyZS9uZXctbGluay1iZWhhdmlvcmAgKGAvYCByZXR1cm5lZCB0aGUgYnVpbHQtaW4gNDA0LFxuICogdGhlIHNpeCBvdGhlciBwYWdlcyB3ZXJlIGZpbmUpIGFuZCBgdGVzdC9lMmUvcHJlcmVuZGVyLXByZXZpZXdgICh0aGUgb25lIGNhc2VcbiAqIHRoYXQgZmV0Y2hlcyBgL2AgZ290IHRoZSA0MDQgcGFnZSdzIEhUTUwsIHRoZSBlaWdodCB0aGF0IGhpdCBBUEkgcm91dGVzIHBhc3NlZCkuXG4gKlxuICogUGFnZXMgUm91dGVyIG91dHB1dHMgb25seSwgd2hpY2ggaXMgd2hhdCBgZnJvbVBhZ2VzUm91dGVyYCBzYXlzLiBBcHAgUm91dGVyXG4gKiByZXBvcnRzIGl0cyBob21lIHBhZ2UgYXMgYC9gIGFuZCBvbmx5IHRoZSBSU0Mgc2libGluZyBhcyBgL2luZGV4LnJzY2AsIHNvIGFuXG4gKiBBcHAgUm91dGVyIGAvaW5kZXhgIGlzIGBhcHAvaW5kZXgvcGFnZS50c3hgIOKAlCBhIHJlYWwgcm91dGUgYXQgYC9pbmRleGAsIGFuZFxuICogbWFwcGluZyBpdCB0byBgL2AgbWFkZSBhbiBhcHAgd2l0aCBib3RoIHBhZ2VzIGZhaWwgdGhlIGJ1aWxkIG9uIGEgcGF0aG5hbWVcbiAqIGNvbGxpc2lvbiwgYW5kIGFuIGFwcCB3aXRoIG9ubHkgdGhlIHNlY29uZCBzZXJ2ZSBpdCBhdCBgL2AuIFRoZSBzYW1lIGdvZXMgZm9yXG4gKiBhIGBwdWJsaWMvaW5kZXhgIGZpbGUuXG4gKlxuICogQm90aCBwYXRobmFtZXMgYXJlIHJlZ2lzdGVyZWQuIGAvYCBiZWNhdXNlIGl0IGlzIHRoZSByZWFsIG9uZTsgYC9pbmRleGAgYmVjYXVzZVxuICogbmV4dCdzIG93biBtaW5pbWFsIG1vZGUg4oCUIHRoZSBtb2RlIG91ciBydW50aW1lIHJ1bnMgaW4g4oCUIGFjY2VwdHMgaXQsIHJld3JpdGluZ1xuICogYHJlcS51cmxgIGFuZCBgeC1tYXRjaGVkLXBhdGhgIGZyb20gYC9pbmRleGAgdG8gYC9gIGJlZm9yZSBtYXRjaGluZ1xuICogKGBiYXNlLXNlcnZlci50c2AsIFwiaW4gbWluaW1hbCBtb2RlXCIpLCBzbyBkcm9wcGluZyBpdCB3b3VsZCBiZSBhIGRpdmVyZ2VuY2UgaW5cbiAqIHRoZSBvdGhlciBkaXJlY3Rpb24uXG4gKlxuICogVW5hbWJpZ3VvdXMgd2l0aGluIHRoZSBQYWdlcyBSb3V0ZXIgZGVzcGl0ZSB0aGUgY29sbGlzaW9uIGl0IGxvb2tzIGxpa2U6XG4gKiBgbm9ybWFsaXplUGFnZVBhdGgoXCIvaW5kZXhcIilgIGlzIGBcIi9pbmRleC9pbmRleFwiYCwgc28gYSByZXBvcnRlZCBgL2luZGV4YCBjYW5cbiAqIG9ubHkgaGF2ZSBjb21lIGZyb20gdGhlIHBhZ2UgYC9gLlxuICogVGhlIGRhdGEgcm91dGUgb2YgdGhlIHNhbWUgcGFnZSwgYC9fbmV4dC9kYXRhLzxidWlsZElkPi9pbmRleC5qc29uYCwgYW5kIGFuIEFwcFxuICogUm91dGVyIGAvaW5kZXgucnNjYCBhcmUgYm90aCByZWFsIFVSTHMgYW5kIGFyZSBsZWZ0IGFsb25lIGJ5IHRoZSBleGFjdCBtYXRjaC5cbiAqL1xuZnVuY3Rpb24gcm91dGFibGVQYXRobmFtZXMoXG4gIHBhdGhuYW1lOiBzdHJpbmcsXG4gIGJhc2VQYXRoOiBzdHJpbmcsXG4gIGZyb21QYWdlc1JvdXRlcjogYm9vbGVhbixcbik6IHN0cmluZ1tdIHtcbiAgaWYgKCFmcm9tUGFnZXNSb3V0ZXIgfHwgcGF0aG5hbWUgIT09IGAke2Jhc2VQYXRofS9pbmRleGApIHtcbiAgICByZXR1cm4gW3BhdGhuYW1lXTtcbiAgfVxuICAvLyBgYmFzZVBhdGggfHwgXCIvXCJgLCBub3QgYCR7YmFzZVBhdGh9L2A6IHdpdGggYGJhc2VQYXRoOiBcIi9wcm9kXCJgIHRoZSBob21lIHBhZ2VcbiAgLy8gaXMgYC9wcm9kYCwgd2hpY2ggaXMgaG93IHRoZSBBcHAgUm91dGVyIGZpeHR1cmVzIHJlcG9ydCB0aGVpcnMuXG4gIHJldHVybiBbYmFzZVBhdGggfHwgXCIvXCIsIHBhdGhuYW1lXTtcbn1cblxuLyoqXG4gKiBBZGQgdGhlIHN0YXRpYyBmaWxlcyB0aGUgKnJ1bnRpbWUqIHNlcnZlcyB0byBhIHN0YWdpbmcgcGxhbiDigJQgdGhlIFwiZXZlcnl0aGluZ1xuICogZWxzZVwiIHBvcHVsYXRpb24gZGVzY3JpYmVkIG9uIHtAbGluayBjb2xsZWN0U3RhdGljRmlsZXN9LCBhbGwgb2YgaXQgdW5kZXJcbiAqIGA8ZGlzdERpcj4vc2VydmVyL2AuXG4gKlxuICogU2VwYXJhdGUgZnJvbSBidWlsZGluZyB0aGUgbWFuaWZlc3QncyBgc3RhdGljRmlsZXNgIG1hcCBiZWNhdXNlIHRoZSBtYXAgaXMgdGhlXG4gKiBzYW1lIGZvciBldmVyeSBncm91cCB3aGlsZSB0aGUgc3RhZ2luZyBpcyBhcHBsaWVkIG9uY2UgcGVyIGRlcGxveW1lbnQgcm9vdDpcbiAqIGFueSBncm91cCBjYW4gYmUgYXNrZWQgZm9yIGAvNDA0YCwgc28gZXZlcnkgZ3JvdXAgc2hpcHMgdGhlc2UuXG4gKi9cbmZ1bmN0aW9uIHN0YWdlU2VydmVkU3RhdGljRmlsZXMoXG4gIGN0eDogQnVpbGRDb21wbGV0ZUNvbnRleHQsXG4gIHN0YWdpbmc6IE1hcDxzdHJpbmcsIHN0cmluZz4sXG4pOiB2b2lkIHtcbiAgY29uc3QgeyByZXBvUm9vdCwgZGlzdERpciB9ID0gY3R4O1xuICBjb25zdCBjbGllbnRTdGF0aWNEaXIgPSBqb2luKGRpc3REaXIsIFwic3RhdGljXCIpICsgc2VwO1xuXG4gIGZvciAoY29uc3Qgb3V0cHV0IG9mIGN0eC5vdXRwdXRzLnN0YXRpY0ZpbGVzKSB7XG4gICAgY29uc3Qgc2VydmVkQnlTMyA9XG4gICAgICBvdXRwdXQuZmlsZVBhdGguc3RhcnRzV2l0aChjbGllbnRTdGF0aWNEaXIpIHx8XG4gICAgICAhb3V0cHV0LmZpbGVQYXRoLnN0YXJ0c1dpdGgoZGlzdERpciArIHNlcCk7XG4gICAgaWYgKHNlcnZlZEJ5UzMpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBrZXkgPSB0b1Bvc2l4KHJlbGF0aXZlKHJlcG9Sb290LCBvdXRwdXQuZmlsZVBhdGgpKTtcbiAgICBhc3NlcnRTdGFnaW5nS2V5KGtleSwgb3V0cHV0LmZpbGVQYXRoKTtcbiAgICBzdGFnaW5nLnNldChrZXksIG91dHB1dC5maWxlUGF0aCk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgaW52YXJpYW50IGJlaGluZCBgbWFuaWZlc3QucmVsYXRpdmVQcm9qZWN0RGlyYDogYG5leHQgYnVpbGRgIG11c3QgcnVuIGZyb21cbiAqIHRoZSBwcm9qZWN0IGRpcmVjdG9yeS5cbiAqXG4gKiBOZXh0IGlubGluZXMgYHJlbGF0aXZlKHByb2Nlc3MuY3dkKCksIHByb2plY3REaXIpYCBpbnRvIGV2ZXJ5IGVudHJ5cG9pbnRcbiAqIChgZGVmaW5lLWVudi5qc2ApIGFuZCB0aGUgYnVpbHQgY29kZSByZXNvbHZlcyBpdCBhZ2FpbnN0IHRoZSAqcnVudGltZSpcbiAqIGBwcm9jZXNzLmN3ZCgpYC4gS2VlcGluZyBidWlsZCBjd2QgYW5kIHByb2plY3QgZGlyIGVxdWFsIG1ha2VzIHRoYXQgaW5saW5lZFxuICogdmFsdWUgYFwiXCJgLCBzbyB0aGUgcnVudGltZSBvbmx5IGhhcyB0byBgY2hkaXJgIHRvIHRoZSBzdGFnZWQgcHJvamVjdCBkaXIuIEFcbiAqIGJ1aWxkIHJ1biBmcm9tIGVsc2V3aGVyZSB3b3VsZCBpbmxpbmUgYSBub24tZW1wdHkgcmVsYXRpdmUgcGF0aCDigJQgb2Z0ZW4gb25lXG4gKiBwb2ludGluZyBvdXRzaWRlIHRoZSBzdGFnaW5nIHRyZWUg4oCUIGFuZCBldmVyeSBlbnRyeXBvaW50IHdvdWxkIGZhaWwgdG8gZmluZFxuICogYHJlcXVpcmVkLXNlcnZlci1maWxlcy5qc29uYCBhdCBydW50aW1lIHdpdGggbm8gaGludCBhcyB0byB3aHkuXG4gKi9cbmZ1bmN0aW9uIGFzc2VydEJ1aWxkQ3dkKGN0eDogQnVpbGRDb21wbGV0ZUNvbnRleHQsIGJ1aWxkQ3dkOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgY3dkID0gcmVzb2x2ZShidWlsZEN3ZCk7XG4gIGlmIChjd2QgPT09IHJlc29sdmUoY3R4LnByb2plY3REaXIpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgJHtMT0dfUFJFRklYfSBcXGBuZXh0IGJ1aWxkXFxgIG11c3QgcnVuIGZyb20gdGhlIE5leHQuanMgcHJvamVjdCBgICtcbiAgICAgIGBkaXJlY3RvcnkuIEl0IHJhbiBmcm9tIFwiJHtjd2R9XCIgd2l0aCB0aGUgcHJvamVjdCBhdCBgICtcbiAgICAgIGBcIiR7Y3R4LnByb2plY3REaXJ9XCIuIE5leHQuanMgYmFrZXMgdGhlIHJlbGF0aXZlIHBhdGggYmV0d2VlbiB0aG9zZSB0d28gYCArXG4gICAgICBgaW50byBldmVyeSBidWlsdCBlbnRyeXBvaW50LCBhbmQgY2RrLW5leHRqcyBjYW5ub3QgcmVwcm9kdWNlIHRoYXQgbGF5b3V0IGAgK1xuICAgICAgYGluIHRoZSBkZXBsb3ltZW50IHBhY2thZ2UuIENoYW5nZSBkaXJlY3RvcnkgZmlyc3QgKFxcYGNkIGAgK1xuICAgICAgYCR7cmVsYXRpdmUoY3dkLCBjdHgucHJvamVjdERpcikgfHwgXCIuXCJ9ICYmIG5leHQgYnVpbGRcXGApIGluc3RlYWQgb2YgYCArXG4gICAgICBgcGFzc2luZyB0aGUgZGlyZWN0b3J5IGFzIGFuIGFyZ3VtZW50OyBpbiBhIG1vbm9yZXBvLCBydW4gdGhlIGFwcCdzIG93biBgICtcbiAgICAgIGBidWlsZCBzY3JpcHQgZnJvbSBpdHMgZGlyZWN0b3J5IChlLmcuIFxcYHBucG0gLS1maWx0ZXIgPGFwcD4gYnVpbGRcXGAsIGAgK1xuICAgICAgYHdoaWNoIHJ1bnMgaW4gdGhlIHBhY2thZ2UgZGlyZWN0b3J5KS5gLFxuICApO1xufVxuXG5mdW5jdGlvbiBhZGRFbnRyeXBvaW50KFxuICBlbnRyeXBvaW50czogUmVjb3JkPHN0cmluZywgQWRhcHRlckVudHJ5cG9pbnQ+LFxuICByZXBvUm9vdDogc3RyaW5nLFxuICBvdXRwdXQ6IHsgaWQ6IHN0cmluZzsgcGF0aG5hbWU6IHN0cmluZzsgZmlsZVBhdGg6IHN0cmluZyB9LFxuICB0eXBlOiBBZGFwdGVyRW50cnlwb2ludFR5cGUsXG4gIGJhc2VQYXRoOiBzdHJpbmcsXG4pOiB2b2lkIHtcbiAgY29uc3QgZmlsZVBhdGggPSB0b1Bvc2l4KHJlbGF0aXZlKHJlcG9Sb290LCBvdXRwdXQuZmlsZVBhdGgpKTtcbiAgY29uc3QgcGF0aG5hbWVzID0gcm91dGFibGVQYXRobmFtZXMoXG4gICAgb3V0cHV0LnBhdGhuYW1lLFxuICAgIGJhc2VQYXRoLFxuICAgIHR5cGUgPT09IFwicGFnZVwiLFxuICApO1xuICBmb3IgKGNvbnN0IHBhdGhuYW1lIG9mIHBhdGhuYW1lcykge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gZW50cnlwb2ludHNbcGF0aG5hbWVdO1xuICAgIGlmIChleGlzdGluZyAmJiBleGlzdGluZy5maWxlUGF0aCAhPT0gZmlsZVBhdGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7TE9HX1BSRUZJWH0gVHdvIGJ1aWxkIG91dHB1dHMgY2xhaW0gdGhlIHBhdGhuYW1lIFwiJHtwYXRobmFtZX1cIiBgICtcbiAgICAgICAgICBgKFwiJHtleGlzdGluZy5maWxlUGF0aH1cIiBhbmQgXCIke2ZpbGVQYXRofVwiKS4gRGlzcGF0Y2ggY2Fubm90IGNob29zZSBgICtcbiAgICAgICAgICBgYmV0d2VlbiB0aGVtLmAsXG4gICAgICApO1xuICAgIH1cbiAgICBlbnRyeXBvaW50c1twYXRobmFtZV0gPSB7IGlkOiBvdXRwdXQuaWQsIGZpbGVQYXRoLCB0eXBlIH07XG4gIH1cbn1cblxuLyoqXG4gKiBBZGQgdGhlICpwcmVyZW5kZXIqIHBhdGhuYW1lcyB0aGF0IG5vIGludm9jYWJsZSBvdXRwdXQgY2xhaW1zIGFuZCB0aGF0IHJvdXRpbmdcbiAqIGNhbm5vdCBvdGhlcndpc2UgcmVhY2guXG4gKlxuICogYHJlc29sdmVSb3V0ZXNgIGNhbiBvbmx5IG1hdGNoIGEgcGF0aG5hbWUgcHJlc2VudCBpbiBgbWFuaWZlc3QucGF0aG5hbWVzYCwgYW5kXG4gKiBmb3IgYSBkeW5hbWljIG1hdGNoIGl0IHJldHVybnMgdGhlICoqdGVtcGxhdGUqKiBpdCBtYXRjaGVkLiBSb3V0ZXMgYW5kIHN0YXRpY1xuICogZmlsZXMgY292ZXIgbW9zdCBvZiB0aGF0OyB0d28gc2hhcGVzIHRoZXkgbWlzczpcbiAqXG4gKiAxLiAqKlRlbXBsYXRlcy4qKiBBIHJlcXVlc3QgZm9yIGAvX25leHQvZGF0YS88YnVpbGRJZD4vZnIvYmxvZy9oZWxsby5qc29uYCBvbmx5XG4gKiAgICByZXNvbHZlcyBpZiBgL19uZXh0L2RhdGEvPGJ1aWxkSWQ+L2ZyL2Jsb2cvW3NsdWddLmpzb25gIGlzIGxpc3RlZCwgYW5kIHRoYXRcbiAqICAgIHBhdGhuYW1lIGV4aXN0cyBzb2xlbHkgYXMgYSBgcHJlcmVuZGVyc2AgZW50cnkuXG4gKiAxYi4gKipBIHN0YXRpYyBgZ2V0U3RhdGljUHJvcHNgIHBhZ2UncyBkYXRhIHJvdXRlLioqIGAvX25leHQvZGF0YS88YnVpbGRJZD4vZ3NwLmpzb25gXG4gKiAgICBoYXMgbm8gdGVtcGxhdGUgdG8gbWF0Y2ggYW5kIG5vIHJ1bGUgb2YgaXRzIG93bjogYG5leHQgYnVpbGRgIG9ubHkgZW1pdHMgYVxuICogICAgYGR5bmFtaWNSb3V0ZXNgIHJ1bGUgZm9yIGEgZGF0YSByb3V0ZSB3aGVuIHRoZSBwYWdlIGlzIGR5bmFtaWMgKm9yKiB0aGUgYXBwIGhhc1xuICogICAgbWlkZGxld2FyZSAoYGJ1aWxkLWNvbXBsZXRlLnRzYCwgYG5lZWRzTWlkZGxld2FyZVJlc29sdmVSb3V0ZXNgLCB3aGljaCBpcyBhbHNvXG4gKiAgICB3aGF0IGByb3V0aW5nLnNob3VsZE5vcm1hbGl6ZU5leHREYXRhYCByZXBvcnRzKS4gV2l0aG91dCBtaWRkbGV3YXJlIE5leHQuanNcbiAqICAgIGV4cGVjdHMgdGhlIHBsYXRmb3JtIHRvIHNlcnZlIHRoZSBkYXRhIHJvdXRlIGFzIGFuIG91dHB1dCwgYnkgcGF0aG5hbWUg4oCUIHNvIGFcbiAqICAgIGNvbmNyZXRlIGRhdGEtcm91dGUgcHJlcmVuZGVyIGlzIHJlZ2lzdGVyZWQgd2hhdGV2ZXIgdGhlIHJ1bGVzIHNheS4gTWlzc2luZyBpdFxuICogICAgdHVybmVkIGV2ZXJ5IGNsaWVudC1zaWRlIG5hdmlnYXRpb24gaW50byBzdWNoIGEgcGFnZSBpbnRvIGEgZnVsbCBwYWdlIGxvYWQsXG4gKiAgICBiZWNhdXNlIHRoZSByb3V0ZXIncyBgLmpzb25gIGZldGNoIDQwNCdkOiBtZWFzdXJlZCBhZ2FpbnN0XG4gKiAgICBgdGVzdC9lMmUvbm8tcGFnZS1wcm9wc2AuIE9ubHkgd2hlbiBubyAqdW5nYXRlZCogcnVsZSBtYXRjaGVzLCBmb3IgdGhlIHJlYXNvblxuICogICAgYmVsb3cg4oCUIGEgZHluYW1pYyBwYWdlJ3MgYC/igKYvYmxvZy9oZWxsby5qc29uYCBtdXN0IGtlZXAgcmVzb2x2aW5nIHRvIGl0c1xuICogICAgYFtzbHVnXS5qc29uYCB0ZW1wbGF0ZSwgd2hpY2ggaXMgd2hlcmUgYG54dFBzbHVnYCBjb21lcyBmcm9tLlxuICogMi4gKipDb25jcmV0ZSBwYXRobmFtZXMgd2hvc2UgZHluYW1pYyByb3V0ZSBydWxlIGlzIGdhdGVkLioqIEEgcm91dGUgd2hvc2UgcGFyYW1zXG4gKiAgICBjYW4gbmV2ZXIgYmUgZmlsbGVkIGF0IHJlcXVlc3QgdGltZSDigJQgcm9vdCBwYXJhbXMgYXJlIHRoZSBjYXNlIHRoYXQgcHJvZHVjZWRcbiAqICAgIHRoaXMsIGBhcHAvW2xvY2FsZV0vcGFnZS50c3hgIHdpdGggYGdlbmVyYXRlU3RhdGljUGFyYW1zKClgIGFuZCBub1xuICogICAgYGFwcC9sYXlvdXQudHN4YCDigJQgZ2V0cyBpdHMgYGR5bmFtaWNSb3V0ZXNgIHJ1bGUgZW1pdHRlZCB3aXRoIGEgZHJhZnQtbW9kZVxuICogICAgYGhhc2Agb24gYF9fcHJlcmVuZGVyX2J5cGFzc2AuIE5leHQuanMgaXMgc2F5aW5nOiBpbnZva2UgdGhlIGZ1bmN0aW9uIG9ubHkgaW5cbiAqICAgIGRyYWZ0IG1vZGUsIGFuZCBvdGhlcndpc2Ugc2VydmUgdGhlIHByZXJlbmRlciB5b3Ugd2VyZSBoYW5kZWQuIFZlcmNlbCdzIENETlxuICogICAgZG9lcyB0aGF0IGZyb20gdGhlIG91dHB1dCBpdHNlbGY7IHdlIHJvdXRlIHRoZSByZXF1ZXN0IHRvIHRoZSBvd25pbmdcbiAqICAgIGVudHJ5cG9pbnQsIHdoaWNoIGFuc3dlcnMgaXQgb3V0IG9mIHRoZSBzZWVkZWQgY2FjaGUuIFdpdGhvdXQgdGhpcywgYC9lbmAgaXMgYVxuICogICAgNDA0IHdoaWxlIGBuZXh0IHN0YXJ0YCByZW5kZXJzIGl0IOKAlCBhbmQgc28gaXMgZXZlcnkgYC5yc2NgL2Auc2VnbWVudHNgXG4gKiAgICB2YXJpYW50LCB3aGljaCBpcyB3aHkgYSBjbGllbnQtc2lkZSBuYXZpZ2F0aW9uIGludG8gc3VjaCBhbiBhcHAgbmV2ZXJcbiAqICAgIGNvbXBsZXRlcy5cbiAqXG4gKiBBIGNvbmNyZXRlIHBhdGhuYW1lIGlzIGFkZGVkIG9ubHkgd2hlbiBhIGdhdGVkIHJ1bGUgbWF0Y2hlcyBpdCBhbmQgbm8gdW5nYXRlZFxuICogb25lIGRvZXMg4oCUIHRoZSBzZXQgdGhhdCB3b3VsZCA0MDQgdG9kYXkgKmFuZCogdGhhdCByb3V0aW5nIGNhbiBzdGlsbCBwcm9kdWNlLlxuICogQWRkaW5nIHRoZW0gdW5jb25kaXRpb25hbGx5IHdhcyBtZWFzdXJlZCB0byBiZSBhY3RpdmVseSB3cm9uZyB0d2ljZSBvdmVyOlxuICogYC9pc3IvMWAgcmVzb2x2ZXMgdG8gaXRzZWxmIHJhdGhlciB0aGFuIHRvIGAvaXNyL1tpZF1gLCBsb3NpbmcgdGhlIGBueHRQaWRgXG4gKiBxdWVyeSBwYXJhbSB0aGUgcm91dGUgbmVlZHMsIGFuZCBwYXRobmFtZXMgbm8gcnVsZSBtYXRjaGVzIGF0IGFsbCAoYSBzdGF0aWNcbiAqIHJvdXRlJ3MgYC5zZWdtZW50cy/igKZgIG91dHB1dHMsIHdoaWNoIGByZXNvbHZlUm91dGVzYCBuZXZlciBhc2tzIGZvcikgYXJlIGRlYWRcbiAqIG1hbmlmZXN0IHdlaWdodC4gTWF0Y2hpbmcgbWlycm9ycyBgcmVzb2x2ZVJvdXRlc2AsIHdoaWNoIGlzIGNhc2UtaW5zZW5zaXRpdmUgYnlcbiAqIGRlZmF1bHQuXG4gKlxuICogVGhlIG93bmluZyBlbnRyeXBvaW50IGNvbWVzIGZyb20gYHByZXJlbmRlci5yb3V0ZWAsIHdoaWNoIGlzIHRoZSB1bnByZWZpeGVkIGFuZFxuICogdW5sb2NhbGl6ZWQgc291cmNlIHJvdXRlIChgL2Jsb2cvW3NsdWddYCksIGhlbmNlIHRoZSBiYXNlUGF0aC10aGVuLWJhcmUgbGFkZGVyLlxuICogTG9jYWxlIHZhcmlhbnRzIG9mIG9uZSBwYWdlIHNoYXJlIGEgYGZpbGVQYXRoYCwgc28gYW55IGxvY2FsZSdzIGVudHJ5cG9pbnQgaXNcbiAqIHRoZSByaWdodCB0YXJnZXQuIEFuIFJTQyBvciBzZWdtZW50LXByZWZldGNoIHBhdGhuYW1lIHByZWZlcnMgdGhlIHJvdXRlJ3MgYC5yc2NgXG4gKiBlbnRyeXBvaW50LCBiZWNhdXNlIHRoYXQgaXMgdGhlIGtleSBgcmVzb2x2ZVJvdXRlc2AgcmVzb2x2ZXMgc3VjaCBhIHJlcXVlc3QgdG8uXG4gKi9cbmZ1bmN0aW9uIGFkZFByZXJlbmRlclBhdGhuYW1lcyhcbiAgZW50cnlwb2ludHM6IFJlY29yZDxzdHJpbmcsIEFkYXB0ZXJFbnRyeXBvaW50PixcbiAgcHJlcmVuZGVyczogQWRhcHRlck91dHB1dHNbXCJwcmVyZW5kZXJzXCJdLFxuICBkeW5hbWljUm91dGVzOiB7XG4gICAgc291cmNlUmVnZXg6IHN0cmluZztcbiAgICBoYXM/OiB1bmtub3duW107XG4gICAgbWlzc2luZz86IHVua25vd25bXTtcbiAgfVtdLFxuICBiYXNlUGF0aDogc3RyaW5nLFxuICBkYXRhUm91dGVQcmVmaXg6IHN0cmluZyxcbik6IHZvaWQge1xuICBjb25zdCBtYXRjaGVycyA9IGR5bmFtaWNSb3V0ZXMubWFwKChyb3V0ZSkgPT4gKHtcbiAgICByZWdleDogbmV3IFJlZ0V4cChyb3V0ZS5zb3VyY2VSZWdleCwgXCJpXCIpLFxuICAgIGdhdGVkOiBCb29sZWFuKHJvdXRlLmhhcz8ubGVuZ3RoIHx8IHJvdXRlLm1pc3Npbmc/Lmxlbmd0aCksXG4gIH0pKTtcbiAgY29uc3QgbWF0Y2hpbmdSdWxlcyA9IChwYXRobmFtZTogc3RyaW5nKSA9PlxuICAgIG1hdGNoZXJzLmZpbHRlcigoeyByZWdleCB9KSA9PiByZWdleC50ZXN0KHBhdGhuYW1lKSk7XG4gIGNvbnN0IG9ubHlHYXRlZFJ1bGVzTWF0Y2ggPSAocGF0aG5hbWU6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IG1hdGNoZWQgPSBtYXRjaGluZ1J1bGVzKHBhdGhuYW1lKTtcbiAgICByZXR1cm4gbWF0Y2hlZC5sZW5ndGggPiAwICYmIG1hdGNoZWQuZXZlcnkoKHsgZ2F0ZWQgfSkgPT4gZ2F0ZWQpO1xuICB9O1xuICAvKipcbiAgICogTm90aGluZyByZWFjaGVzIHRoaXMgcGF0aG5hbWUgYXQgcmVxdWVzdCB0aW1lOiBlaXRoZXIgbm8gcnVsZSBtYXRjaGVzIGl0IG9yXG4gICAqIGV2ZXJ5IHJ1bGUgdGhhdCBkb2VzIGlzIGdhdGVkLiBUaGUgZ2F0ZWQgaGFsZiBpcyB7QGxpbmsgb25seUdhdGVkUnVsZXNNYXRjaH07XG4gICAqIHRoZSBcIm5vIHJ1bGUgYXQgYWxsXCIgaGFsZiBvbmx5IGV2ZXIgaG9sZHMgZm9yIGEgZGF0YSByb3V0ZSwgYmVjYXVzZSBhIHBhZ2Unc1xuICAgKiBvd24gcGF0aG5hbWUgaXMgYW4gb3V0cHV0LlxuICAgKi9cbiAgY29uc3Qgbm90aGluZ1VuZ2F0ZWRNYXRjaGVzID0gKHBhdGhuYW1lOiBzdHJpbmcpOiBib29sZWFuID0+XG4gICAgbWF0Y2hpbmdSdWxlcyhwYXRobmFtZSkuZXZlcnkoKHsgZ2F0ZWQgfSkgPT4gZ2F0ZWQpO1xuXG4gIGNvbnN0IG9ycGhhbnM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgcHJlcmVuZGVyIG9mIHByZXJlbmRlcnMpIHtcbiAgICBjb25zdCB7IHBhdGhuYW1lIH0gPSBwcmVyZW5kZXI7XG4gICAgaWYgKGVudHJ5cG9pbnRzW3BhdGhuYW1lXSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IGlzVGVtcGxhdGUgPSBwYXRobmFtZS5pbmNsdWRlcyhcIltcIik7XG4gICAgY29uc3QgaXNEYXRhUm91dGUgPVxuICAgICAgcGF0aG5hbWUuc3RhcnRzV2l0aChkYXRhUm91dGVQcmVmaXgpICYmIHBhdGhuYW1lLmVuZHNXaXRoKFwiLmpzb25cIik7XG4gICAgY29uc3QgcmVhY2hhYmxlID0gaXNEYXRhUm91dGVcbiAgICAgID8gbm90aGluZ1VuZ2F0ZWRNYXRjaGVzKHBhdGhuYW1lKVxuICAgICAgOiBvbmx5R2F0ZWRSdWxlc01hdGNoKHBhdGhuYW1lKTtcbiAgICBpZiAoIWlzVGVtcGxhdGUgJiYgIXJlYWNoYWJsZSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IHN1ZmZpeGVzID0gcGF0aG5hbWUuZW5kc1dpdGgoXCIucnNjXCIpID8gW1wiLnJzY1wiLCBcIlwiXSA6IFtcIlwiXTtcbiAgICBjb25zdCBvd25lciA9IHN1ZmZpeGVzXG4gICAgICAuZmxhdE1hcCgoc3VmZml4KSA9PiBbXG4gICAgICAgIGAke2Jhc2VQYXRofSR7cHJlcmVuZGVyLnJvdXRlfSR7c3VmZml4fWAsXG4gICAgICAgIGAke3ByZXJlbmRlci5yb3V0ZX0ke3N1ZmZpeH1gLFxuICAgICAgXSlcbiAgICAgIC5tYXAoKGtleSkgPT4gZW50cnlwb2ludHNba2V5XSlcbiAgICAgIC5maW5kKEJvb2xlYW4pO1xuICAgIGlmICghb3duZXIpIHtcbiAgICAgIG9ycGhhbnMucHVzaChgJHtwYXRobmFtZX0gKHJvdXRlOiBcIiR7cHJlcmVuZGVyLnJvdXRlfVwiKWApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGVudHJ5cG9pbnRzW3BhdGhuYW1lXSA9IHtcbiAgICAgIGlkOiBwcmVyZW5kZXIuaWQsXG4gICAgICBmaWxlUGF0aDogb3duZXIuZmlsZVBhdGgsXG4gICAgICB0eXBlOiBvd25lci50eXBlLFxuICAgIH07XG4gIH1cblxuICBpZiAob3JwaGFucy5sZW5ndGggPiAwKSB7XG4gICAgLy8gV2FybiByYXRoZXIgdGhhbiB0aHJvdzogYW4gdW5tYXBwZWQgcGF0aG5hbWUgZGVncmFkZXMgb25lIFVSTCBzaGFwZSB0byBhXG4gICAgLy8gNDA0LCB3aGljaCBpcyB3aGF0IHdvdWxkIGhhcHBlbiB3aXRob3V0IHRoaXMgZnVuY3Rpb24gYXQgYWxsLiBBIHRocm93XG4gICAgLy8gd291bGQgYnJlYWsgdGhlIGJ1aWxkIG91dHJpZ2h0IG9uIGFuIG91dHB1dCBzaGFwZSBhIGZ1dHVyZSBgbmV4dGAgbWlub3JcbiAgICAvLyBtaWdodCBpbnRyb2R1Y2UuXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYCR7TE9HX1BSRUZJWH0gJHtvcnBoYW5zLmxlbmd0aH0gcHJlcmVuZGVyIHBhdGhuYW1lKHMpIGhhdmUgbm8gYCArXG4gICAgICAgIGBtYXRjaGluZyByb3V0ZSBlbnRyeXBvaW50IGFuZCB3aWxsIDQwNDogYCArXG4gICAgICAgIGAke29ycGhhbnMuc2xpY2UoMCwgNSkuam9pbihcIiwgXCIpfWAgK1xuICAgICAgICBgJHtvcnBoYW5zLmxlbmd0aCA+IDUgPyBgLCBhbmQgJHtvcnBoYW5zLmxlbmd0aCAtIDV9IG1vcmVgIDogXCJcIn0uYCxcbiAgICApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkTWlkZGxld2FyZShcbiAgcmVwb1Jvb3Q6IHN0cmluZyxcbiAgbWlkZGxld2FyZTogQWRhcHRlck91dHB1dHNbXCJtaWRkbGV3YXJlXCJdLFxuKTogQWRhcHRlck1pZGRsZXdhcmUgfCBudWxsIHtcbiAgaWYgKCFtaWRkbGV3YXJlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgLy8gYGNvbmZpZy5tYXRjaGVyc2AgaXMgZGVsaWJlcmF0ZWx5IG5vdCBjb3BpZWQgaGVyZTogaXQgYXJyaXZlcyBpbnNpZGVcbiAgLy8gYGN0eC5yb3V0aW5nLm1pZGRsZXdhcmVNYXRjaGVyc2AsIHdoaWNoIGBAbmV4dC9yb3V0aW5nYCBjb25zdW1lcyBkaXJlY3RseS5cbiAgcmV0dXJuIHtcbiAgICBpZDogbWlkZGxld2FyZS5pZCxcbiAgICBmaWxlUGF0aDogdG9Qb3NpeChyZWxhdGl2ZShyZXBvUm9vdCwgbWlkZGxld2FyZS5maWxlUGF0aCkpLFxuICB9O1xufVxuXG4vKipcbiAqIENvcHkgdGhlIHN0YWdpbmcgcGxhbiBpbnRvIGBzdGFnaW5nRGlyYC5cbiAqXG4gKiAqKlN5bWxpbmtzIGFyZSByZWNyZWF0ZWQgYXMgc3ltbGlua3MsIG5vdCBkZXJlZmVyZW5jZWQqKiwgd2hpY2ggaXMgd2hhdFxuICogTmV4dC5qcydzIG93biBgY29weVRyYWNlZEZpbGVzYCBkb2VzIChgbmV4dC9kaXN0L2J1aWxkL3V0aWxzLmpzYDogYHJlYWRsaW5rYFxuICogdGhlbiBgc3ltbGlua2AsIHdpdGggYSBXaW5kb3dzIGp1bmN0aW9uIGZhbGxiYWNrKS4gVW5kZXIgcG5wbSBhIHRyYWNlZCBhc3NldFxuICoga2V5IGlzIGZyZXF1ZW50bHkgYSAqZGlyZWN0b3J5KiBzeW1saW5rIGludG8gdGhlIHN0b3JlXG4gKiAoYG5vZGVfbW9kdWxlcy8ucG5wbS9uZXh0QOKApi9ub2RlX21vZHVsZXMvcmVhY3RgIOKGkiBgLi4vLi4vcmVhY3RAMTkuMi4zL+KApmApLCBzb1xuICogYGNvcHlGaWxlYCBmYWlscyBvdXRyaWdodCB3aXRoIGBFTk9UU1VQYC4gRGVyZWZlcmVuY2luZyBpbnN0ZWFkIHdvdWxkIHRyaXBsZVxuICogdGhlIHRyZWUg4oCUIGBleGFtcGxlcy9hcHAtcGxheWdyb3VuZGAgbWVhc3VyZXMgMzIgTUIgc3RhZ2VkIHZlcnN1cyA5NiBNQiB3aXRoXG4gKiBgZHUgLXNoTGAsIGFnYWluc3QgYSAyNTAgTUIgdW56aXBwZWQgTGFtYmRhIGNhcCDigJQgYmVjYXVzZSB3aG9sZSBwYWNrYWdlcyBhcmVcbiAqIHJlYWNoYWJsZSB0aHJvdWdoIHNldmVyYWwgc3VjaCBsaW5rcy4gVGhlIGxpbmsgdGFyZ2V0cyBhcmUgdGhlbXNlbHZlcyBzdGFnZWRcbiAqIGtleXMsIHNvIHJlbGF0aXZlIGxpbmtzIHJlc29sdmUgaW5zaWRlIHRoZSBkZXBsb3ltZW50IHJvb3QuXG4gKlxuICogUmVndWxhciBmaWxlcyBhcmUgc3RhZ2VkIGZpcnN0IHNvIHRoYXQgYSBzeW1saW5rIHdob3NlIHBhdGggd2FzIGFscmVhZHlcbiAqIG1hdGVyaWFsaXplZCBhcyBhIHJlYWwgZGlyZWN0b3J5IGlzIHNraXBwZWQgcmF0aGVyIHRoYW4gY2xvYmJlcmluZyBpdC5cbiAqXG4gKiBOb3RoaW5nIG1heSBkZXJlZmVyZW5jZSB0aGVtIGFmdGVyd2FyZHM6IHRoZSBGdW5jdGlvbnMgemlwIGtlZXBzIHRoZW0gYXNcbiAqIGxpbmtzIChgemlwRGlyZWN0b3J5YCksIGFuZCB0aGUgQ29udGFpbmVycyBgQ09QWWAgZG9lcyB0b28uXG4gKi9cbi8qKiBCb3VuZGVkIHNvIGEgbGFyZ2UgYXBwIGRvZXNuJ3QgZXhoYXVzdCBmaWxlIGRlc2NyaXB0b3JzLiAqL1xuY29uc3QgU1RBR0lOR19DT05DVVJSRU5DWSA9IDMyO1xuXG5hc3luYyBmdW5jdGlvbiBzdGFnZUZpbGVzKFxuICBzdGFnaW5nOiBTdGFnaW5nUGxhbixcbiAgc3RhZ2luZ0Rpcjogc3RyaW5nLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHBsYW5uZWQgPSBbLi4uc3RhZ2luZ107XG4gIC8vIExpbmtzIGxhbmQgYnkgcGxhbiBpbmRleCwgc28gdGhlIHBhc3MgYmVsb3cgY3JlYXRlcyB0aGVtIGluIHRoZSBwbGFuJ3NcbiAgLy8gb3JkZXIgd2hhdGV2ZXIgb3JkZXIgdGhlIHdvcmtlcnMgZmluaXNoZWQgaW4uXG4gIGNvbnN0IGxpbmtzOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIHN0cmluZ10gfCB1bmRlZmluZWQ+ID0gbmV3IEFycmF5KFxuICAgIHBsYW5uZWQubGVuZ3RoLFxuICApO1xuICBsZXQgbmV4dEVudHJ5ID0gMDtcbiAgY29uc3Qgd29ya2VyID0gYXN5bmMgKCkgPT4ge1xuICAgIHdoaWxlIChuZXh0RW50cnkgPCBwbGFubmVkLmxlbmd0aCkge1xuICAgICAgY29uc3QgaW5kZXggPSBuZXh0RW50cnkrKztcbiAgICAgIGNvbnN0IFtrZXksIHNvdXJjZV0gPSBwbGFubmVkW2luZGV4XTtcbiAgICAgIGNvbnN0IGxpbmtUYXJnZXQgPSBhd2FpdCByZWFkbGluayhzb3VyY2UpLmNhdGNoKCgpID0+IG51bGwpO1xuICAgICAgaWYgKGxpbmtUYXJnZXQgIT09IG51bGwpIHtcbiAgICAgICAgbGlua3NbaW5kZXhdID0gW2tleSwgc291cmNlLCBsaW5rVGFyZ2V0XTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBkZXN0ID0gam9pbihzdGFnaW5nRGlyLCBrZXkpO1xuICAgICAgYXdhaXQgbWtkaXIoZGlybmFtZShkZXN0KSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCBjb3B5RmlsZShzb3VyY2UsIGRlc3QpO1xuICAgIH1cbiAgfTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgQXJyYXkuZnJvbShcbiAgICAgIHsgbGVuZ3RoOiBNYXRoLm1pbihTVEFHSU5HX0NPTkNVUlJFTkNZLCBwbGFubmVkLmxlbmd0aCkgfSxcbiAgICAgIHdvcmtlcixcbiAgICApLFxuICApO1xuXG4gIGZvciAoY29uc3QgbGluayBvZiBsaW5rcykge1xuICAgIGlmIChsaW5rID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBba2V5LCBzb3VyY2UsIGxpbmtUYXJnZXRdID0gbGluaztcbiAgICBjb25zdCBkZXN0ID0gam9pbihzdGFnaW5nRGlyLCBrZXkpO1xuICAgIGlmIChleGlzdHNTeW5jKGRlc3QpKSB7XG4gICAgICAvLyBBbHJlYWR5IHN0YWdlZCBhcyByZWFsIGNvbnRlbnQgYnkgdGhlIHBvb2wgYWJvdmU7IHRoZSBsaW5rIHdvdWxkIGFkZFxuICAgICAgLy8gbm90aGluZyBhbmQgd291bGQgcmVwbGFjZSBhIGRpcmVjdG9yeSB3ZSBuZWVkLlxuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGF3YWl0IG1rZGlyKGRpcm5hbWUoZGVzdCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZShkaXJuYW1lKGRlc3QpLCBsaW5rVGFyZ2V0KTtcbiAgICBpZiAocmVzb2x2ZWQgPT09IHN0YWdpbmdEaXIgfHwgcmVzb2x2ZWQuc3RhcnRzV2l0aChzdGFnaW5nRGlyICsgc2VwKSkge1xuICAgICAgYXdhaXQgc3ltbGluayhsaW5rVGFyZ2V0LCBkZXN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUG9pbnRzIG91dHNpZGUgdGhlIGRlcGxveW1lbnQgcm9vdCwgc28gdGhlIGxpbmsgd291bGQgZGFuZ2xlIGluIExhbWJkYS5cbiAgICAgIC8vIEFic29sdXRlIHN0b3JlIHBhdGhzIGFyZSB0aGUgcmVhbGlzdGljIGNhc2UgaGVyZS5cbiAgICAgIGF3YWl0IGNwKHNvdXJjZSwgZGVzdCwgeyByZWN1cnNpdmU6IHRydWUsIGRlcmVmZXJlbmNlOiB0cnVlIH0pO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEFkZHMge0BsaW5rIFJVTlRJTUVfTkVYVF9NT0RVTEVTfSwgYEBuZXh0L2VudmAsIGFuZCBldmVyeXRoaW5nIHRoZXkgcmVxdWlyZSB0b1xuICogYHN0YWdpbmdgLCBhbmQge0BsaW5rIElNQUdFX05FWFRfTU9EVUxFU30gYW5kIHRoZWlycyB0byBgaW1hZ2VTdGFnaW5nYC5cbiAqXG4gKiBXaXRob3V0IHRoaXMgdGhlIGRlcGxveW1lbnQgaXMgY29tcGxldGUgZm9yIGV2ZXJ5IHJvdXRlIHRoZSBhcHAgaGFzIGFuZCBicm9rZW5cbiAqIGZvciBgL19uZXh0L2ltYWdlYDogdGhlIHRyYWNlZCBgYXNzZXRzYCBvZiBhIGJ1aWxkIG91dHB1dCBjb3ZlciB3aGF0IHRoZSAqYXBwKlxuICogcmVhY2hlcywgYW5kIGFuIGFwcCBuZXZlciByZWFjaGVzIG5leHQncyBpbWFnZSBvcHRpbWl6ZXIsIHNvXG4gKiBgbmV4dC9kaXN0L3NlcnZlci9pbWFnZS1vcHRpbWl6ZXIuanNgIGFuZCBpdHMgY2xvc3VyZSBhcmUgc2ltcGx5IGFic2VudCBhbmRcbiAqIGV2ZXJ5IGltYWdlIHJlcXVlc3QgNTAwcyB3aXRoIGEgYE1PRFVMRV9OT1RfRk9VTkRgIGZyb20gYG5leHRNb2R1bGVgLlxuICpcbiAqIFJlc29sdXRpb24gaXMgYW5jaG9yZWQgaW5zaWRlIGBjdHgucHJvamVjdERpcmAgZm9yIHRoZSBzYW1lIHJlYXNvblxuICogYHVzZU5leHRGcm9tYCBhbmNob3JzIHRoZXJlIGF0IHJ1bnRpbWU6IGl0IGlzIHRoZSBkaXJlY3Rvcnkgd2hvc2VcbiAqIGBub2RlX21vZHVsZXNgIHdhbGsgZmluZHMgdGhlIGFwcCdzIGBuZXh0YC4gQSByZXBvIHdoZXJlIHRoYXQgcmVzb2x1dGlvbiBmYWlsc1xuICogaXMgbm90IGEgcmVhbCBgbmV4dCBidWlsZGAg4oCUIG5vdGhpbmcgZWxzZSB3b3VsZCBoYXZlIHJ1biDigJQgc28gaXQgd2FybnMgYW5kXG4gKiBjb250aW51ZXMgcmF0aGVyIHRoYW4gZmFpbGluZyBhIGJ1aWxkIGZvciBhIHBhY2thZ2UgaXQgY291bGQgbm90IGhhdmUgbmVlZGVkLlxuICogQSBtaXNzaW5nICp0cmFjZXIqIGlzIGRpZmZlcmVudDogYG5leHRgIGlzIHJpZ2h0IHRoZXJlIGFuZCBpbWFnZSBvcHRpbWl6YXRpb25cbiAqIHdvdWxkIHNpbGVudGx5IDUwMCBpbiBwcm9kdWN0aW9uLCBzbyB0aGF0IHRocm93cy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gYWRkUnVudGltZU5leHRDbG9zdXJlKFxuICBjdHg6IEJ1aWxkQ29tcGxldGVDb250ZXh0LFxuICBzdGFnaW5nOiBNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBpbWFnZVN0YWdpbmc6IE1hcDxzdHJpbmcsIHN0cmluZz4sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gVGhlIGFuY2hvciBmaWxlIG5lZWRuJ3QgZXhpc3Q7IGBjcmVhdGVSZXF1aXJlYCBvbmx5IHJlYWRzIGl0cyBkaXJlY3RvcnkuXG4gIGNvbnN0IG5leHRSZXF1aXJlID0gY3JlYXRlUmVxdWlyZShcbiAgICBqb2luKGN0eC5wcm9qZWN0RGlyLCBcImNkay1uZXh0anMtbmV4dC1yZXNvbHZlci5janNcIiksXG4gICk7XG5cbiAgbGV0IGVudHJpZXM6IHN0cmluZ1tdO1xuICBsZXQgaW1hZ2VFbnRyaWVzOiBzdHJpbmdbXTtcbiAgdHJ5IHtcbiAgICBlbnRyaWVzID0gUlVOVElNRV9ORVhUX01PRFVMRVMubWFwKChzcGVjaWZpZXIpID0+XG4gICAgICBuZXh0UmVxdWlyZS5yZXNvbHZlKHNwZWNpZmllciksXG4gICAgKTtcbiAgICBpbWFnZUVudHJpZXMgPSBJTUFHRV9ORVhUX01PRFVMRVMubWFwKChzcGVjaWZpZXIpID0+XG4gICAgICBuZXh0UmVxdWlyZS5yZXNvbHZlKHNwZWNpZmllciksXG4gICAgKTtcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBgJHtMT0dfUFJFRklYfSBDb3VsZCBub3QgcmVzb2x2ZSBuZXh0J3MgaW1hZ2Ugb3B0aW1pemVyIGZyb20gYCArXG4gICAgICAgIGBcIiR7Y3R4LnByb2plY3REaXJ9XCIgKCR7KGNhdXNlIGFzIEVycm9yKS5tZXNzYWdlfSkuIFJlcXVlc3RzIHRvIGAgK1xuICAgICAgICBgL19uZXh0L2ltYWdlIHdpbGwgZmFpbCBhdCBydW50aW1lLmAsXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gYGxvYWRFbnZGaWxlc2AgKHJ1bnRpbWUgYG5leHQtbW9kdWxlcy50c2ApIGxvYWRzIHRoZSBzdGFnZWQgZW52IGZpbGVzIHdpdGhcbiAgLy8gYEBuZXh0L2VudmAsIHdoaWNoIGlzIGBuZXh0YCdzIGRlcGVuZGVuY3ksIHNvIHJlc29sdmVkIGZyb20gYG5leHRgJ3MgZGlyLlxuICAvLyBBbiBhcHAgbmV2ZXIgcmVxdWlyZXMgaXQsIHNvIG5vIG91dHB1dCdzIHRyYWNlIGhhcyBpdCBlaXRoZXIuXG4gIGNvbnN0IG5leHRQYWNrYWdlID0gbmV4dFJlcXVpcmUucmVzb2x2ZShcIm5leHQvcGFja2FnZS5qc29uXCIpO1xuICB0cnkge1xuICAgIGVudHJpZXMucHVzaChjcmVhdGVSZXF1aXJlKG5leHRQYWNrYWdlKS5yZXNvbHZlKFwiQG5leHQvZW52XCIpKTtcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtMT0dfUFJFRklYfSBDb3VsZCBub3QgcmVzb2x2ZSBcIkBuZXh0L2VudlwiIGZyb20gdGhlIGFwcCdzIFxcYG5leHRcXGAsIGAgK1xuICAgICAgICBgd2hpY2ggdGhlIGNkay1uZXh0anMgcnVudGltZSB1c2VzIHRvIGxvYWQgLmVudiBmaWxlcy5gLFxuICAgICAgeyBjYXVzZSB9LFxuICAgICk7XG4gIH1cblxuICBsZXQgbm9kZUZpbGVUcmFjZTogTm9kZUZpbGVUcmFjZTtcbiAgdHJ5IHtcbiAgICAoeyBub2RlRmlsZVRyYWNlIH0gPSBuZXh0UmVxdWlyZShORVhUX0ZJTEVfVFJBQ0VSKSk7XG4gIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7TE9HX1BSRUZJWH0gQ291bGQgbm90IGxvYWQgXCIke05FWFRfRklMRV9UUkFDRVJ9XCIsIHdoaWNoIGNkay1uZXh0anMgdXNlcyBgICtcbiAgICAgICAgYHRvIHN0YWdlIHRoZSBcXGBuZXh0XFxgIGZpbGVzIGl0cyBpbWFnZSBvcHRpbWl6ZXIgcmVxdWlyZXMuIFRoaXMgTmV4dC5qcyBgICtcbiAgICAgICAgYHZlcnNpb24gbWF5IGhhdmUgbW92ZWQgaXQ7IHBsZWFzZSBvcGVuIGFuIGlzc3VlLmAsXG4gICAgICB7IGNhdXNlIH0sXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGFkZCA9IChmaWxlTGlzdDogU2V0PHN0cmluZz4sIHRhcmdldDogTWFwPHN0cmluZywgc3RyaW5nPikgPT4ge1xuICAgIGZvciAoY29uc3QgdHJhY2VkIG9mIGZpbGVMaXN0KSB7XG4gICAgICBjb25zdCBrZXkgPSB0b1Bvc2l4KHRyYWNlZCk7XG4gICAgICBpZiAodGFyZ2V0LmhhcyhrZXkpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3Qgc291cmNlID0gam9pbihjdHgucmVwb1Jvb3QsIHRyYWNlZCk7XG4gICAgICBhc3NlcnRTdGFnaW5nS2V5KGtleSwgc291cmNlKTtcbiAgICAgIHRhcmdldC5zZXQoa2V5LCBzb3VyY2UpO1xuICAgIH1cbiAgfTtcbiAgYWRkKFxuICAgIChhd2FpdCBub2RlRmlsZVRyYWNlKGltYWdlRW50cmllcywgeyBiYXNlOiBjdHgucmVwb1Jvb3QgfSkpLmZpbGVMaXN0LFxuICAgIGltYWdlU3RhZ2luZyxcbiAgKTtcbiAgY29uc3QgeyBmaWxlTGlzdCB9ID0gYXdhaXQgbm9kZUZpbGVUcmFjZShlbnRyaWVzLCB7IGJhc2U6IGN0eC5yZXBvUm9vdCB9KTtcbiAgLy8gVGhlIHRyYWNlIHN0YXJ0cyBmcm9tIGBAbmV4dC9lbnZgJ3MgcmVhbCBwYXRoLCBzbyB1bmRlciBwbnBtIGl0IG5ldmVyXG4gIC8vIHBhc3NlcyB0aHJvdWdoIHRoZSBgLnBucG0vbmV4dEDigKYvbm9kZV9tb2R1bGVzL0BuZXh0L2VudmAgbGluayB0aGF0IGBuZXh0YFxuICAvLyByZXNvbHZlcyBpdCBieS4gV2l0aG91dCB0aGUgbGluaywgZXZlcnkgcmVxdWVzdCBmYWlscyBhdCBjb2xkIHN0YXJ0IHdpdGhcbiAgLy8gXCJDYW5ub3QgZmluZCBtb2R1bGUgJ0BuZXh0L2VudidcIi5cbiAgY29uc3QgbmV4dEVudkxpbmsgPSBqb2luKGRpcm5hbWUobmV4dFBhY2thZ2UpLCBcIi4uXCIsIFwiQG5leHRcIiwgXCJlbnZcIik7XG4gIGlmIChsc3RhdFN5bmMobmV4dEVudkxpbmssIHsgdGhyb3dJZk5vRW50cnk6IGZhbHNlIH0pPy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgLy8gYHJlc29sdmVgIHJldHVybnMgcmVhbCBwYXRocywgc28gcmVsYXRpdmUgdG8gdGhlIHJlYWwgcmVwbyByb290LlxuICAgIGZpbGVMaXN0LmFkZChyZWxhdGl2ZShyZWFscGF0aFN5bmMoY3R4LnJlcG9Sb290KSwgbmV4dEVudkxpbmspKTtcbiAgfVxuICBhZGQoZmlsZUxpc3QsIHN0YWdpbmcpO1xufVxuXG4vKipcbiAqIEFkZCBgPGRpc3REaXI+L3JlcXVpcmVkLXNlcnZlci1maWxlcy5qc29uYCB0byBhIHBsYW4gZXZlcnkgZ3JvdXAgaXMgbWVyZ2VkIHdpdGguXG4gKlxuICogSXQgcmVhY2hlcyBhIGdyb3VwIG90aGVyd2lzZSBvbmx5IGFzIGEgdHJhY2VkIGBhc3NldGAgb2Ygc29tZSBpbnZvY2FibGUgb3V0cHV0LFxuICogd2hpY2ggaXMgbm90IGEgZ3VhcmFudGVlOiBhIGdyb3VwIHdob3NlIHRlbXBsYXRlcyBhcmUgYWxsIGFzc2lnbmVkIGVsc2V3aGVyZVxuICogb3ducyBubyBvdXRwdXRzIGF0IGFsbC4gVGhhdCBpcyByZWFjaGFibGUg4oCUIGEgUGFnZXMtUm91dGVyLW9ubHkgYXBwIHdob3NlIGV2ZXJ5XG4gKiBwYWdlIGZhbGxzIHVuZGVyIHRoZSBjb25maWd1cmVkIGBmdW5jdGlvbkdyb3Vwc2AgbGVhdmVzIHRoZSAqZGVmYXVsdCogZ3JvdXBcbiAqIHRlbXBsYXRlLWVtcHR5LCBhbmQgdGhlIGRlZmF1bHQgZ3JvdXAgaXMgc3RpbGwgd2hhdCBzZXJ2ZXMgYC9fbmV4dC9pbWFnZWAsIHRoZVxuICogc3RhdGljIGZpbGVzLCBhbmQgdGhlIGRpc3RyaWJ1dGlvbidzIGNhdGNoLWFsbC5cbiAqXG4gKiBJdHMgYWJzZW5jZSBpcyBub3QgYSBwYXJ0aWFsIGZhaWx1cmU6IGBsb2FkUnVudGltZWAgcHJvYmVzIGZvciBleGFjdGx5IHRoaXMgZmlsZVxuICogYmVmb3JlIGl0IHdpbGwgc2VydmUgYW55dGhpbmcsIGFuZCBgaW1hZ2UudHNgIHJlYWRzIHRoZSBpbWFnZSBjb25maWcgb3V0IG9mIGl0LFxuICogc28gdGhlIHdob2xlIHJvb3QgYW5zd2VycyBcInRoZSBkZXBsb3ltZW50IHBhY2thZ2UgaXMgaW5jb21wbGV0ZVwiLiBDaGVhcCB0byBtYWtlXG4gKiB1bmNvbmRpdGlvbmFsLCBzbyBtYWtlIGl0IHVuY29uZGl0aW9uYWwuXG4gKlxuICogTm90IHRyYWNlZCBsaWtlIHtAbGluayBSVU5USU1FX05FWFRfTU9EVUxFU30sIGJlY2F1c2UgaXQgaXMgZGF0YSByYXRoZXIgdGhhbiBhXG4gKiBtb2R1bGU6IG5vdGhpbmcgYHJlcXVpcmVgcyBpdCwgc28gbm8gZmlsZSB0cmFjZXIgY2FuIGZpbmQgaXQuXG4gKlxuICogQWJzZW5jZSBpcyBsZWZ0IHRvIGBsb2FkUnVudGltZWAsIHdoaWNoIG5hbWVzIHRoZSBmaWxlIGFuZCB0aGUgbGF5b3V0IGNvbnRyYWN0XG4gKiBpdCBiZWxvbmdzIHRvLiBgbmV4dCBidWlsZGAgYWx3YXlzIHdyaXRlcyBpdCwgc28gdGhlcmUgaXMgbm8gYnVpbGQtdGltZSBlcnJvclxuICogd29ydGggaW52ZW50aW5nIGhlcmUgZm9yIGEgZmlsZSB0aGlzIHN0ZXAgZG9lcyBub3Qgb3duLlxuICovXG5mdW5jdGlvbiBhZGRSZXF1aXJlZFNlcnZlckZpbGVzKFxuICBjdHg6IEJ1aWxkQ29tcGxldGVDb250ZXh0LFxuICBzdGFnaW5nOiBNYXA8c3RyaW5nLCBzdHJpbmc+LFxuKTogdm9pZCB7XG4gIGNvbnN0IHNvdXJjZSA9IGpvaW4oY3R4LmRpc3REaXIsIFwicmVxdWlyZWQtc2VydmVyLWZpbGVzLmpzb25cIik7XG4gIGNvbnN0IGtleSA9IHRvUG9zaXgocmVsYXRpdmUoY3R4LnJlcG9Sb290LCBzb3VyY2UpKTtcbiAgaWYgKHN0YWdpbmcuaGFzKGtleSkgfHwgIWV4aXN0c1N5bmMoc291cmNlKSkge1xuICAgIHJldHVybjtcbiAgfVxuICBhc3NlcnRTdGFnaW5nS2V5KGtleSwgc291cmNlKTtcbiAgc3RhZ2luZy5zZXQoa2V5LCBzb3VyY2UpO1xufVxuXG4vKipcbiAqIEV2ZXJ5IHN0YWdlZCBwYXRoIG11c3QgbGFuZCBpbnNpZGUgdGhlIHN0YWdpbmcgdHJlZSBhbmQgbXVzdCBub3Qgc2hhZG93IHRoZVxuICogcmVzZXJ2ZWQgZGlyZWN0b3J5IGNkay1uZXh0anMgY29waWVzIGl0cyBvd24gcnVudGltZSBpbnRvIGF0IHN5bnRoLlxuICovXG5mdW5jdGlvbiBhc3NlcnRTdGFnaW5nS2V5KGtleTogc3RyaW5nLCBzb3VyY2U6IHN0cmluZyk6IHZvaWQge1xuICBpZiAoa2V5ID09PSBcIlwiIHx8IGtleS5zdGFydHNXaXRoKFwiL1wiKSB8fCBrZXkuc3RhcnRzV2l0aChcIi4uXCIpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7TE9HX1BSRUZJWH0gQnVpbGQgb3V0cHV0IGFzc2V0IFwiJHtzb3VyY2V9XCIgcmVzb2x2ZXMgdG8gdGhlIHN0YWdpbmcga2V5IGAgK1xuICAgICAgICBgXCIke2tleX1cIiwgd2hpY2ggaXMgb3V0c2lkZSB0aGUgZGVwbG95bWVudCByb290LiBTZXQgYCArXG4gICAgICAgIGBcXGBvdXRwdXRGaWxlVHJhY2luZ1Jvb3RcXGAgc28gYWxsIHRyYWNlZCBmaWxlcyBsaXZlIHVuZGVyIG9uZSByb290LmAsXG4gICAgKTtcbiAgfVxuICBpZiAoa2V5ID09PSBSVU5USU1FX0RJUl9OQU1FIHx8IGtleS5zdGFydHNXaXRoKGAke1JVTlRJTUVfRElSX05BTUV9L2ApKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7TE9HX1BSRUZJWH0gQnVpbGQgb3V0cHV0IGFzc2V0IFwiJHtzb3VyY2V9XCIgcmVzb2x2ZXMgdG8gdGhlIHN0YWdpbmcga2V5IGAgK1xuICAgICAgICBgXCIke2tleX1cIiwgYnV0IFwiJHtSVU5USU1FX0RJUl9OQU1FfS9cIiBpcyByZXNlcnZlZCBmb3IgY2RrLW5leHRqcydzIG93biBgICtcbiAgICAgICAgYHJ1bnRpbWUgZmlsZXMuYCxcbiAgICApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvUG9zaXgocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNlcCA9PT0gXCIvXCIgPyBwYXRoIDogcGF0aC5zcGxpdChzZXApLmpvaW4oXCIvXCIpO1xufVxuXG5mdW5jdGlvbiBzb3J0ZWRVbmlxdWUodmFsdWVzOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5uZXcgU2V0KHZhbHVlcyldLnNvcnQoKTtcbn1cbiJdfQ==