cdk-nextjs 0.6.2 → 0.7.1

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