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,863 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const promises_1 = require("node:fs/promises");
7
+ const node_os_1 = require("node:os");
8
+ const node_path_1 = require("node:path");
9
+ const app_playground_base_path_json_1 = __importDefault(require("./__fixtures__/app-playground-base-path.json"));
10
+ const app_playground_json_1 = __importDefault(require("./__fixtures__/app-playground.json"));
11
+ const pages_i18n_json_1 = __importDefault(require("./__fixtures__/pages-i18n.json"));
12
+ const build_outputs_1 = require("./build-outputs");
13
+ const manifest_1 = require("../runtime/manifest");
14
+ /**
15
+ * The fixtures are real `onBuildComplete` contexts captured by
16
+ * `scripts/capture-adapter-fixture.mjs`, with absolute paths rewritten to a
17
+ * `/repo` placeholder. Regenerate them when `next` is upgraded.
18
+ */
19
+ const fixtures = {
20
+ "app-playground": app_playground_json_1.default,
21
+ "app-playground-base-path": app_playground_base_path_json_1.default,
22
+ "pages-i18n": pages_i18n_json_1.default,
23
+ };
24
+ /** Fixtures are JSON, so the structural cast is the point of the cast. */
25
+ const asContext = (fixture) => structuredClone(fixture);
26
+ /**
27
+ * `buildAdapterManifest` requires the build cwd to be the project dir — see
28
+ * `assertBuildCwd`. The fixtures' project dirs are synthetic `/repo/…` paths, so
29
+ * every call supplies it rather than letting it default to `process.cwd()`. The
30
+ * assertion itself is covered separately below.
31
+ */
32
+ const build = (ctx) => (0, build_outputs_1.buildAdapterManifest)(ctx, { buildCwd: ctx.projectDir });
33
+ const write = (ctx) => (0, build_outputs_1.writeBuildOutputs)(ctx, { buildCwd: ctx.projectDir });
34
+ /**
35
+ * The one deployment root an unsplit build stages. Asserted rather than indexed
36
+ * so a regression that starts splitting unasked fails here instead of silently
37
+ * checking group 0.
38
+ */
39
+ const soleRoot = (result) => {
40
+ expect(result.stagedGroups).toHaveLength(1);
41
+ return result.stagedGroups[0].path;
42
+ };
43
+ beforeEach(() => {
44
+ // `maxDuration` warnings are expected from the pages-i18n fixture.
45
+ jest.spyOn(console, "warn").mockImplementation(() => { });
46
+ });
47
+ afterEach(() => {
48
+ jest.restoreAllMocks();
49
+ });
50
+ describe.each(Object.keys(fixtures))("buildAdapterManifest(%s)", (name) => {
51
+ const ctx = asContext(fixtures[name]);
52
+ const { manifest, groups: [{ staging }], } = build(ctx);
53
+ it("stamps the manifest version and build identity", () => {
54
+ expect(manifest.version).toBe(1);
55
+ expect(manifest.buildId).toBe(ctx.buildId);
56
+ expect(manifest.relativeProjectDir).toBe(name.startsWith("pages-i18n") ? "pages-i18n" : "app-playground");
57
+ });
58
+ it("copies the config fields the runtime router needs", () => {
59
+ expect(manifest.config).toEqual({
60
+ basePath: ctx.config.basePath ?? "",
61
+ trailingSlash: ctx.config.trailingSlash === true,
62
+ assetPrefix: ctx.config.assetPrefix ?? "",
63
+ distDir: ".next",
64
+ compress: true,
65
+ generateEtags: true,
66
+ i18n: ctx.config.i18n ?? null,
67
+ deploymentId: "",
68
+ });
69
+ });
70
+ it("persists ctx.routing verbatim", () => {
71
+ // `@next/routing`'s `resolveRoutes` consumes this whole object; anything we
72
+ // reshape here is a behavior difference from `next start`.
73
+ expect(manifest.routing).toEqual(ctx.routing);
74
+ expect(manifest.routing).toHaveProperty("middlewareMatchers");
75
+ });
76
+ it("maps every invocable output pathname to an entrypoint", () => {
77
+ const expected = [
78
+ ...ctx.outputs.pages,
79
+ ...ctx.outputs.pagesApi,
80
+ ...ctx.outputs.appPages,
81
+ ...ctx.outputs.appRoutes,
82
+ ].map((o) => o.pathname);
83
+ // Plus dynamic prerender templates, which `addPrerenderPathnames` maps to
84
+ // the entrypoint of the route that owns them. None of these fixtures has a
85
+ // gated dynamic route, so no *concrete* prerender pathname is added - see
86
+ // the root-params test below.
87
+ const templates = ctx.outputs.prerenders
88
+ .filter((o) => o.pathname.includes("["))
89
+ .map((o) => o.pathname);
90
+ expect(Object.keys(manifest.entrypoints).sort()).toEqual([...new Set([...expected, ...templates])].sort());
91
+ for (const [pathname, entry] of Object.entries(manifest.entrypoints)) {
92
+ expect(entry.filePath).toMatch(/^[^/]/);
93
+ expect(entry.filePath).not.toContain("\\");
94
+ expect(staging.has(entry.filePath)).toBe(true);
95
+ expect(entry.id).toBeTruthy();
96
+ expect(["app-page", "app-route", "page", "page-api"]).toContain(entry.type);
97
+ expect(pathname).toBeTruthy();
98
+ }
99
+ });
100
+ it("lists pathnames as the sorted union of entrypoints and static files", () => {
101
+ expect(manifest.pathnames).toEqual([...manifest.pathnames].sort());
102
+ expect(new Set(manifest.pathnames).size).toBe(manifest.pathnames.length);
103
+ for (const key of Object.keys(manifest.entrypoints)) {
104
+ expect(manifest.pathnames).toContain(key);
105
+ }
106
+ for (const file of ctx.outputs.staticFiles) {
107
+ expect(manifest.pathnames).toContain(file.pathname);
108
+ }
109
+ // One reported pathname can produce two keys - a `/index` static file is
110
+ // also served at `/`, see the static-home-page tests below. None of these
111
+ // fixtures has one, so here the two sets coincide.
112
+ expect(Object.keys(manifest.staticFiles)).toEqual([...new Set(ctx.outputs.staticFiles.map((f) => f.pathname))].sort());
113
+ });
114
+ it("maps each static file to a repo-root-relative key", () => {
115
+ for (const [pathname, key] of Object.entries(manifest.staticFiles)) {
116
+ const output = ctx.outputs.staticFiles.find((f) => f.pathname === pathname);
117
+ expect(key).toBe(output.filePath.replace("/repo/", ""));
118
+ expect(key.startsWith("/")).toBe(false);
119
+ }
120
+ });
121
+ it("stages the static files nothing in front of the compute serves", () => {
122
+ // `<distDir>/static` goes to S3; `<distDir>/server/**` (404.html,
123
+ // favicon.ico.body, fully-static Pages Router HTML) does not, so the
124
+ // runtime must be able to read it off disk.
125
+ for (const [pathname, key] of Object.entries(manifest.staticFiles)) {
126
+ const servedByS3 = pathname.includes("/_next/static/");
127
+ expect(staging.has(key)).toBe(!servedByS3);
128
+ }
129
+ });
130
+ it("stages only keys that land inside the deployment root", () => {
131
+ expect(staging.size).toBeGreaterThan(0);
132
+ for (const key of staging.keys()) {
133
+ expect(key).not.toBe("");
134
+ expect(key.startsWith("/")).toBe(false);
135
+ expect(key.startsWith("..")).toBe(false);
136
+ expect(key.startsWith(`${manifest_1.RUNTIME_DIR_NAME}/`)).toBe(false);
137
+ }
138
+ // The traced `next` closure is merged into every output, so staging is far
139
+ // smaller than the sum of the per-output `assets` maps.
140
+ expect(staging.size).toBeLessThan(ctx.outputs.appPages.length * 100 +
141
+ ctx.outputs.pages.length * 100 +
142
+ 1000);
143
+ });
144
+ });
145
+ describe("buildAdapterManifest edge cases", () => {
146
+ it("throws when `next build` ran from outside the project directory", () => {
147
+ const ctx = asContext(app_playground_json_1.default);
148
+ expect(() => (0, build_outputs_1.buildAdapterManifest)(ctx, { buildCwd: "/repo" })).toThrow(/must run from the Next.js project directory/);
149
+ });
150
+ it("defaults the build cwd to process.cwd()", () => {
151
+ // Which is this package's root, never a fixture's `/repo/…` project dir, so
152
+ // the assertion fires — proving the default is wired and not just the option.
153
+ expect(() => (0, build_outputs_1.buildAdapterManifest)(asContext(app_playground_json_1.default))).toThrow(/must run from the Next.js project directory/);
154
+ });
155
+ it("records the deploymentId, reduced to what a cache key prefix can hold", () => {
156
+ // `NextjsBuild` suffixes its `buildId` with it: next pins the build ID
157
+ // itself once `deploymentId` is set.
158
+ const ctx = asContext(app_playground_json_1.default);
159
+ const { manifest } = build({
160
+ ...ctx,
161
+ config: { ...ctx.config, deploymentId: "v1.2/main" },
162
+ });
163
+ expect(manifest.config.deploymentId).toBe("v1-2-main");
164
+ });
165
+ it("keys locale variants of one page to the same entrypoint file", () => {
166
+ const { manifest } = build(asContext(pages_i18n_json_1.default));
167
+ // i18n fans one page out into one output per locale, plus a
168
+ // `/_next/data/<buildId>/…json` sibling each. They share `filePath` and
169
+ // `type`; `id` stays per-pathname (locale-prefixed), so it is not a dedup key.
170
+ const ssr = [
171
+ "/ssr",
172
+ "/en-US/ssr",
173
+ "/fr/ssr",
174
+ "/nl-NL/ssr",
175
+ `/_next/data/${manifest.buildId}/fr/ssr.json`,
176
+ ];
177
+ for (const pathname of ssr) {
178
+ expect(manifest.entrypoints[pathname]).toMatchObject({
179
+ filePath: manifest.entrypoints["/ssr"].filePath,
180
+ type: "page",
181
+ });
182
+ expect(manifest.entrypoints[pathname].id).toBe(pathname);
183
+ }
184
+ expect(manifest.entrypoints["/ssr"].type).toBe("page");
185
+ expect(manifest.entrypoints["/api/hello"].type).toBe("page-api");
186
+ });
187
+ it("carries basePath in pathnames but not in entrypoint ids", () => {
188
+ // `output.pathname` is basePath-prefixed while `output.id` is not. Dispatch
189
+ // keys off the pathname, so the prefix has to stay.
190
+ const { manifest } = build(asContext(app_playground_base_path_json_1.default));
191
+ expect(manifest.config.basePath).toBe("/prod");
192
+ expect(manifest.entrypoints["/prod/api/health"]).toBeDefined();
193
+ expect(manifest.entrypoints["/prod/api/health"].id).toBe("/api/health");
194
+ expect(manifest.entrypoints["/api/health"]).toBeUndefined();
195
+ });
196
+ /**
197
+ * A Pages Router home page reaches us as `/index`, whichever population it lands
198
+ * in: `normalizePagePath("/")` is `"/index"`, and the adapter hook uses it for a
199
+ * fully-static page's `STATIC_FILE` and for an SSG/SSR page's `PAGES` output
200
+ * alike. Nothing else in the outputs carries `/`, so the mapping under test is
201
+ * the only thing that makes the home page routable.
202
+ */
203
+ function withHomePage(basePath, kind) {
204
+ const ctx = asContext(pages_i18n_json_1.default);
205
+ ctx.config.i18n = null;
206
+ ctx.config.basePath = basePath;
207
+ ctx.outputs.staticFiles = [];
208
+ ctx.outputs.prerenders = [];
209
+ const page = ctx.outputs.pages.find((o) => o.pathname === "/ssr");
210
+ ctx.outputs.pages =
211
+ kind === "invocable"
212
+ ? [{ ...page, id: "/index", pathname: `${basePath}/index` }]
213
+ : [];
214
+ if (kind === "static") {
215
+ ctx.outputs.staticFiles = [
216
+ {
217
+ id: "/",
218
+ pathname: `${basePath}/index`,
219
+ type: "STATIC_FILE",
220
+ filePath: "/repo/pages-i18n/.next/server/pages/index.html",
221
+ },
222
+ ];
223
+ }
224
+ return build(ctx);
225
+ }
226
+ it("routes a fully-static Pages Router home page at `/`, not `/index`", () => {
227
+ const { manifest } = withHomePage("", "static");
228
+ const html = "pages-i18n/.next/server/pages/index.html";
229
+ expect(manifest.staticFiles["/"]).toBe(html);
230
+ expect(manifest.pathnames).toContain("/");
231
+ // Kept as well as `/`: next's minimal mode rewrites `/index` to `/` before
232
+ // matching, so it answers there too.
233
+ expect(manifest.staticFiles["/index"]).toBe(html);
234
+ });
235
+ it("routes an SSG or SSR home page's entrypoint at `/` as well", () => {
236
+ const { manifest } = withHomePage("", "invocable");
237
+ expect(manifest.entrypoints["/"]).toEqual(manifest.entrypoints["/index"]);
238
+ expect(manifest.pathnames).toContain("/");
239
+ // The output's own `id` is what next reported, and only names the entrypoint
240
+ // in diagnostics and group ownership - it is not a key into anything.
241
+ expect(manifest.entrypoints["/"].id).toBe("/index");
242
+ });
243
+ it("routes that home page under basePath at the basePath itself", () => {
244
+ // `/prod`, not `/prod/` — which is how the App Router fixture reports its own
245
+ // home page.
246
+ const { manifest } = withHomePage("/prod", "static");
247
+ expect(Object.keys(manifest.staticFiles)).toEqual(["/prod", "/prod/index"]);
248
+ });
249
+ it("leaves an App Router `/index` route at `/index`", () => {
250
+ // `app/index/page.tsx` is a real route. Only the Pages Router reports its
251
+ // home page as `/index`.
252
+ const ctx = asContext(app_playground_json_1.default);
253
+ const home = ctx.outputs.appPages.find((o) => o.pathname === "/");
254
+ const indexFile = home.filePath.replace(/page\.js$/, "index/page.js");
255
+ ctx.outputs.appPages.push({
256
+ ...home,
257
+ id: "/index",
258
+ pathname: "/index",
259
+ filePath: indexFile,
260
+ });
261
+ const { manifest } = build(ctx);
262
+ expect(manifest.entrypoints["/"].filePath).not.toBe(manifest.entrypoints["/index"].filePath);
263
+ expect(manifest.entrypoints["/index"].filePath).toMatch(/index\/page\.js$/);
264
+ });
265
+ it("records middleware without duplicating its matchers", () => {
266
+ const { manifest, groups: [{ staging }], } = build(asContext(app_playground_json_1.default));
267
+ expect(manifest.middleware).not.toBeNull();
268
+ expect(manifest.middleware.filePath).toMatch(/^[^/]/);
269
+ expect(staging.has(manifest.middleware.filePath)).toBe(true);
270
+ expect(manifest.middleware).not.toHaveProperty("matchers");
271
+ const { manifest: noMiddleware } = build(asContext(pages_i18n_json_1.default));
272
+ expect(noMiddleware.middleware).toBeNull();
273
+ });
274
+ it("maps a Pages Router data-route template to its owning route", () => {
275
+ // `/_next/data/<buildId>/<locale>/blog/[slug].json` exists only as a
276
+ // prerender. Without it, the ISR data URLs `next start` serves would 404.
277
+ const { manifest } = build(asContext(pages_i18n_json_1.default));
278
+ const dataTemplate = `/_next/data/${manifest.buildId}/fr/blog/[slug].json`;
279
+ expect(manifest.entrypoints[dataTemplate]).toEqual({
280
+ id: dataTemplate,
281
+ filePath: manifest.entrypoints["/fr/blog/[slug]"].filePath,
282
+ type: "page",
283
+ });
284
+ expect(manifest.pathnames).toContain(dataTemplate);
285
+ });
286
+ it("registers a static getStaticProps page's data route, which no rule reaches", () => {
287
+ // `test/e2e/no-page-props`: `/_next/data/<buildId>/gsp.json` 404'd while
288
+ // `next start` serves it 200, so every client-side navigation into the page
289
+ // fell back to a full page load. `next build` emits a `dynamicRoutes` rule for
290
+ // a data route only when the page is dynamic or the app has middleware, so
291
+ // without middleware a *static* page's data route arrives as a concrete
292
+ // prerender pathname with nothing to match it. Reproduced on `pages-i18n`,
293
+ // whose captured prerenders are all dynamic, by renaming one.
294
+ const ctx = asContext(pages_i18n_json_1.default);
295
+ const dataRoute = `/_next/data/${ctx.buildId}/en-US/gsp.json`;
296
+ const concrete = ctx.outputs.prerenders.find((it) => it.pathname.endsWith("hello.json"));
297
+ concrete.pathname = dataRoute;
298
+ concrete.id = dataRoute;
299
+ const { manifest } = build(ctx);
300
+ expect(manifest.entrypoints[dataRoute]).toEqual({
301
+ id: dataRoute,
302
+ filePath: manifest.entrypoints["/en-US/blog/[slug]"].filePath,
303
+ type: "page",
304
+ });
305
+ // And the dynamic page's own concrete data pathname stays out: the ungated
306
+ // `…/blog/[slug].json` rule already reaches it, and that rule is where the
307
+ // `nxtPslug` param comes from — resolving the request to itself would drop it.
308
+ const { manifest: captured } = build(asContext(pages_i18n_json_1.default));
309
+ expect(captured.entrypoints[`/_next/data/${captured.buildId}/en-US/blog/hello.json`]).toBeUndefined();
310
+ });
311
+ it("leaves an App Router fallback template on its own entrypoint", () => {
312
+ // `/isr/[id]` is a prerender *and* an appPages output. The output wins, so
313
+ // `id` stays the route's own rather than being rewritten.
314
+ const { manifest } = build(asContext(app_playground_json_1.default));
315
+ expect(manifest.entrypoints["/isr/[id]"].id).toBe("/isr/[id]");
316
+ expect(manifest.entrypoints["/isr/[id].rsc"]).toBeDefined();
317
+ });
318
+ it("adds a concrete prerender pathname when only a gated rule matches it", () => {
319
+ // What a root-params app produces: `app/[locale]/page.tsx` with
320
+ // `generateStaticParams()` and no `app/layout.tsx`. The params can never be
321
+ // filled at request time, so `next build` emits the `dynamicRoutes` rule with a
322
+ // draft-mode `has` and expects the platform to serve `/en` from the prerender.
323
+ // Measured against `test/e2e/app-dir/parallel-routes-root-param-dynamic-child`,
324
+ // where every URL of the app 404'd. Reproduced here by gating
325
+ // `app-playground`'s `/isr/[id]` rules, which no committed capture does.
326
+ const ctx = asContext(app_playground_json_1.default);
327
+ for (const route of ctx.routing.dynamicRoutes) {
328
+ if (route.sourceRegex.includes("isr")) {
329
+ route.has = [
330
+ { type: "cookie", key: "__prerender_bypass", value: "secret" },
331
+ ];
332
+ }
333
+ }
334
+ const { manifest } = build(ctx);
335
+ expect(manifest.entrypoints["/isr/1"]).toEqual({
336
+ id: "/isr/1",
337
+ filePath: manifest.entrypoints["/isr/[id]"].filePath,
338
+ type: "app-page",
339
+ });
340
+ // The RSC and segment-prefetch variants too: they are the URLs a client-side
341
+ // navigation asks for, so without them the app renders and never hydrates.
342
+ expect(manifest.entrypoints["/isr/1.rsc"]).toBeDefined();
343
+ expect(manifest.entrypoints["/isr/1.segments/isr/$d$id/__PAGE__.segment.rsc"]).toBeDefined();
344
+ // Unmutated, the same pathnames stay out: the ungated rule already reaches
345
+ // `/isr/[id]`, which is where the `nxtPid` param comes from.
346
+ const { manifest: ungated } = build(asContext(app_playground_json_1.default));
347
+ expect(ungated.entrypoints["/isr/1"]).toBeUndefined();
348
+ expect(ungated.entrypoints["/isr/1.rsc"]).toBeUndefined();
349
+ // And a pathname no rule matches at all stays out either way: `resolveRoutes`
350
+ // never resolves a static route's segment outputs, so listing them is weight.
351
+ expect(manifest.entrypoints["/index.segments/_tree.segment.rsc"]).toBeUndefined();
352
+ });
353
+ it("leaves public/ out of the manifest and the staging plan", async () => {
354
+ // The container runtime lists `public/` off disk at cold start
355
+ // (`readPublicFiles`), because only the disk has what a `postbuild` wrote
356
+ // into it after this hook ran; and the Lambda types never serve it.
357
+ const repoRoot = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-public-"));
358
+ // Every path in the fixture, rebased from `/repo` onto a real directory.
359
+ const ctx = asContext(JSON.parse(JSON.stringify(app_playground_base_path_json_1.default).replaceAll('"/repo', `"${repoRoot}`)));
360
+ await (0, promises_1.mkdir)((0, node_path_1.join)(ctx.projectDir, "public"), { recursive: true });
361
+ await (0, promises_1.writeFile)((0, node_path_1.join)(ctx.projectDir, "public", "test.txt"), "hello");
362
+ const { manifest, groups: [{ staging }], } = build(ctx);
363
+ expect(Object.values(manifest.staticFiles).filter((key) => key.includes("/public/"))).toEqual([]);
364
+ expect(manifest.pathnames).not.toContain("/prod/test.txt");
365
+ expect([...staging.keys()].filter((key) => key.includes("/public/"))).toEqual([]);
366
+ });
367
+ it("warns instead of throwing when a template has no owning route", () => {
368
+ const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
369
+ const ctx = asContext(pages_i18n_json_1.default);
370
+ ctx.outputs.prerenders[0].route = "/gone/[slug]";
371
+ ctx.outputs.prerenders[0].pathname = "/gone/[slug]";
372
+ const { manifest } = build(ctx);
373
+ expect(manifest.entrypoints["/gone/[slug]"]).toBeUndefined();
374
+ expect(warn.mock.calls
375
+ .map((call) => String(call[0]))
376
+ .filter((message) => message.includes("will 404"))).toEqual([
377
+ expect.stringContaining('/gone/[slug] (route: "/gone/[slug]")'),
378
+ ]);
379
+ });
380
+ it("warns once per unsupported route config key", () => {
381
+ const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
382
+ build(asContext(pages_i18n_json_1.default));
383
+ const messages = warn.mock.calls.map((call) => String(call[0]));
384
+ expect(messages.filter((m) => m.includes("`maxDuration`"))).toHaveLength(1);
385
+ expect(messages[0]).toContain("ssr");
386
+ expect(messages[0]).toContain("overrides");
387
+ expect(messages.some((m) => m.includes("`preferredRegion`"))).toBe(false);
388
+ });
389
+ it("throws on an edge-runtime output", () => {
390
+ const ctx = asContext(app_playground_json_1.default);
391
+ ctx.outputs.appRoutes[0].runtime = "edge";
392
+ expect(() => build(ctx)).toThrow(/cannot deploy routes built for the edge runtime/);
393
+ expect(() => build(ctx)).toThrow(ctx.outputs.appRoutes[0].sourcePage);
394
+ });
395
+ it("blames middleware, not `/`, for edge-runtime middleware", () => {
396
+ const ctx = asContext(app_playground_json_1.default);
397
+ const middleware = ctx.outputs.middleware;
398
+ if (!middleware) {
399
+ throw new Error("fixture has no middleware output");
400
+ }
401
+ // What a legacy `middleware.ts` builds to. Its `sourcePage` is `/`, so the
402
+ // regression guarded here is the message telling an author to edit the home
403
+ // page.
404
+ middleware.runtime = "edge";
405
+ expect(() => build(ctx)).toThrow(/cannot deploy middleware built for the edge runtime/);
406
+ expect(() => build(ctx)).toThrow(middleware.filePath);
407
+ // Both ways out: `middleware.ts` only defaults to edge.
408
+ expect(() => build(ctx)).toThrow(/runtime: "nodejs"/);
409
+ expect(() => build(ctx)).toThrow(/proxy\.ts/);
410
+ expect(() => build(ctx)).not.toThrow(/edge-only/);
411
+ expect(() => build(ctx)).not.toThrow(/cannot deploy routes built for the edge runtime/);
412
+ });
413
+ it("throws when two outputs map one key to different content", () => {
414
+ const ctx = asContext(app_playground_json_1.default);
415
+ const [first, second] = ctx.outputs.appPages;
416
+ const key = Object.keys(first.assets)[0];
417
+ first.assetsHashes[key] = "hash-a";
418
+ second.assets[key] = first.assets[key];
419
+ second.assetsHashes[key] = "hash-b";
420
+ expect(() => build(ctx)).toThrow(/map "[^"]+" to different content/);
421
+ });
422
+ it("throws on an asset key outside the deployment root", () => {
423
+ const ctx = asContext(app_playground_json_1.default);
424
+ ctx.outputs.appPages[0].assets["../escape.js"] = "/elsewhere/escape.js";
425
+ expect(() => build(ctx)).toThrow(/outside the deployment root/);
426
+ });
427
+ it("throws on an asset key shadowing the reserved runtime directory", () => {
428
+ const ctx = asContext(app_playground_json_1.default);
429
+ ctx.outputs.appPages[0].assets[`${manifest_1.RUNTIME_DIR_NAME}/lambda.mjs`] =
430
+ "/repo/whatever.mjs";
431
+ expect(() => build(ctx)).toThrow(new RegExp(`"${manifest_1.RUNTIME_DIR_NAME}/" is reserved`));
432
+ });
433
+ it("throws when two outputs claim one pathname from different files", () => {
434
+ const ctx = asContext(app_playground_json_1.default);
435
+ ctx.outputs.appRoutes[0].pathname = ctx.outputs.appPages[0].pathname;
436
+ expect(() => build(ctx)).toThrow(/claim the pathname "[^"]+"/);
437
+ });
438
+ });
439
+ describe("writeBuildOutputs", () => {
440
+ /**
441
+ * Builds a throwaway repo on disk so staging can be exercised for real:
442
+ * fixture sources are `/repo` placeholders and cannot be copied.
443
+ */
444
+ /**
445
+ * A `next` install just real enough for {@link addRuntimeNextClosure}: the
446
+ * modules `src/runtime/image.ts` requires, one file only the trace reaches, and
447
+ * a stand-in for next's vendored `@vercel/nft` that reports them. Tracing for
448
+ * real is next's job, not ours; what is under test is that the closure is
449
+ * resolved from the project dir and staged under repo-root-relative keys.
450
+ */
451
+ async function installFakeNext(repoRoot, options = {}) {
452
+ // Under pnpm, `next` lives in the virtual store behind a link, and its own
453
+ // dependencies are links beside it.
454
+ const storeModules = (0, node_path_1.join)(repoRoot, "node_modules", ".pnpm", "next@1.0.0", "node_modules");
455
+ const nextRoot = options.pnpm
456
+ ? (0, node_path_1.join)(storeModules, "next")
457
+ : (0, node_path_1.join)(repoRoot, "node_modules", "next");
458
+ if (options.pnpm) {
459
+ const nextEnv = (0, node_path_1.join)(repoRoot, "node_modules", ".pnpm", "@next+env@1.0.0", "node_modules", "@next", "env");
460
+ await (0, promises_1.mkdir)(nextEnv, { recursive: true });
461
+ await (0, promises_1.writeFile)((0, node_path_1.join)(nextEnv, "index.js"), "// @next/env\n");
462
+ await (0, promises_1.writeFile)((0, node_path_1.join)(nextEnv, "package.json"), JSON.stringify({ name: "@next/env", main: "index.js" }));
463
+ await (0, promises_1.mkdir)((0, node_path_1.join)(storeModules, "@next"), { recursive: true });
464
+ await (0, promises_1.symlink)("../../../@next+env@1.0.0/node_modules/@next/env", (0, node_path_1.join)(storeModules, "@next", "env"));
465
+ await (0, promises_1.mkdir)(nextRoot, { recursive: true });
466
+ await (0, promises_1.symlink)(".pnpm/next@1.0.0/node_modules/next", (0, node_path_1.join)(repoRoot, "node_modules", "next"));
467
+ }
468
+ const files = [
469
+ "dist/server/config-shared.js",
470
+ "dist/shared/lib/image-config.js",
471
+ "dist/server/image-optimizer.js",
472
+ "dist/server/serve-static.js",
473
+ "dist/server/lib/router-utils/instrumentation-globals.external.js",
474
+ // Reached only through the trace, i.e. the reason tracing is needed.
475
+ "dist/shared/lib/match-remote-pattern.js",
476
+ ];
477
+ for (const file of files) {
478
+ const path = (0, node_path_1.join)(nextRoot, file);
479
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(path), { recursive: true });
480
+ await (0, promises_1.writeFile)(path, `// ${file}\n`);
481
+ }
482
+ // No `exports` field: `next/dist/**` is required by path.
483
+ await (0, promises_1.writeFile)((0, node_path_1.join)(nextRoot, "package.json"), JSON.stringify({ name: "next", version: "0.0.0-test" }));
484
+ const tracer = (0, node_path_1.join)(nextRoot, "dist", "compiled", "@vercel", "nft");
485
+ await (0, promises_1.mkdir)(tracer, { recursive: true });
486
+ await (0, promises_1.writeFile)((0, node_path_1.join)(tracer, "package.json"), JSON.stringify({ name: "@vercel/nft", main: "index.js" }));
487
+ await (0, promises_1.writeFile)((0, node_path_1.join)(tracer, "index.js"),
488
+ // Real nft returns paths relative to `base`, which is the repo root the
489
+ // adapter passes.
490
+ `const prefix = ${JSON.stringify((0, node_path_1.relative)(repoRoot, nextRoot).split(node_path_1.sep).join("/"))};\n` +
491
+ "const { realpathSync } = require('node:fs');\n" +
492
+ "const { relative } = require('node:path');\n" +
493
+ "exports.nodeFileTrace = async (entries, { base }) => {\n" +
494
+ // Like real nft, the entries themselves are in the list.
495
+ " const traced = entries\n" +
496
+ " .map((e) => relative(realpathSync(base), e))\n" +
497
+ " .filter((e) => !e.startsWith('..'));\n" +
498
+ " if (traced.some((e) => e.endsWith('image-optimizer.js'))) {\n" +
499
+ " traced.push(`${prefix}/dist/shared/lib/match-remote-pattern.js`);\n" +
500
+ " }\n" +
501
+ " return { fileList: new Set(traced) };\n" +
502
+ "};\n");
503
+ }
504
+ async function makeRepo(options = {}) {
505
+ const repoRoot = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-staging-"));
506
+ if (options.withNext || options.pnpmNext) {
507
+ await installFakeNext(repoRoot, { pnpm: options.pnpmNext });
508
+ }
509
+ const projectDir = (0, node_path_1.join)(repoRoot, "app");
510
+ const distDir = (0, node_path_1.join)(projectDir, ".next");
511
+ const entry = (0, node_path_1.join)(distDir, "server", "app", "page.js");
512
+ const dep = (0, node_path_1.join)(projectDir, "node_modules", "dep");
513
+ const store = (0, node_path_1.join)(repoRoot, "store", "pkg");
514
+ // pnpm's virtual store: one package reachable only from inside it, and one
515
+ // that also has a logical path (`app/node_modules/dep`).
516
+ const virtualStore = (0, node_path_1.join)(repoRoot, "node_modules", ".pnpm");
517
+ const hidden = (0, node_path_1.join)(virtualStore, "helpers@1.0.0", "node_modules", "@scope", "helpers");
518
+ const depInStore = (0, node_path_1.join)(virtualStore, "dep@1.0.0", "node_modules", "dep");
519
+ // The shape that makes a store package reachable from another store
520
+ // package: a link between two store directories, no files of its own.
521
+ const hiddenLink = (0, node_path_1.join)(virtualStore, "dep@1.0.0", "node_modules", "@scope", "helpers");
522
+ await (0, promises_1.mkdir)((0, node_path_1.join)(distDir, "server", "app"), { recursive: true });
523
+ // Every deployment root needs this, and `loadRuntime` refuses to serve
524
+ // without it, so the staging plan carries it independently of any output's
525
+ // traced assets.
526
+ await (0, promises_1.writeFile)((0, node_path_1.join)(distDir, "required-server-files.json"), "{}\n");
527
+ await (0, promises_1.mkdir)(dep, { recursive: true });
528
+ await (0, promises_1.mkdir)(store, { recursive: true });
529
+ await (0, promises_1.mkdir)(hidden, { recursive: true });
530
+ await (0, promises_1.mkdir)(depInStore, { recursive: true });
531
+ await (0, promises_1.writeFile)(entry, "module.exports = {};\n");
532
+ await (0, promises_1.writeFile)((0, node_path_1.join)(dep, "index.js"), "// dep\n");
533
+ await (0, promises_1.writeFile)((0, node_path_1.join)(store, "index.js"), "// store\n");
534
+ await (0, promises_1.writeFile)((0, node_path_1.join)(hidden, "index.js"), "// helpers\n");
535
+ await (0, promises_1.writeFile)((0, node_path_1.join)(depInStore, "index.js"), "// dep\n");
536
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(hiddenLink), { recursive: true });
537
+ await (0, promises_1.symlink)((0, node_path_1.join)("..", "..", "..", "helpers@1.0.0", "node_modules", "@scope", "helpers"), hiddenLink);
538
+ await (0, promises_1.writeFile)((0, node_path_1.join)(projectDir, ".env"), "SHARED=1\n");
539
+ await (0, promises_1.writeFile)((0, node_path_1.join)(projectDir, ".env.production"), "PROD=1\n");
540
+ // A relative link whose target is itself staged: pnpm's common shape.
541
+ await (0, promises_1.symlink)("dep", (0, node_path_1.join)(projectDir, "node_modules", "rel-link"));
542
+ // An absolute link out of the tree: staging must materialize it instead.
543
+ await (0, promises_1.symlink)(store, (0, node_path_1.join)(projectDir, "node_modules", "abs-link"));
544
+ const output = {
545
+ id: "/",
546
+ pathname: "/",
547
+ sourcePage: "/page",
548
+ filePath: entry,
549
+ runtime: "nodejs",
550
+ config: {},
551
+ assets: {
552
+ "app/node_modules/dep/index.js": (0, node_path_1.join)(dep, "index.js"),
553
+ "app/node_modules/rel-link": (0, node_path_1.join)(projectDir, "node_modules", "rel-link"),
554
+ "app/node_modules/abs-link": (0, node_path_1.join)(projectDir, "node_modules", "abs-link"),
555
+ "node_modules/.pnpm/helpers@1.0.0/node_modules/@scope/helpers/index.js": (0, node_path_1.join)(hidden, "index.js"),
556
+ "node_modules/.pnpm/dep@1.0.0/node_modules/dep/index.js": (0, node_path_1.join)(depInStore, "index.js"),
557
+ "node_modules/.pnpm/dep@1.0.0/node_modules/@scope/helpers": hiddenLink,
558
+ },
559
+ assetsHashes: {},
560
+ };
561
+ const ctx = {
562
+ repoRoot,
563
+ projectDir,
564
+ distDir,
565
+ buildId: "test-build",
566
+ nextVersion: "16.3.5",
567
+ config: {
568
+ basePath: "",
569
+ trailingSlash: false,
570
+ assetPrefix: "",
571
+ i18n: null,
572
+ },
573
+ routing: { dynamicRoutes: [] },
574
+ outputs: {
575
+ pages: [],
576
+ pagesApi: [],
577
+ appPages: [output],
578
+ appRoutes: [],
579
+ prerenders: [],
580
+ staticFiles: [],
581
+ middleware: undefined,
582
+ },
583
+ };
584
+ return { ctx, repoRoot };
585
+ }
586
+ it("stages the tree, preserves symlinks, and writes the manifest", async () => {
587
+ const { ctx } = await makeRepo();
588
+ const result = await write(ctx);
589
+ expect(soleRoot(result)).toBe((0, node_path_1.join)(ctx.distDir, "cdk-nextjs-adapter", "app"));
590
+ const staged = (...parts) => (0, node_path_1.join)(soleRoot(result), ...parts);
591
+ await expect((0, promises_1.readFile)(staged("app", ".next", "server", "app", "page.js"), "utf8")).resolves.toContain("module.exports");
592
+ await expect((0, promises_1.readFile)(staged("app", "node_modules", "dep", "index.js"), "utf8")).resolves.toContain("dep");
593
+ // `copyFile` fails outright on a directory symlink, and dereferencing the
594
+ // pnpm store triples the tree against the 250 MB unzipped Lambda limit.
595
+ await expect((0, promises_1.lstat)(staged("app", "node_modules", "rel-link")).then((s) => s.isSymbolicLink())).resolves.toBe(true);
596
+ // Points outside the deployment root, so it would dangle in Lambda.
597
+ await expect((0, promises_1.lstat)(staged("app", "node_modules", "abs-link")).then((s) => s.isSymbolicLink())).resolves.toBe(false);
598
+ await expect((0, promises_1.readFile)(staged("app", "node_modules", "abs-link", "index.js"), "utf8")).resolves.toContain("store");
599
+ // `writeStandaloneDirectory` copies these; `onBuildComplete` has no
600
+ // equivalent, so dropping `output: "standalone"` drops them silently.
601
+ await expect((0, promises_1.readFile)(staged("app", ".env"), "utf8")).resolves.toContain("SHARED=1");
602
+ await expect((0, promises_1.readFile)(staged("app", ".env.production"), "utf8")).resolves.toContain("PROD=1");
603
+ const written = JSON.parse(await (0, promises_1.readFile)(result.manifestPath, "utf8"));
604
+ expect(written).toEqual(JSON.parse(JSON.stringify(result.manifest)));
605
+ expect(written.relativeProjectDir).toBe("app");
606
+ });
607
+ it("leaves store-only packages in the store, behind their links", async () => {
608
+ const { ctx } = await makeRepo();
609
+ const result = await write(ctx);
610
+ const staged = (...parts) => (0, node_path_1.join)(soleRoot(result), ...parts);
611
+ // Node resolves `@scope/helpers` from `dep` through the store link, as it
612
+ // does in the workspace, so long as nothing dereferences the tree (the
613
+ // Functions zip keeps links as links). A copy at the root is dead weight.
614
+ await expect((0, promises_1.lstat)(staged("node_modules", "@scope", "helpers"))).rejects.toThrow(/ENOENT/);
615
+ await expect((0, promises_1.lstat)(staged("node_modules", ".pnpm", "dep@1.0.0", "node_modules", "@scope", "helpers")).then((s) => s.isSymbolicLink())).resolves.toBe(true);
616
+ await expect((0, promises_1.readFile)(staged("node_modules", ".pnpm", "dep@1.0.0", "node_modules", "@scope", "helpers", "index.js"), "utf8")).resolves.toContain("helpers");
617
+ });
618
+ it("stages the next closure the runtime's image optimizer requires", async () => {
619
+ // `next build` traces what the *app* reaches, and no app reaches next's
620
+ // image optimizer, so without this every /_next/image request 500s on a
621
+ // MODULE_NOT_FOUND that nothing in the build warned about.
622
+ const { ctx } = await makeRepo({ withNext: true });
623
+ const result = await write(ctx);
624
+ const staged = (...parts) => (0, node_path_1.join)(soleRoot(result), ...parts);
625
+ await expect((0, promises_1.readFile)(staged("node_modules", "next", "dist", "server", "image-optimizer.js"), "utf8")).resolves.toContain("image-optimizer");
626
+ await expect((0, promises_1.readFile)(staged("node_modules", "next", "dist", "shared", "lib", "match-remote-pattern.js"), "utf8")).resolves.toContain("match-remote-pattern");
627
+ });
628
+ it("stages the link next resolves @next/env through under pnpm", async () => {
629
+ // The trace starts at `@next/env`'s real path and so never records the
630
+ // link beside `next`; without it every cold start threw "Cannot find
631
+ // module '@next/env'".
632
+ const { ctx } = await makeRepo({ pnpmNext: true });
633
+ const result = await write(ctx);
634
+ const link = (0, node_path_1.join)(soleRoot(result), "node_modules", ".pnpm", "next@1.0.0", "node_modules", "@next", "env");
635
+ expect((await (0, promises_1.lstat)(link)).isSymbolicLink()).toBe(true);
636
+ await expect((0, promises_1.readFile)((0, node_path_1.join)(link, "index.js"), "utf8")).resolves.toContain("@next/env");
637
+ });
638
+ it("warns instead of failing when next cannot be resolved for tracing", async () => {
639
+ const { ctx } = await makeRepo();
640
+ const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
641
+ await expect(write(ctx)).resolves.toBeDefined();
642
+ expect(warn).toHaveBeenCalledWith(expect.stringContaining("/_next/image will fail at runtime"));
643
+ });
644
+ it("removes a previous build's tree before staging", async () => {
645
+ const { ctx } = await makeRepo();
646
+ const first = await write(ctx);
647
+ const stale = (0, node_path_1.join)(soleRoot(first), "app", "stale.js");
648
+ await (0, promises_1.writeFile)(stale, "// removed route\n");
649
+ await write(ctx);
650
+ await expect((0, promises_1.lstat)(stale)).rejects.toThrow(/ENOENT/);
651
+ });
652
+ describe("with functionGroups", () => {
653
+ /**
654
+ * Two routes with one asset each, so "the group's tree holds its own route
655
+ * and not the other's" is checkable by file. Deliberately not `makeRepo`'s
656
+ * repo: its single output cannot be split.
657
+ */
658
+ async function makeSplittableRepo(options = {}) {
659
+ const repoRoot = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-groups-"));
660
+ if (options.withNext) {
661
+ await installFakeNext(repoRoot);
662
+ }
663
+ const projectDir = (0, node_path_1.join)(repoRoot, "app");
664
+ const distDir = (0, node_path_1.join)(projectDir, ".next");
665
+ await (0, promises_1.mkdir)((0, node_path_1.join)(distDir, "server", "app"), { recursive: true });
666
+ await (0, promises_1.writeFile)((0, node_path_1.join)(distDir, "required-server-files.json"), "{}\n");
667
+ const outputFor = async (name, pathname) => {
668
+ const entry = (0, node_path_1.join)(distDir, "server", "app", `${name}.js`);
669
+ const asset = (0, node_path_1.join)(projectDir, "node_modules", name, "index.js");
670
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(asset), { recursive: true });
671
+ await (0, promises_1.writeFile)(entry, `// ${name}\n`);
672
+ await (0, promises_1.writeFile)(asset, `// ${name} dep\n`);
673
+ return {
674
+ id: pathname,
675
+ pathname,
676
+ sourcePage: pathname,
677
+ filePath: entry,
678
+ runtime: "nodejs",
679
+ config: {},
680
+ assets: { [`app/node_modules/${name}/index.js`]: asset },
681
+ assetsHashes: {},
682
+ };
683
+ };
684
+ const ctx = {
685
+ repoRoot,
686
+ projectDir,
687
+ distDir,
688
+ buildId: "test-build",
689
+ nextVersion: "16.3.5",
690
+ config: {
691
+ basePath: "",
692
+ trailingSlash: false,
693
+ assetPrefix: "",
694
+ i18n: null,
695
+ },
696
+ routing: { dynamicRoutes: [] },
697
+ outputs: {
698
+ pages: options.withPagesSsr
699
+ ? await (async () => {
700
+ const page = await outputFor("ssr", "/ssr");
701
+ // A separate output, with its own id, backed by the same file.
702
+ const dataRoute = "/_next/data/test-build/ssr.json";
703
+ return [page, { ...page, id: dataRoute, pathname: dataRoute }];
704
+ })()
705
+ : [],
706
+ pagesApi: [],
707
+ appPages: [
708
+ await outputFor("home", "/"),
709
+ ...(options.withNotFound
710
+ ? [await outputFor("not-found", "/_not-found")]
711
+ : []),
712
+ ],
713
+ appRoutes: [await outputFor("reports", "/api/reports/[id]")],
714
+ prerenders: [],
715
+ staticFiles: [],
716
+ middleware: undefined,
717
+ },
718
+ };
719
+ return { ctx };
720
+ }
721
+ const groups = [{ name: "reports", routes: ["/api/reports/**"] }];
722
+ it("records the assignment in the manifest every group shares", async () => {
723
+ const { ctx } = await makeSplittableRepo();
724
+ const { manifest } = (0, build_outputs_1.buildAdapterManifest)(ctx, {
725
+ buildCwd: ctx.projectDir,
726
+ functionGroups: groups,
727
+ });
728
+ expect(manifest.groups).toEqual({
729
+ default: ["/"],
730
+ reports: ["/api/reports/[id]"],
731
+ });
732
+ // What synth compares its own props with, to catch a stale build.
733
+ expect(manifest.functionGroups).toEqual(groups);
734
+ // And what it deploys, as the assignment checked it.
735
+ expect(manifest.behaviors).toEqual([
736
+ {
737
+ group: "reports",
738
+ route: "/api/reports/**",
739
+ pattern: "api/reports/*",
740
+ },
741
+ ]);
742
+ });
743
+ it("stages one tree per group, each holding only its own routes", async () => {
744
+ const { ctx } = await makeSplittableRepo();
745
+ const result = await (0, build_outputs_1.writeBuildOutputs)(ctx, {
746
+ buildCwd: ctx.projectDir,
747
+ functionGroups: groups,
748
+ });
749
+ expect(result.stagedGroups.map((group) => group.name).sort()).toEqual([
750
+ "default",
751
+ "reports",
752
+ ]);
753
+ const pathOf = (name) => {
754
+ const group = result.stagedGroups.find((it) => it.name === name);
755
+ if (!group) {
756
+ throw new Error(`No staged group "${name}"`);
757
+ }
758
+ return group.path;
759
+ };
760
+ // Under `groups/<name>/`, so neither can collide with the unsplit layout.
761
+ expect(pathOf("reports")).toBe((0, node_path_1.join)(ctx.distDir, "cdk-nextjs-adapter", "groups", "reports"));
762
+ expect(pathOf("default")).toBe((0, node_path_1.join)(ctx.distDir, "cdk-nextjs-adapter", "groups", "default"));
763
+ const has = (name, ...parts) => (0, promises_1.lstat)((0, node_path_1.join)(pathOf(name), ...parts)).then(() => true, () => false);
764
+ await expect(has("reports", "app", ".next", "server", "app", "reports.js")).resolves.toBe(true);
765
+ await expect(has("reports", "app", "node_modules", "reports", "index.js")).resolves.toBe(true);
766
+ // The point of splitting: the other group's route is absent.
767
+ await expect(has("reports", "app", ".next", "server", "app", "home.js")).resolves.toBe(false);
768
+ await expect(has("default", "app", ".next", "server", "app", "home.js")).resolves.toBe(true);
769
+ await expect(has("default", "app", ".next", "server", "app", "reports.js")).resolves.toBe(false);
770
+ // The manifest is written once, above the groups; `NextjsBuild` copies it
771
+ // and the runtime shell into each group's reserved runtime dir afterwards,
772
+ // so no group's staged tree may contain that directory yet.
773
+ expect(result.manifestPath).toBe((0, node_path_1.join)(ctx.distDir, "cdk-nextjs-adapter", "manifest.json"));
774
+ for (const name of ["default", "reports"]) {
775
+ await expect(has(name, manifest_1.RUNTIME_DIR_NAME)).resolves.toBe(false);
776
+ }
777
+ // `required-server-files.json` is not any output's traced asset, so a
778
+ // group that reaches it only through the outputs it owns does not get it -
779
+ // and `loadRuntime` probes for it before serving anything, so the whole
780
+ // root answers "the deployment package is incomplete" without it.
781
+ for (const name of ["default", "reports"]) {
782
+ await expect(has(name, "app", ".next", "required-server-files.json")).resolves.toBe(true);
783
+ }
784
+ });
785
+ it("stages the image optimizer into default only, serve-static into every group", async () => {
786
+ // Only `default` answers `/_next/image`, and the optimizer is what pulls
787
+ // `sharp` in; prerendered and static results are served with
788
+ // `serve-static` in whichever group they land.
789
+ const { ctx } = await makeSplittableRepo({ withNext: true });
790
+ const result = await (0, build_outputs_1.writeBuildOutputs)(ctx, {
791
+ buildCwd: ctx.projectDir,
792
+ functionGroups: groups,
793
+ });
794
+ const has = (name, file) => (0, promises_1.lstat)((0, node_path_1.join)(result.stagedGroups.find((it) => it.name === name).path, "node_modules", "next", "dist", file)).then(() => true, () => false);
795
+ for (const file of [
796
+ "server/image-optimizer.js",
797
+ "shared/lib/image-config.js",
798
+ "server/config-shared.js",
799
+ "shared/lib/match-remote-pattern.js",
800
+ ]) {
801
+ await expect(has("default", file)).resolves.toBe(true);
802
+ await expect(has("reports", file)).resolves.toBe(false);
803
+ }
804
+ for (const name of ["default", "reports"]) {
805
+ await expect(has(name, "server/serve-static.js")).resolves.toBe(true);
806
+ await expect(has(name, "server/lib/router-utils/instrumentation-globals.external.js")).resolves.toBe(true);
807
+ }
808
+ });
809
+ it("stages the not-found page into every group, not only its owner", async () => {
810
+ // The runtime renders a 404 with the manifest's `/_not-found` wherever the
811
+ // request landed, so `/api/reports/nope` needs it in the reports group.
812
+ const { ctx } = await makeSplittableRepo({ withNotFound: true });
813
+ const { groups: staged, manifest } = (0, build_outputs_1.buildAdapterManifest)(ctx, {
814
+ buildCwd: ctx.projectDir,
815
+ functionGroups: groups,
816
+ });
817
+ expect(manifest.groups?.default).toContain("/_not-found");
818
+ expect(staged.map((group) => group.name).sort()).toEqual([
819
+ "default",
820
+ "reports",
821
+ ]);
822
+ for (const group of staged) {
823
+ expect([...group.staging.keys()]).toContain("app/.next/server/app/not-found.js");
824
+ }
825
+ });
826
+ it("keeps a Pages Router page's data route in the page's group", async () => {
827
+ const { ctx } = await makeSplittableRepo({ withPagesSsr: true });
828
+ const { groups: staged, manifest } = (0, build_outputs_1.buildAdapterManifest)(ctx, {
829
+ buildCwd: ctx.projectDir,
830
+ functionGroups: [{ name: "ssr", routes: ["/ssr"] }],
831
+ });
832
+ expect(manifest.groups?.ssr).toEqual([
833
+ "/_next/data/test-build/ssr.json",
834
+ "/ssr",
835
+ ]);
836
+ const defaultGroup = staged.find((group) => group.name === "default");
837
+ // Otherwise the page and its trace ship in the default zip as well.
838
+ expect([...defaultGroup.staging.keys()]).not.toContain("app/.next/server/app/ssr.js");
839
+ });
840
+ it("refuses to split an i18n app, whose routes are locale-prefixed", async () => {
841
+ const { ctx } = await makeSplittableRepo();
842
+ const i18nCtx = {
843
+ ...ctx,
844
+ config: {
845
+ ...ctx.config,
846
+ i18n: { locales: ["en"], defaultLocale: "en" },
847
+ },
848
+ };
849
+ expect(() => (0, build_outputs_1.buildAdapterManifest)(i18nCtx, {
850
+ buildCwd: ctx.projectDir,
851
+ functionGroups: groups,
852
+ })).toThrow(/cannot be combined with `i18n`/);
853
+ });
854
+ it("throws on a pattern that matches nothing, rather than silently not splitting", async () => {
855
+ const { ctx } = await makeSplittableRepo();
856
+ expect(() => (0, build_outputs_1.buildAdapterManifest)(ctx, {
857
+ buildCwd: ctx.projectDir,
858
+ functionGroups: [{ name: "typo", routes: ["/api/report/**"] }],
859
+ })).toThrow(/matches no route in this build/);
860
+ });
861
+ });
862
+ });
863
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtb3V0cHV0cy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FkYXB0ZXIvYnVpbGQtb3V0cHV0cy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0NBTzBCO0FBQzFCLHFDQUFpQztBQUNqQyx5Q0FBeUQ7QUFDekQsaUhBQWlGO0FBQ2pGLDZGQUErRDtBQUMvRCxxRkFBdUQ7QUFDdkQsbURBSXlCO0FBQ3pCLGtEQUF1RDtBQUV2RDs7OztHQUlHO0FBQ0gsTUFBTSxRQUFRLEdBQUc7SUFDZixnQkFBZ0IsRUFBRSw2QkFBYTtJQUMvQiwwQkFBMEIsRUFBRSx1Q0FBcUI7SUFDakQsWUFBWSxFQUFFLHlCQUFTO0NBQ2YsQ0FBQztBQUVYLDBFQUEwRTtBQUMxRSxNQUFNLFNBQVMsR0FBRyxDQUFDLE9BQWdCLEVBQXdCLEVBQUUsQ0FDM0QsZUFBZSxDQUFDLE9BQU8sQ0FBeUIsQ0FBQztBQUVuRDs7Ozs7R0FLRztBQUNILE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBeUIsRUFBRSxFQUFFLENBQzFDLElBQUEsb0NBQW9CLEVBQUMsR0FBRyxFQUFFLEVBQUUsUUFBUSxFQUFFLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0FBQzFELE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBeUIsRUFBRSxFQUFFLENBQzFDLElBQUEsaUNBQWlCLEVBQUMsR0FBRyxFQUFFLEVBQUUsUUFBUSxFQUFFLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0FBRXZEOzs7O0dBSUc7QUFDSCxNQUFNLFFBQVEsR0FBRyxDQUFDLE1BQWlELEVBQUUsRUFBRTtJQUNyRSxNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QyxPQUFPLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ3JDLENBQUMsQ0FBQztBQUVGLFVB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LENBQUMsQ0FDSCxDQUFDLE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQzlDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDhFQUE4RSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzVGLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxNQUFNLGtCQUFrQixFQUFFLENBQUM7WUFDM0MsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUNWLElBQUEsb0NBQW9CLEVBQUMsR0FBRyxFQUFFO2dCQUN4QixRQUFRLEVBQUUsR0FBRyxDQUFDLFVBQVU7Z0JBQ3hCLGNBQWMsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7YUFDL0QsQ0FBQyxDQUNILENBQUMsT0FBTyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgbHN0YXQsXG4gIG1rZGlyLFxuICBta2R0ZW1wLFxuICByZWFkRmlsZSxcbiAgc3ltbGluayxcbiAgd3JpdGVGaWxlLFxufSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgdG1wZGlyIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4sIHJlbGF0aXZlLCBzZXAgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgYXBwUGxheWdyb3VuZEJhc2VQYXRoIGZyb20gXCIuL19fZml4dHVyZXNfXy9hcHAtcGxheWdyb3VuZC1iYXNlLXBhdGguanNvblwiO1xuaW1wb3J0IGFwcFBsYXlncm91bmQgZnJvbSBcIi4vX19maXh0dXJlc19fL2FwcC1wbGF5Z3JvdW5kLmpzb25cIjtcbmltcG9ydCBwYWdlc0kxOG4gZnJvbSBcIi4vX19maXh0dXJlc19fL3BhZ2VzLWkxOG4uanNvblwiO1xuaW1wb3J0IHtcbiAgQnVpbGRDb21wbGV0ZUNvbnRleHQsXG4gIGJ1aWxkQWRhcHRlck1hbmlmZXN0LFxuICB3cml0ZUJ1aWxkT3V0cHV0cyxcbn0gZnJvbSBcIi4vYnVpbGQtb3V0cHV0c1wiO1xuaW1wb3J0IHsgUlVOVElNRV9ESVJfTkFNRSB9IGZyb20gXCIuLi9ydW50aW1lL21hbmlmZXN0XCI7XG5cbi8qKlxuICogVGhlIGZpeHR1cmVzIGFyZSByZWFsIGBvbkJ1aWxkQ29tcGxldGVgIGNvbnRleHRzIGNhcHR1cmVkIGJ5XG4gKiBgc2NyaXB0cy9jYXB0dXJlLWFkYXB0ZXItZml4dHVyZS5tanNgLCB3aXRoIGFic29sdXRlIHBhdGhzIHJld3JpdHRlbiB0byBhXG4gKiBgL3JlcG9gIHBsYWNlaG9sZGVyLiBSZWdlbmVyYXRlIHRoZW0gd2hlbiBgbmV4dGAgaXMgdXBncmFkZWQuXG4gKi9cbmNvbnN0IGZpeHR1cmVzID0ge1xuICBcImFwcC1wbGF5Z3JvdW5kXCI6IGFwcFBsYXlncm91bmQsXG4gIFwiYXBwLXBsYXlncm91bmQtYmFzZS1wYXRoXCI6IGFwcFBsYXlncm91bmRCYXNlUGF0aCxcbiAgXCJwYWdlcy1pMThuXCI6IHBhZ2VzSTE4bixcbn0gYXMgY29uc3Q7XG5cbi8qKiBGaXh0dXJlcyBhcmUgSlNPTiwgc28gdGhlIHN0cnVjdHVyYWwgY2FzdCBpcyB0aGUgcG9pbnQgb2YgdGhlIGNhc3QuICovXG5jb25zdCBhc0NvbnRleHQgPSAoZml4dHVyZTogdW5rbm93bik6IEJ1aWxkQ29tcGxldGVDb250ZXh0ID0+XG4gIHN0cnVjdHVyZWRDbG9uZShmaXh0dXJlKSBhcyBCdWlsZENvbXBsZXRlQ29udGV4dDtcblxuLyoqXG4gKiBgYnVpbGRBZGFwdGVyTWFuaWZlc3RgIHJlcXVpcmVzIHRoZSBidWlsZCBjd2QgdG8gYmUgdGhlIHByb2plY3QgZGlyIOKAlCBzZWVcbiAqIGBhc3NlcnRCdWlsZEN3ZGAuIFRoZSBmaXh0dXJlcycgcHJvamVjdCBkaXJzIGFyZSBzeW50aGV0aWMgYC9yZXBvL+KApmAgcGF0aHMsIHNvXG4gKiBldmVyeSBjYWxsIHN1cHBsaWVzIGl0IHJhdGhlciB0aGFuIGxldHRpbmcgaXQgZGVmYXVsdCB0byBgcHJvY2Vzcy5jd2QoKWAuIFRoZVxuICogYXNzZXJ0aW9uIGl0c2VsZiBpcyBjb3ZlcmVkIHNlcGFyYXRlbHkgYmVsb3cuXG4gKi9cbmNvbnN0IGJ1aWxkID0gKGN0eDogQnVpbGRDb21wbGV0ZUNvbnRleHQpID0+XG4gIGJ1aWxkQWRhcHRlck1hbmlmZXN0KGN0eCwgeyBidWlsZEN3ZDogY3R4LnByb2plY3REaXIgfSk7XG5jb25zdCB3cml0ZSA9IChjdHg6IEJ1aWxkQ29tcGxldGVDb250ZXh0KSA9PlxuICB3cml0ZUJ1aWxkT3V0cHV0cyhjdHgsIHsgYnVpbGRDd2Q6IGN0eC5wcm9qZWN0RGlyIH0pO1xuXG4vKipcbiAqIFRoZSBvbmUgZGVwbG95bWVudCByb290IGFuIHVuc3BsaXQgYnVpbGQgc3RhZ2VzLiBBc3NlcnRlZCByYXRoZXIgdGhhbiBpbmRleGVkXG4gKiBzbyBhIHJlZ3Jlc3Npb24gdGhhdCBzdGFydHMgc3BsaXR0aW5nIHVuYXNrZWQgZmFpbHMgaGVyZSBpbnN0ZWFkIG9mIHNpbGVudGx5XG4gKiBjaGVja2luZyBncm91cCAwLlxuICovXG5jb25zdCBzb2xlUm9vdCA9IChyZXN1bHQ6IHsgc3RhZ2VkR3JvdXBzOiBBcnJheTx7IHBhdGg6IHN0cmluZyB9PiB9KSA9PiB7XG4gIGV4cGVjdChyZXN1bHQuc3RhZ2VkR3JvdXBzKS50b0hhdmVMZW5ndGgoMSk7XG4gIHJldHVybiByZXN1bHQuc3RhZ2VkR3JvdXBzWzBdLnBhdGg7XG59O1xuXG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgLy8gYG1heER1cmF0aW9uYCB3YXJuaW5ncyBhcmUgZXhwZWN0ZWQgZnJvbSB0aGUgcGFnZXMtaTE4biBmaXh0dXJlLlxuICBqZXN0LnNweU9uKGNvbnNvbGUsIFwid2FyblwiKS5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4ge30pO1xufSk7XG5cbmFmdGVyRWFjaCgoKSA9PiB7XG4gIGplc3QucmVzdG9yZUFsbE1vY2tzKCk7XG59KTtcblxuZGVzY3JpYmUuZWFjaChPYmplY3Qua2V5cyhmaXh0dXJlcykgYXMgQXJyYXk8a2V5b2YgdHlwZW9mIGZpeHR1cmVzPikoXG4gIFwiYnVpbGRBZGFwdGVyTWFuaWZlc3QoJXMpXCIsXG4gIChuYW1lKSA9PiB7XG4gICAgY29uc3QgY3R4ID0gYXNDb250ZXh0KGZpeHR1cmVzW25hbWVdKTtcbiAgICBjb25zdCB7XG4gICAgICBtYW5pZmVzdCxcbiAgICAgIGdyb3VwczogW3sgc3RhZ2luZyB9XSxcbiAgICB9ID0gYnVpbGQoY3R4KTtcblxuICAgIGl0KFwic3RhbXBzIHRoZSBtYW5pZmVzdCB2ZXJzaW9uIGFuZCBidWlsZCBpZGVudGl0eVwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QobWFuaWZlc3QudmVyc2lvbikudG9CZSgxKTtcbiAgICAgIGV4cGVjdChtYW5pZmVzdC5idWlsZElkKS50b0JlKGN0eC5idWlsZElkKTtcbiAgICAgIGV4cGVjdChtYW5pZmVzdC5yZWxhdGl2ZVByb2plY3REaXIpLnRvQmUoXG4gICAgICAgIG5hbWUuc3RhcnRzV2l0aChcInBhZ2VzLWkxOG5cIikgPyBcInBhZ2VzLWkxOG5cIiA6IFwiYXBwLXBsYXlncm91bmRcIixcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdChcImNvcGllcyB0aGUgY29uZmlnIGZpZWxkcyB0aGUgcnVudGltZSByb3V0ZXIgbmVlZHNcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KG1hbmlmZXN0LmNvbmZpZykudG9FcXVhbCh7XG4gICAgICAgIGJhc2VQYXRoOiBjdHguY29uZmlnLmJhc2VQYXRoID8/IFwiXCIsXG4gICAgICAgIHRyYWlsaW5nU2xhc2g6IGN0eC5jb25maWcudHJhaWxpbmdTbGFzaCA9PT0gdHJ1ZSxcbiAgICAgICAgYXNzZXRQcmVmaXg6IGN0eC5jb25maWcuYXNzZXRQcmVmaXggPz8gXCJcIixcbiAgICAgICAgZGlzdERpcjogXCIubmV4dFwiLFxuICAgICAgICBjb21wcmVzczogdHJ1ZSxcbiAgICAgICAgZ2VuZXJhdGVFdGFnczogdHJ1ZSxcbiAgICAgICAgaTE4bjogY3R4LmNvbmZpZy5pMThuID8/IG51bGwsXG4gICAgICAgIGRlcGxveW1lbnRJZDogXCJcIixcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJwZXJzaXN0cyBjdHgucm91dGluZyB2ZXJiYXRpbVwiLCAoKSA9PiB7XG4gICAgICAvLyBgQG5leHQvcm91dGluZ2AncyBgcmVzb2x2ZVJvdXRlc2AgY29uc3VtZXMgdGhpcyB3aG9sZSBvYmplY3Q7IGFueXRoaW5nIHdlXG4gICAgICAvLyByZXNoYXBlIGhlcmUgaXMgYSBiZWhhdmlvciBkaWZmZXJlbmNlIGZyb20gYG5leHQgc3RhcnRgLlxuICAgICAgZXhwZWN0KG1hbmlmZXN0LnJvdXRpbmcpLnRvRXF1YWwoY3R4LnJvdXRpbmcpO1xuICAgICAgZXhwZWN0KG1hbmlmZXN0LnJvdXRpbmcpLnRvSGF2ZVByb3BlcnR5KFwibWlkZGxld2FyZU1hdGNoZXJzXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJtYXBzIGV2ZXJ5IGludm9jYWJsZSBvdXRwdXQgcGF0aG5hbWUgdG8gYW4gZW50cnlwb2ludFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IFtcbiAgICAgICAgLi4uY3R4Lm91dHB1dHMucGFnZXMsXG4gICAgICAgIC4uLmN0eC5vdXRwdXRzLnBhZ2VzQXBpLFxuICAgICAgICAuLi5jdHgub3V0cHV0cy5hcHBQYWdlcyxcbiAgICAgICAgLi4uY3R4Lm91dHB1dHMuYXBwUm91dGVzLFxuICAgICAgXS5tYXAoKG8pID0+IG8ucGF0aG5hbWUpO1xuICAgICAgLy8gUGx1cyBkeW5hbWljIHByZXJlbmRlciB0ZW1wbGF0ZXMsIHdoaWNoIGBhZGRQcmVyZW5kZXJQYXRobmFtZXNgIG1hcHMgdG9cbiAgICAgIC8vIHRoZSBlbnRyeXBvaW50IG9mIHRoZSByb3V0ZSB0aGF0IG93bnMgdGhlbS4gTm9uZSBvZiB0aGVzZSBmaXh0dXJlcyBoYXMgYVxuICAgICAgLy8gZ2F0ZWQgZHluYW1pYyByb3V0ZSwgc28gbm8gKmNvbmNyZXRlKiBwcmVyZW5kZXIgcGF0aG5hbWUgaXMgYWRkZWQgLSBzZWVcbiAgICAgIC8vIHRoZSByb290LXBhcmFtcyB0ZXN0IGJlbG93LlxuICAgICAgY29uc3QgdGVtcGxhdGVzID0gY3R4Lm91dHB1dHMucHJlcmVuZGVyc1xuICAgICAgICAuZmlsdGVyKChvKSA9PiBvLnBhdGhuYW1lLmluY2x1ZGVzKFwiW1wiKSlcbiAgICAgICAgLm1hcCgobykgPT4gby5wYXRobmFtZSk7XG4gICAgICBleHBlY3QoT2JqZWN0LmtleXMobWFuaWZlc3QuZW50cnlwb2ludHMpLnNvcnQoKSkudG9FcXVhbChcbiAgICAgICAgWy4uLm5ldyBTZXQoWy4uLmV4cGVjdGVkLCAuLi50ZW1wbGF0ZXNdKV0uc29ydCgpLFxuICAgICAgKTtcbiAgICAgIGZvciAoY29uc3QgW3BhdGhuYW1lLCBlbnRyeV0gb2YgT2JqZWN0LmVudHJpZXMobWFuaWZlc3QuZW50cnlwb2ludHMpKSB7XG4gICAgICAgIGV4cGVjdChlbnRyeS5maWxlUGF0aCkudG9NYXRjaCgvXlteL10vKTtcbiAgICAgICAgZXhwZWN0KGVudHJ5LmZpbGVQYXRoKS5ub3QudG9Db250YWluKFwiXFxcXFwiKTtcbiAgICAgICAgZXhwZWN0KHN0YWdpbmcuaGFzKGVudHJ5LmZpbGVQYXRoKSkudG9CZSh0cnVlKTtcbiAgICAgICAgZXhwZWN0KGVudHJ5LmlkKS50b0JlVHJ1dGh5KCk7XG4gICAgICAgIGV4cGVjdChbXCJhcHAtcGFnZVwiLCBcImFwcC1yb3V0ZVwiLCBcInBhZ2VcIiwgXCJwYWdlLWFwaVwiXSkudG9Db250YWluKFxuICAgICAgICAgIGVudHJ5LnR5cGUsXG4gICAgICAgICk7XG4gICAgICAgIGV4cGVjdChwYXRobmFtZSkudG9CZVRydXRoeSgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoXCJsaXN0cyBwYXRobmFtZXMgYXMgdGhlIHNvcnRlZCB1bmlvbiBvZiBlbnRyeXBvaW50cyBhbmQgc3RhdGljIGZpbGVzXCIsICgpID0+IHtcbiAgICAgIGV4cGVjdChtYW5pZmVzdC5wYXRobmFtZXMpLnRvRXF1YWwoWy4uLm1hbmlmZXN0LnBhdGhuYW1lc10uc29ydCgpKTtcbiAgICAgIGV4cGVjdChuZXcgU2V0KG1hbmlmZXN0LnBhdGhuYW1lcykuc2l6ZSkudG9CZShtYW5pZmVzdC5wYXRobmFtZXMubGVuZ3RoKTtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKG1hbmlmZXN0LmVudHJ5cG9pbnRzKSkge1xuICAgICAgICBleHBlY3QobWFuaWZlc3QucGF0aG5hbWVzKS50b0NvbnRhaW4oa2V5KTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBjdHgub3V0cHV0cy5zdGF0aWNGaWxlcykge1xuICAgICAgICBleHBlY3QobWFuaWZlc3QucGF0aG5hbWVzKS50b0NvbnRhaW4oZmlsZS5wYXRobmFtZSk7XG4gICAgICB9XG4gICAgICAvLyBPbmUgcmVwb3J0ZWQgcGF0aG5hbWUgY2FuIHByb2R1Y2UgdHdvIGtleXMgLSBhIGAvaW5kZXhgIHN0YXRpYyBmaWxlIGlzXG4gICAgICAvLyBhbHNvIHNlcnZlZCBhdCBgL2AsIHNlZSB0aGUgc3RhdGljLWhvbWUtcGFnZSB0ZXN0cyBiZWxvdy4gTm9uZSBvZiB0aGVzZVxuICAgICAgLy8gZml4dHVyZXMgaGFzIG9uZSwgc28gaGVyZSB0aGUgdHdvIHNldHMgY29pbmNpZGUuXG4gICAgICBleHBlY3QoT2JqZWN0LmtleXMobWFuaWZlc3Quc3RhdGljRmlsZXMpKS50b0VxdWFsKFxuICAgICAgICBbLi4ubmV3IFNldChjdHgub3V0cHV0cy5zdGF0aWNGaWxlcy5tYXAoKGYpID0+IGYucGF0aG5hbWUpKV0uc29ydCgpLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KFwibWFwcyBlYWNoIHN0YXRpYyBmaWxlIHRvIGEgcmVwby1yb290LXJlbGF0aXZlIGtleVwiLCAoKSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IFtwYXRobmFtZSwga2V5XSBvZiBPYmplY3QuZW50cmllcyhtYW5pZmVzdC5zdGF0aWNGaWxlcykpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gY3R4Lm91dHB1dHMuc3RhdGljRmlsZXMuZmluZChcbiAgICAgICAgICAoZikgPT4gZi5wYXRobmFtZSA9PT0gcGF0aG5hbWUsXG4gICAgICAgICkhO1xuICAgICAgICBleHBlY3Qoa2V5KS50b0JlKG91dHB1dC5maWxlUGF0aC5yZXBsYWNlKFwiL3JlcG8vXCIsIFwiXCIpKTtcbiAgICAgICAgZXhwZWN0KGtleS5zdGFydHNXaXRoKFwiL1wiKSkudG9CZShmYWxzZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdChcInN0YWdlcyB0aGUgc3RhdGljIGZpbGVzIG5vdGhpbmcgaW4gZnJvbnQgb2YgdGhlIGNvbXB1dGUgc2VydmVzXCIsICgpID0+IHtcbiAgICAgIC8vIGA8ZGlzdERpcj4vc3RhdGljYCBnb2VzIHRvIFMzOyBgPGRpc3REaXI+L3NlcnZlci8qKmAgKDQwNC5odG1sLFxuICAgICAgLy8gZmF2aWNvbi5pY28uYm9keSwgZnVsbHktc3RhdGljIFBhZ2VzIFJvdXRlciBIVE1MKSBkb2VzIG5vdCwgc28gdGhlXG4gICAgICAvLyBydW50aW1lIG11c3QgYmUgYWJsZSB0byByZWFkIGl0IG9mZiBkaXNrLlxuICAgICAgZm9yIChjb25zdCBbcGF0aG5hbWUsIGtleV0gb2YgT2JqZWN0LmVudHJpZXMobWFuaWZlc3Quc3RhdGljRmlsZXMpKSB7XG4gICAgICAgIGNvbnN0IHNlcnZlZEJ5UzMgPSBwYXRobmFtZS5pbmNsdWRlcyhcIi9fbmV4dC9zdGF0aWMvXCIpO1xuICAgICAgICBleHBlY3Qoc3RhZ2luZy5oYXMoa2V5KSkudG9CZSghc2VydmVkQnlTMyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdChcInN0YWdlcyBvbmx5IGtleXMgdGhhdCBsYW5kIGluc2lkZSB0aGUgZGVwbG95bWVudCByb290XCIsICgpID0+IHtcbiAgICAgIGV4cGVjdChzdGFnaW5nLnNpemUpLnRvQmVHcmVhdGVyVGhhbigwKTtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIHN0YWdpbmcua2V5cygpKSB7XG4gICAgICAgIGV4cGVjdChrZXkpLm5vdC50b0JlKFwiXCIpO1xuICAgICAgICBleHBlY3Qoa2V5LnN0YXJ0c1dpdGgoXCIvXCIpKS50b0JlKGZhbHNlKTtcbiAgICAgICAgZXhwZWN0KGtleS5zdGFydHNXaXRoKFwiLi5cIikpLnRvQmUoZmFsc2UpO1xuICAgICAgICBleHBlY3Qoa2V5LnN0YXJ0c1dpdGgoYCR7UlVOVElNRV9ESVJfTkFNRX0vYCkpLnRvQmUoZmFsc2UpO1xuICAgICAgfVxuICAgICAgLy8gVGhlIHRyYWNlZCBgbmV4dGAgY2xvc3VyZSBpcyBtZXJnZWQgaW50byBldmVyeSBvdXRwdXQsIHNvIHN0YWdpbmcgaXMgZmFyXG4gICAgICAvLyBzbWFsbGVyIHRoYW4gdGhlIHN1bSBvZiB0aGUgcGVyLW91dHB1dCBgYXNzZXRzYCBtYXBzLlxuICAgICAgZXhwZWN0KHN0YWdpbmcuc2l6ZSkudG9CZUxlc3NUaGFuKFxuICAgICAgICBjdHgub3V0cHV0cy5hcHBQYWdlcy5sZW5ndGggKiAxMDAgK1xuICAgICAgICAgIGN0eC5vdXRwdXRzLnBhZ2VzLmxlbmd0aCAqIDEwMCArXG4gICAgICAgICAgMTAwMCxcbiAgICAgICk7XG4gICAgfSk7XG4gIH0sXG4pO1xuXG5kZXNjcmliZShcImJ1aWxkQWRhcHRlck1hbmlmZXN0IGVkZ2UgY2FzZXNcIiwgKCkgPT4ge1xuICBpdChcInRocm93cyB3aGVuIGBuZXh0IGJ1aWxkYCByYW4gZnJvbSBvdXRzaWRlIHRoZSBwcm9qZWN0IGRpcmVjdG9yeVwiLCAoKSA9PiB7XG4gICAgY29uc3QgY3R4ID0gYXNDb250ZXh0KGFwcFBsYXlncm91bmQpO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZEFkYXB0ZXJNYW5pZmVzdChjdHgsIHsgYnVpbGRDd2Q6IFwiL3JlcG9cIiB9KSkudG9UaHJvdyhcbiAgICAgIC9tdXN0IHJ1biBmcm9tIHRoZSBOZXh0LmpzIHByb2plY3QgZGlyZWN0b3J5LyxcbiAgICApO1xuICB9KTtcblxuICBpdChcImRlZmF1bHRzIHRoZSBidWlsZCBjd2QgdG8gcHJvY2Vzcy5jd2QoKVwiLCAoKSA9PiB7XG4gICAgLy8gV2hpY2ggaXMgdGhpcyBwYWNrYWdlJ3Mgcm9vdCwgbmV2ZXIgYSBmaXh0dXJlJ3MgYC9yZXBvL+KApmAgcHJvamVjdCBkaXIsIHNvXG4gICAgLy8gdGhlIGFzc2VydGlvbiBmaXJlcyDigJQgcHJvdmluZyB0aGUgZGVmYXVsdCBpcyB3aXJlZCBhbmQgbm90IGp1c3QgdGhlIG9wdGlvbi5cbiAgICBleHBlY3QoKCkgPT4gYnVpbGRBZGFwdGVyTWFuaWZlc3QoYXNDb250ZXh0KGFwcFBsYXlncm91bmQpKSkudG9UaHJvdyhcbiAgICAgIC9tdXN0IHJ1biBmcm9tIHRoZSBOZXh0LmpzIHByb2plY3QgZGlyZWN0b3J5LyxcbiAgICApO1xuICB9KTtcblxuICBpdChcInJlY29yZHMgdGhlIGRlcGxveW1lbnRJZCwgcmVkdWNlZCB0byB3aGF0IGEgY2FjaGUga2V5IHByZWZpeCBjYW4gaG9sZFwiLCAoKSA9PiB7XG4gICAgLy8gYE5leHRqc0J1aWxkYCBzdWZmaXhlcyBpdHMgYGJ1aWxkSWRgIHdpdGggaXQ6IG5leHQgcGlucyB0aGUgYnVpbGQgSURcbiAgICAvLyBpdHNlbGYgb25jZSBgZGVwbG95bWVudElkYCBpcyBzZXQuXG4gICAgY29uc3QgY3R4ID0gYXNDb250ZXh0KGFwcFBsYXlncm91bmQpO1xuICAgIGNvbnN0IHsgbWFuaWZlc3QgfSA9IGJ1aWxkKHtcbiAgICAgIC4uLmN0eCxcbiAgICAgIGNvbmZpZzogeyAuLi5jdHguY29uZmlnLCBkZXBsb3ltZW50SWQ6IFwidjEuMi9tYWluXCIgfSxcbiAgICB9KTtcbiAgICBleHBlY3QobWFuaWZlc3QuY29uZmlnLmRlcGxveW1lbnRJZCkudG9CZShcInYxLTItbWFpblwiKTtcbiAgfSk7XG5cbiAgaXQoXCJrZXlzIGxvY2FsZSB2YXJpYW50cyBvZiBvbmUgcGFnZSB0byB0aGUgc2FtZSBlbnRyeXBvaW50IGZpbGVcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHsgbWFuaWZlc3QgfSA9IGJ1aWxkKGFzQ29udGV4dChwYWdlc0kxOG4pKTtcbiAgICAvLyBpMThuIGZhbnMgb25lIHBhZ2Ugb3V0IGludG8gb25lIG91dHB1dCBwZXIgbG9jYWxlLCBwbHVzIGFcbiAgICAvLyBgL19uZXh0L2RhdGEvPGJ1aWxkSWQ+L+KApmpzb25gIHNpYmxpbmcgZWFjaC4gVGhleSBzaGFyZSBgZmlsZVBhdGhgIGFuZFxuICAgIC8vIGB0eXBlYDsgYGlkYCBzdGF5cyBwZXItcGF0aG5hbWUgKGxvY2FsZS1wcmVmaXhlZCksIHNvIGl0IGlzIG5vdCBhIGRlZHVwIGtleS5cbiAgICBjb25zdCBzc3IgPSBbXG4gICAgICBcIi9zc3JcIixcbiAgICAgIFwiL2VuLVVTL3NzclwiLFxuICAgICAgXCIvZnIvc3NyXCIsXG4gICAgICBcIi9ubC1OTC9zc3JcIixcbiAgICAgIGAvX25leHQvZGF0YS8ke21hbmlmZXN0LmJ1aWxkSWR9L2ZyL3Nzci5qc29uYCxcbiAgICBdO1xuICAgIGZvciAoY29uc3QgcGF0aG5hbWUgb2Ygc3NyKSB7XG4gICAgICBleHBlY3QobWFuaWZlc3QuZW50cnlwb2ludHNbcGF0aG5hbWVdKS50b01hdGNoT2JqZWN0KHtcbiAgICAgICAgZmlsZVBhdGg6IG1hbmlmZXN0LmVudHJ5cG9pbnRzW1wiL3NzclwiXS5maWxlUGF0aCxcbiAgICAgICAgdHlwZTogXCJwYWdlXCIsXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1twYXRobmFtZV0uaWQpLnRvQmUocGF0aG5hbWUpO1xuICAgIH1cbiAgICBleHBlY3QobWFuaWZlc3QuZW50cnlwb2ludHNbXCIvc3NyXCJdLnR5cGUpLnRvQmUoXCJwYWdlXCIpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9hcGkvaGVsbG9cIl0udHlwZSkudG9CZShcInBhZ2UtYXBpXCIpO1xuICB9KTtcblxuICBpdChcImNhcnJpZXMgYmFzZVBhdGggaW4gcGF0aG5hbWVzIGJ1dCBub3QgaW4gZW50cnlwb2ludCBpZHNcIiwgKCkgPT4ge1xuICAgIC8vIGBvdXRwdXQucGF0aG5hbWVgIGlzIGJhc2VQYXRoLXByZWZpeGVkIHdoaWxlIGBvdXRwdXQuaWRgIGlzIG5vdC4gRGlzcGF0Y2hcbiAgICAvLyBrZXlzIG9mZiB0aGUgcGF0aG5hbWUsIHNvIHRoZSBwcmVmaXggaGFzIHRvIHN0YXkuXG4gICAgY29uc3QgeyBtYW5pZmVzdCB9ID0gYnVpbGQoYXNDb250ZXh0KGFwcFBsYXlncm91bmRCYXNlUGF0aCkpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5jb25maWcuYmFzZVBhdGgpLnRvQmUoXCIvcHJvZFwiKTtcbiAgICBleHBlY3QobWFuaWZlc3QuZW50cnlwb2ludHNbXCIvcHJvZC9hcGkvaGVhbHRoXCJdKS50b0JlRGVmaW5lZCgpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9wcm9kL2FwaS9oZWFsdGhcIl0uaWQpLnRvQmUoXCIvYXBpL2hlYWx0aFwiKTtcbiAgICBleHBlY3QobWFuaWZlc3QuZW50cnlwb2ludHNbXCIvYXBpL2hlYWx0aFwiXSkudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcblxuICAvKipcbiAgICogQSBQYWdlcyBSb3V0ZXIgaG9tZSBwYWdlIHJlYWNoZXMgdXMgYXMgYC9pbmRleGAsIHdoaWNoZXZlciBwb3B1bGF0aW9uIGl0IGxhbmRzXG4gICAqIGluOiBgbm9ybWFsaXplUGFnZVBhdGgoXCIvXCIpYCBpcyBgXCIvaW5kZXhcImAsIGFuZCB0aGUgYWRhcHRlciBob29rIHVzZXMgaXQgZm9yIGFcbiAgICogZnVsbHktc3RhdGljIHBhZ2UncyBgU1RBVElDX0ZJTEVgIGFuZCBmb3IgYW4gU1NHL1NTUiBwYWdlJ3MgYFBBR0VTYCBvdXRwdXRcbiAgICogYWxpa2UuIE5vdGhpbmcgZWxzZSBpbiB0aGUgb3V0cHV0cyBjYXJyaWVzIGAvYCwgc28gdGhlIG1hcHBpbmcgdW5kZXIgdGVzdCBpc1xuICAgKiB0aGUgb25seSB0aGluZyB0aGF0IG1ha2VzIHRoZSBob21lIHBhZ2Ugcm91dGFibGUuXG4gICAqL1xuICBmdW5jdGlvbiB3aXRoSG9tZVBhZ2UoXG4gICAgYmFzZVBhdGg6IHN0cmluZyxcbiAgICBraW5kOiBcInN0YXRpY1wiIHwgXCJpbnZvY2FibGVcIixcbiAgKTogUmV0dXJuVHlwZTx0eXBlb2YgYnVpbGQ+IHtcbiAgICBjb25zdCBjdHggPSBhc0NvbnRleHQocGFnZXNJMThuKTtcbiAgICBjdHguY29uZmlnLmkxOG4gPSBudWxsO1xuICAgIGN0eC5jb25maWcuYmFzZVBhdGggPSBiYXNlUGF0aDtcbiAgICBjdHgub3V0cHV0cy5zdGF0aWNGaWxlcyA9IFtdO1xuICAgIGN0eC5vdXRwdXRzLnByZXJlbmRlcnMgPSBbXTtcbiAgICBjb25zdCBwYWdlID0gY3R4Lm91dHB1dHMucGFnZXMuZmluZCgobykgPT4gby5wYXRobmFtZSA9PT0gXCIvc3NyXCIpITtcbiAgICBjdHgub3V0cHV0cy5wYWdlcyA9XG4gICAgICBraW5kID09PSBcImludm9jYWJsZVwiXG4gICAgICAgID8gW3sgLi4ucGFnZSwgaWQ6IFwiL2luZGV4XCIsIHBhdGhuYW1lOiBgJHtiYXNlUGF0aH0vaW5kZXhgIH1dXG4gICAgICAgIDogW107XG4gICAgaWYgKGtpbmQgPT09IFwic3RhdGljXCIpIHtcbiAgICAgIGN0eC5vdXRwdXRzLnN0YXRpY0ZpbGVzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6IFwiL1wiLFxuICAgICAgICAgIHBhdGhuYW1lOiBgJHtiYXNlUGF0aH0vaW5kZXhgLFxuICAgICAgICAgIHR5cGU6IFwiU1RBVElDX0ZJTEVcIixcbiAgICAgICAgICBmaWxlUGF0aDogXCIvcmVwby9wYWdlcy1pMThuLy5uZXh0L3NlcnZlci9wYWdlcy9pbmRleC5odG1sXCIsXG4gICAgICAgIH0sXG4gICAgICBdIGFzIHR5cGVvZiBjdHgub3V0cHV0cy5zdGF0aWNGaWxlcztcbiAgICB9XG4gICAgcmV0dXJuIGJ1aWxkKGN0eCk7XG4gIH1cblxuICBpdChcInJvdXRlcyBhIGZ1bGx5LXN0YXRpYyBQYWdlcyBSb3V0ZXIgaG9tZSBwYWdlIGF0IGAvYCwgbm90IGAvaW5kZXhgXCIsICgpID0+IHtcbiAgICBjb25zdCB7IG1hbmlmZXN0IH0gPSB3aXRoSG9tZVBhZ2UoXCJcIiwgXCJzdGF0aWNcIik7XG4gICAgY29uc3QgaHRtbCA9IFwicGFnZXMtaTE4bi8ubmV4dC9zZXJ2ZXIvcGFnZXMvaW5kZXguaHRtbFwiO1xuXG4gICAgZXhwZWN0KG1hbmlmZXN0LnN0YXRpY0ZpbGVzW1wiL1wiXSkudG9CZShodG1sKTtcbiAgICBleHBlY3QobWFuaWZlc3QucGF0aG5hbWVzKS50b0NvbnRhaW4oXCIvXCIpO1xuICAgIC8vIEtlcHQgYXMgd2VsbCBhcyBgL2A6IG5leHQncyBtaW5pbWFsIG1vZGUgcmV3cml0ZXMgYC9pbmRleGAgdG8gYC9gIGJlZm9yZVxuICAgIC8vIG1hdGNoaW5nLCBzbyBpdCBhbnN3ZXJzIHRoZXJlIHRvby5cbiAgICBleHBlY3QobWFuaWZlc3Quc3RhdGljRmlsZXNbXCIvaW5kZXhcIl0pLnRvQmUoaHRtbCk7XG4gIH0pO1xuXG4gIGl0KFwicm91dGVzIGFuIFNTRyBvciBTU1IgaG9tZSBwYWdlJ3MgZW50cnlwb2ludCBhdCBgL2AgYXMgd2VsbFwiLCAoKSA9PiB7XG4gICAgY29uc3QgeyBtYW5pZmVzdCB9ID0gd2l0aEhvbWVQYWdlKFwiXCIsIFwiaW52b2NhYmxlXCIpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9cIl0pLnRvRXF1YWwobWFuaWZlc3QuZW50cnlwb2ludHNbXCIvaW5kZXhcIl0pO1xuICAgIGV4cGVjdChtYW5pZmVzdC5wYXRobmFtZXMpLnRvQ29udGFpbihcIi9cIik7XG4gICAgLy8gVGhlIG91dHB1dCdzIG93biBgaWRgIGlzIHdoYXQgbmV4dCByZXBvcnRlZCwgYW5kIG9ubHkgbmFtZXMgdGhlIGVudHJ5cG9pbnRcbiAgICAvLyBpbiBkaWFnbm9zdGljcyBhbmQgZ3JvdXAgb3duZXJzaGlwIC0gaXQgaXMgbm90IGEga2V5IGludG8gYW55dGhpbmcuXG4gICAgZXhwZWN0KG1hbmlmZXN0LmVudHJ5cG9pbnRzW1wiL1wiXS5pZCkudG9CZShcIi9pbmRleFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJyb3V0ZXMgdGhhdCBob21lIHBhZ2UgdW5kZXIgYmFzZVBhdGggYXQgdGhlIGJhc2VQYXRoIGl0c2VsZlwiLCAoKSA9PiB7XG4gICAgLy8gYC9wcm9kYCwgbm90IGAvcHJvZC9gIOKAlCB3aGljaCBpcyBob3cgdGhlIEFwcCBSb3V0ZXIgZml4dHVyZSByZXBvcnRzIGl0cyBvd25cbiAgICAvLyBob21lIHBhZ2UuXG4gICAgY29uc3QgeyBtYW5pZmVzdCB9ID0gd2l0aEhvbWVQYWdlKFwiL3Byb2RcIiwgXCJzdGF0aWNcIik7XG4gICAgZXhwZWN0KE9iamVjdC5rZXlzKG1hbmlmZXN0LnN0YXRpY0ZpbGVzKSkudG9FcXVhbChbXCIvcHJvZFwiLCBcIi9wcm9kL2luZGV4XCJdKTtcbiAgfSk7XG5cbiAgaXQoXCJsZWF2ZXMgYW4gQXBwIFJvdXRlciBgL2luZGV4YCByb3V0ZSBhdCBgL2luZGV4YFwiLCAoKSA9PiB7XG4gICAgLy8gYGFwcC9pbmRleC9wYWdlLnRzeGAgaXMgYSByZWFsIHJvdXRlLiBPbmx5IHRoZSBQYWdlcyBSb3V0ZXIgcmVwb3J0cyBpdHNcbiAgICAvLyBob21lIHBhZ2UgYXMgYC9pbmRleGAuXG4gICAgY29uc3QgY3R4ID0gYXNDb250ZXh0KGFwcFBsYXlncm91bmQpO1xuICAgIGNvbnN0IGhvbWUgPSBjdHgub3V0cHV0cy5hcHBQYWdlcy5maW5kKChvKSA9PiBvLnBhdGhuYW1lID09PSBcIi9cIikhO1xuICAgIGNvbnN0IGluZGV4RmlsZSA9IGhvbWUuZmlsZVBhdGgucmVwbGFjZSgvcGFnZVxcLmpzJC8sIFwiaW5kZXgvcGFnZS5qc1wiKTtcbiAgICBjdHgub3V0cHV0cy5hcHBQYWdlcy5wdXNoKHtcbiAgICAgIC4uLmhvbWUsXG4gICAgICBpZDogXCIvaW5kZXhcIixcbiAgICAgIHBhdGhuYW1lOiBcIi9pbmRleFwiLFxuICAgICAgZmlsZVBhdGg6IGluZGV4RmlsZSxcbiAgICB9KTtcbiAgICBjb25zdCB7IG1hbmlmZXN0IH0gPSBidWlsZChjdHgpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9cIl0uZmlsZVBhdGgpLm5vdC50b0JlKFxuICAgICAgbWFuaWZlc3QuZW50cnlwb2ludHNbXCIvaW5kZXhcIl0uZmlsZVBhdGgsXG4gICAgKTtcbiAgICBleHBlY3QobWFuaWZlc3QuZW50cnlwb2ludHNbXCIvaW5kZXhcIl0uZmlsZVBhdGgpLnRvTWF0Y2goL2luZGV4XFwvcGFnZVxcLmpzJC8pO1xuICB9KTtcblxuICBpdChcInJlY29yZHMgbWlkZGxld2FyZSB3aXRob3V0IGR1cGxpY2F0aW5nIGl0cyBtYXRjaGVyc1wiLCAoKSA9PiB7XG4gICAgY29uc3Qge1xuICAgICAgbWFuaWZlc3QsXG4gICAgICBncm91cHM6IFt7IHN0YWdpbmcgfV0sXG4gICAgfSA9IGJ1aWxkKGFzQ29udGV4dChhcHBQbGF5Z3JvdW5kKSk7XG4gICAgZXhwZWN0KG1hbmlmZXN0Lm1pZGRsZXdhcmUpLm5vdC50b0JlTnVsbCgpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5taWRkbGV3YXJlIS5maWxlUGF0aCkudG9NYXRjaCgvXlteL10vKTtcbiAgICBleHBlY3Qoc3RhZ2luZy5oYXMobWFuaWZlc3QubWlkZGxld2FyZSEuZmlsZVBhdGgpKS50b0JlKHRydWUpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5taWRkbGV3YXJlKS5ub3QudG9IYXZlUHJvcGVydHkoXCJtYXRjaGVyc1wiKTtcblxuICAgIGNvbnN0IHsgbWFuaWZlc3Q6IG5vTWlkZGxld2FyZSB9ID0gYnVpbGQoYXNDb250ZXh0KHBhZ2VzSTE4bikpO1xuICAgIGV4cGVjdChub01pZGRsZXdhcmUubWlkZGxld2FyZSkudG9CZU51bGwoKTtcbiAgfSk7XG5cbiAgaXQoXCJtYXBzIGEgUGFnZXMgUm91dGVyIGRhdGEtcm91dGUgdGVtcGxhdGUgdG8gaXRzIG93bmluZyByb3V0ZVwiLCAoKSA9PiB7XG4gICAgLy8gYC9fbmV4dC9kYXRhLzxidWlsZElkPi88bG9jYWxlPi9ibG9nL1tzbHVnXS5qc29uYCBleGlzdHMgb25seSBhcyBhXG4gICAgLy8gcHJlcmVuZGVyLiBXaXRob3V0IGl0LCB0aGUgSVNSIGRhdGEgVVJMcyBgbmV4dCBzdGFydGAgc2VydmVzIHdvdWxkIDQwNC5cbiAgICBjb25zdCB7IG1hbmlmZXN0IH0gPSBidWlsZChhc0NvbnRleHQocGFnZXNJMThuKSk7XG4gICAgY29uc3QgZGF0YVRlbXBsYXRlID0gYC9fbmV4dC9kYXRhLyR7bWFuaWZlc3QuYnVpbGRJZH0vZnIvYmxvZy9bc2x1Z10uanNvbmA7XG4gICAgZXhwZWN0KG1hbmlmZXN0LmVudHJ5cG9pbnRzW2RhdGFUZW1wbGF0ZV0pLnRvRXF1YWwoe1xuICAgICAgaWQ6IGRhdGFUZW1wbGF0ZSxcbiAgICAgIGZpbGVQYXRoOiBtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9mci9ibG9nL1tzbHVnXVwiXS5maWxlUGF0aCxcbiAgICAgIHR5cGU6IFwicGFnZVwiLFxuICAgIH0pO1xuICAgIGV4cGVjdChtYW5pZmVzdC5wYXRobmFtZXMpLnRvQ29udGFpbihkYXRhVGVtcGxhdGUpO1xuICB9KTtcblxuICBpdChcInJlZ2lzdGVycyBhIHN0YXRpYyBnZXRTdGF0aWNQcm9wcyBwYWdlJ3MgZGF0YSByb3V0ZSwgd2hpY2ggbm8gcnVsZSByZWFjaGVzXCIsICgpID0+IHtcbiAgICAvLyBgdGVzdC9lMmUvbm8tcGFnZS1wcm9wc2A6IGAvX25leHQvZGF0YS88YnVpbGRJZD4vZ3NwLmpzb25gIDQwNCdkIHdoaWxlXG4gICAgLy8gYG5leHQgc3RhcnRgIHNlcnZlcyBpdCAyMDAsIHNvIGV2ZXJ5IGNsaWVudC1zaWRlIG5hdmlnYXRpb24gaW50byB0aGUgcGFnZVxuICAgIC8vIGZlbGwgYmFjayB0byBhIGZ1bGwgcGFnZSBsb2FkLiBgbmV4dCBidWlsZGAgZW1pdHMgYSBgZHluYW1pY1JvdXRlc2AgcnVsZSBmb3JcbiAgICAvLyBhIGRhdGEgcm91dGUgb25seSB3aGVuIHRoZSBwYWdlIGlzIGR5bmFtaWMgb3IgdGhlIGFwcCBoYXMgbWlkZGxld2FyZSwgc29cbiAgICAvLyB3aXRob3V0IG1pZGRsZXdhcmUgYSAqc3RhdGljKiBwYWdlJ3MgZGF0YSByb3V0ZSBhcnJpdmVzIGFzIGEgY29uY3JldGVcbiAgICAvLyBwcmVyZW5kZXIgcGF0aG5hbWUgd2l0aCBub3RoaW5nIHRvIG1hdGNoIGl0LiBSZXByb2R1Y2VkIG9uIGBwYWdlcy1pMThuYCxcbiAgICAvLyB3aG9zZSBjYXB0dXJlZCBwcmVyZW5kZXJzIGFyZSBhbGwgZHluYW1pYywgYnkgcmVuYW1pbmcgb25lLlxuICAgIGNvbnN0IGN0eCA9IGFzQ29udGV4dChwYWdlc0kxOG4pO1xuICAgIGNvbnN0IGRhdGFSb3V0ZSA9IGAvX25leHQvZGF0YS8ke2N0eC5idWlsZElkfS9lbi1VUy9nc3AuanNvbmA7XG4gICAgY29uc3QgY29uY3JldGUgPSBjdHgub3V0cHV0cy5wcmVyZW5kZXJzLmZpbmQoKGl0KSA9PlxuICAgICAgaXQucGF0aG5hbWUuZW5kc1dpdGgoXCJoZWxsby5qc29uXCIpLFxuICAgICkhO1xuICAgIGNvbmNyZXRlLnBhdGhuYW1lID0gZGF0YVJvdXRlO1xuICAgIGNvbmNyZXRlLmlkID0gZGF0YVJvdXRlO1xuICAgIGNvbnN0IHsgbWFuaWZlc3QgfSA9IGJ1aWxkKGN0eCk7XG4gICAgZXhwZWN0KG1hbmlmZXN0LmVudHJ5cG9pbnRzW2RhdGFSb3V0ZV0pLnRvRXF1YWwoe1xuICAgICAgaWQ6IGRhdGFSb3V0ZSxcbiAgICAgIGZpbGVQYXRoOiBtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9lbi1VUy9ibG9nL1tzbHVnXVwiXS5maWxlUGF0aCxcbiAgICAgIHR5cGU6IFwicGFnZVwiLFxuICAgIH0pO1xuXG4gICAgLy8gQW5kIHRoZSBkeW5hbWljIHBhZ2UncyBvd24gY29uY3JldGUgZGF0YSBwYXRobmFtZSBzdGF5cyBvdXQ6IHRoZSB1bmdhdGVkXG4gICAgLy8gYOKApi9ibG9nL1tzbHVnXS5qc29uYCBydWxlIGFscmVhZHkgcmVhY2hlcyBpdCwgYW5kIHRoYXQgcnVsZSBpcyB3aGVyZSB0aGVcbiAgICAvLyBgbnh0UHNsdWdgIHBhcmFtIGNvbWVzIGZyb20g4oCUIHJlc29sdmluZyB0aGUgcmVxdWVzdCB0byBpdHNlbGYgd291bGQgZHJvcCBpdC5cbiAgICBjb25zdCB7IG1hbmlmZXN0OiBjYXB0dXJlZCB9ID0gYnVpbGQoYXNDb250ZXh0KHBhZ2VzSTE4bikpO1xuICAgIGV4cGVjdChcbiAgICAgIGNhcHR1cmVkLmVudHJ5cG9pbnRzW1xuICAgICAgICBgL19uZXh0L2RhdGEvJHtjYXB0dXJlZC5idWlsZElkfS9lbi1VUy9ibG9nL2hlbGxvLmpzb25gXG4gICAgICBdLFxuICAgICkudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcblxuICBpdChcImxlYXZlcyBhbiBBcHAgUm91dGVyIGZhbGxiYWNrIHRlbXBsYXRlIG9uIGl0cyBvd24gZW50cnlwb2ludFwiLCAoKSA9PiB7XG4gICAgLy8gYC9pc3IvW2lkXWAgaXMgYSBwcmVyZW5kZXIgKmFuZCogYW4gYXBwUGFnZXMgb3V0cHV0LiBUaGUgb3V0cHV0IHdpbnMsIHNvXG4gICAgLy8gYGlkYCBzdGF5cyB0aGUgcm91dGUncyBvd24gcmF0aGVyIHRoYW4gYmVpbmcgcmV3cml0dGVuLlxuICAgIGNvbnN0IHsgbWFuaWZlc3QgfSA9IGJ1aWxkKGFzQ29udGV4dChhcHBQbGF5Z3JvdW5kKSk7XG4gICAgZXhwZWN0KG1hbmlmZXN0LmVudHJ5cG9pbnRzW1wiL2lzci9baWRdXCJdLmlkKS50b0JlKFwiL2lzci9baWRdXCIpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9pc3IvW2lkXS5yc2NcIl0pLnRvQmVEZWZpbmVkKCk7XG4gIH0pO1xuXG4gIGl0KFwiYWRkcyBhIGNvbmNyZXRlIHByZXJlbmRlciBwYXRobmFtZSB3aGVuIG9ubHkgYSBnYXRlZCBydWxlIG1hdGNoZXMgaXRcIiwgKCkgPT4ge1xuICAgIC8vIFdoYXQgYSByb290LXBhcmFtcyBhcHAgcHJvZHVjZXM6IGBhcHAvW2xvY2FsZV0vcGFnZS50c3hgIHdpdGhcbiAgICAvLyBgZ2VuZXJhdGVTdGF0aWNQYXJhbXMoKWAgYW5kIG5vIGBhcHAvbGF5b3V0LnRzeGAuIFRoZSBwYXJhbXMgY2FuIG5ldmVyIGJlXG4gICAgLy8gZmlsbGVkIGF0IHJlcXVlc3QgdGltZSwgc28gYG5leHQgYnVpbGRgIGVtaXRzIHRoZSBgZHluYW1pY1JvdXRlc2AgcnVsZSB3aXRoIGFcbiAgICAvLyBkcmFmdC1tb2RlIGBoYXNgIGFuZCBleHBlY3RzIHRoZSBwbGF0Zm9ybSB0byBzZXJ2ZSBgL2VuYCBmcm9tIHRoZSBwcmVyZW5kZXIuXG4gICAgLy8gTWVhc3VyZWQgYWdhaW5zdCBgdGVzdC9lMmUvYXBwLWRpci9wYXJhbGxlbC1yb3V0ZXMtcm9vdC1wYXJhbS1keW5hbWljLWNoaWxkYCxcbiAgICAvLyB3aGVyZSBldmVyeSBVUkwgb2YgdGhlIGFwcCA0MDQnZC4gUmVwcm9kdWNlZCBoZXJlIGJ5IGdhdGluZ1xuICAgIC8vIGBhcHAtcGxheWdyb3VuZGAncyBgL2lzci9baWRdYCBydWxlcywgd2hpY2ggbm8gY29tbWl0dGVkIGNhcHR1cmUgZG9lcy5cbiAgICBjb25zdCBjdHggPSBhc0NvbnRleHQoYXBwUGxheWdyb3VuZCk7XG4gICAgZm9yIChjb25zdCByb3V0ZSBvZiBjdHgucm91dGluZy5keW5hbWljUm91dGVzKSB7XG4gICAgICBpZiAocm91dGUuc291cmNlUmVnZXguaW5jbHVkZXMoXCJpc3JcIikpIHtcbiAgICAgICAgcm91dGUuaGFzID0gW1xuICAgICAgICAgIHsgdHlwZTogXCJjb29raWVcIiwga2V5OiBcIl9fcHJlcmVuZGVyX2J5cGFzc1wiLCB2YWx1ZTogXCJzZWNyZXRcIiB9LFxuICAgICAgICBdO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB7IG1hbmlmZXN0IH0gPSBidWlsZChjdHgpO1xuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9pc3IvMVwiXSkudG9FcXVhbCh7XG4gICAgICBpZDogXCIvaXNyLzFcIixcbiAgICAgIGZpbGVQYXRoOiBtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9pc3IvW2lkXVwiXS5maWxlUGF0aCxcbiAgICAgIHR5cGU6IFwiYXBwLXBhZ2VcIixcbiAgICB9KTtcbiAgICAvLyBUaGUgUlNDIGFuZCBzZWdtZW50LXByZWZldGNoIHZhcmlhbnRzIHRvbzogdGhleSBhcmUgdGhlIFVSTHMgYSBjbGllbnQtc2lkZVxuICAgIC8vIG5hdmlnYXRpb24gYXNrcyBmb3IsIHNvIHdpdGhvdXQgdGhlbSB0aGUgYXBwIHJlbmRlcnMgYW5kIG5ldmVyIGh5ZHJhdGVzLlxuICAgIGV4cGVjdChtYW5pZmVzdC5lbnRyeXBvaW50c1tcIi9pc3IvMS5yc2NcIl0pLnRvQmVEZWZpbmVkKCk7XG4gICAgZXhwZWN0KFxuICAgICAgbWFuaWZlc3QuZW50cnlwb2ludHNbXCIvaXNyLzEuc2VnbWVudHMvaXNyLyRkJGlkL19fUEFHRV9fLnNlZ21lbnQucnNjXCJdLFxuICAgICkudG9CZURlZmluZWQoKTtcbiAgICAvLyBVbm11dGF0ZWQsIHRoZSBzYW1lIHBhdGhuYW1lcyBzdGF5IG91dDogdGhlIHVuZ2F0ZWQgcnVsZSBhbHJlYWR5IHJlYWNoZXNcbiAgICAvLyBgL2lzci9baWRdYCwgd2hpY2ggaXMgd2hlcmUgdGhlIGBueHRQaWRgIHBhcmFtIGNvbWVzIGZyb20uXG4gICAgY29uc3QgeyBtYW5pZmVzdDogdW5nYXRlZCB9ID0gYnVpbGQoYXNDb250ZXh0KGFwcFBsYXlncm91bmQpKTtcbiAgICBleHBlY3QodW5nYXRlZC5lbnRyeXBvaW50c1tcIi9pc3IvMVwiXSkudG9CZVVuZGVmaW5lZCgpO1xuICAgIGV4cGVjdCh1bmdhdGVkLmVudHJ5cG9pbnRzW1wiL2lzci8xLnJzY1wiXSkudG9CZVVuZGVmaW5lZCgpO1xuICAgIC8vIEFuZCBhIHBhdGhuYW1lIG5vIHJ1bGUgbWF0Y2hlcyBhdCBhbGwgc3RheXMgb3V0IGVpdGhlciB3YXk6IGByZXNvbHZlUm91dGVzYFxuICAgIC8vIG5ldmVyIHJlc29sdmVzIGEgc3RhdGljIHJvdXRlJ3Mgc2VnbWVudCBvdXRwdXRzLCBzbyBsaXN0aW5nIHRoZW0gaXMgd2VpZ2h0LlxuICAgIGV4cGVjdChcbiAgICAgIG1hbmlmZXN0LmVudHJ5cG9pbnRzW1wiL2luZGV4LnNlZ21lbnRzL190cmVlLnNlZ21lbnQucnNjXCJdLFxuICAgICkudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcblxuICBpdChcImxlYXZlcyBwdWJsaWMvIG91dCBvZiB0aGUgbWFuaWZlc3QgYW5kIHRoZSBzdGFnaW5nIHBsYW5cIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIFRoZSBjb250YWluZXIgcnVudGltZSBsaXN0cyBgcHVibGljL2Agb2ZmIGRpc2sgYXQgY29sZCBzdGFydFxuICAgIC8vIChgcmVhZFB1YmxpY0ZpbGVzYCksIGJlY2F1c2Ugb25seSB0aGUgZGlzayBoYXMgd2hhdCBhIGBwb3N0YnVpbGRgIHdyb3RlXG4gICAgLy8gaW50byBpdCBhZnRlciB0aGlzIGhvb2sgcmFuOyBhbmQgdGhlIExhbWJkYSB0eXBlcyBuZXZlciBzZXJ2ZSBpdC5cbiAgICBjb25zdCByZXBvUm9vdCA9IGF3YWl0IG1rZHRlbXAoam9pbih0bXBkaXIoKSwgXCJjZGstbmV4dGpzLXB1YmxpYy1cIikpO1xuICAgIC8vIEV2ZXJ5IHBhdGggaW4gdGhlIGZpeHR1cmUsIHJlYmFzZWQgZnJvbSBgL3JlcG9gIG9udG8gYSByZWFsIGRpcmVjdG9yeS5cbiAgICBjb25zdCBjdHggPSBhc0NvbnRleHQoXG4gICAgICBKU09OLnBhcnNlKFxuICAgICAgICBKU09OLnN0cmluZ2lmeShhcHBQbGF5Z3JvdW5kQmFzZVBhdGgpLnJlcGxhY2VBbGwoXG4gICAgICAgICAgJ1wiL3JlcG8nLFxuICAgICAgICAgIGBcIiR7cmVwb1Jvb3R9YCxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgKTtcbiAgICBhd2FpdCBta2Rpcihqb2luKGN0eC5wcm9qZWN0RGlyLCBcInB1YmxpY1wiKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4oY3R4LnByb2plY3REaXIsIFwicHVibGljXCIsIFwidGVzdC50eHRcIiksIFwiaGVsbG9cIik7XG5cbiAgICBjb25zdCB7XG4gICAgICBtYW5pZmVzdCxcbiAgICAgIGdyb3VwczogW3sgc3RhZ2luZyB9XSxcbiAgICB9ID0gYnVpbGQoY3R4KTtcbiAgICBleHBlY3QoXG4gICAgICBPYmplY3QudmFsdWVzKG1hbmlmZXN0LnN0YXRpY0ZpbGVzKS5maWx0ZXIoKGtleSkgPT5cbiAgICAgICAga2V5LmluY2x1ZGVzKFwiL3B1YmxpYy9cIiksXG4gICAgICApLFxuICAgICkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0KG1hbmlmZXN0LnBhdGhuYW1lcykubm90LnRvQ29udGFpbihcIi9wcm9kL3Rlc3QudHh0XCIpO1xuICAgIGV4cGVjdChcbiAgICAgIFsuLi5zdGFnaW5nLmtleXMoKV0uZmlsdGVyKChrZXkpID0+IGtleS5pbmNsdWRlcyhcIi9wdWJsaWMvXCIpKSxcbiAgICApLnRvRXF1YWwoW10pO1xuICB9KTtcblxuICBpdChcIndhcm5zIGluc3RlYWQgb2YgdGhyb3dpbmcgd2hlbiBhIHRlbXBsYXRlIGhhcyBubyBvd25pbmcgcm91dGVcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHdhcm4gPSBqZXN0LnNweU9uKGNvbnNvbGUsIFwid2FyblwiKS5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4ge30pO1xuICAgIGNvbnN0IGN0eCA9IGFzQ29udGV4dChwYWdlc0kxOG4pO1xuICAgIGN0eC5vdXRwdXRzLnByZXJlbmRlcnNbMF0ucm91dGUgPSBcIi9nb25lL1tzbHVnXVwiO1xuICAgIGN0eC5vdXRwdXRzLnByZXJlbmRlcnNbMF0ucGF0aG5hbWUgPSBcIi9nb25lL1tzbHVnXVwiO1xuICAgIGNvbnN0IHsgbWFuaWZlc3QgfSA9IGJ1aWxkKGN0eCk7XG4gICAgZXhwZWN0KG1hbmlmZXN0LmVudHJ5cG9pbnRzW1wiL2dvbmUvW3NsdWddXCJdKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KFxuICAgICAgd2Fybi5tb2NrLmNhbGxzXG4gICAgICAgIC5tYXAoKGNhbGwpID0+IFN0cmluZyhjYWxsWzBdKSlcbiAgICAgICAgLmZpbHRlcigobWVzc2FnZSkgPT4gbWVzc2FnZS5pbmNsdWRlcyhcIndpbGwgNDA0XCIpKSxcbiAgICApLnRvRXF1YWwoW1xuICAgICAgZXhwZWN0LnN0cmluZ0NvbnRhaW5pbmcoJy9nb25lL1tzbHVnXSAocm91dGU6IFwiL2dvbmUvW3NsdWddXCIpJyksXG4gICAgXSk7XG4gIH0pO1xuXG4gIGl0KFwid2FybnMgb25jZSBwZXIgdW5zdXBwb3J0ZWQgcm91dGUgY29uZmlnIGtleVwiLCAoKSA9PiB7XG4gICAgY29uc3Qgd2FybiA9IGplc3Quc3B5T24oY29uc29sZSwgXCJ3YXJuXCIpLm1vY2tJbXBsZW1lbnRhdGlvbigoKSA9PiB7fSk7XG4gICAgYnVpbGQoYXNDb250ZXh0KHBhZ2VzSTE4bikpO1xuICAgIGNvbnN0IG1lc3NhZ2VzID0gd2Fybi5tb2NrLmNhbGxzLm1hcCgoY2FsbCkgPT4gU3RyaW5nKGNhbGxbMF0pKTtcbiAgICBleHBlY3QobWVzc2FnZXMuZmlsdGVyKChtKSA9PiBtLmluY2x1ZGVzKFwiYG1heER1cmF0aW9uYFwiKSkpLnRvSGF2ZUxlbmd0aCgxKTtcbiAgICBleHBlY3QobWVzc2FnZXNbMF0pLnRvQ29udGFpbihcInNzclwiKTtcbiAgICBleHBlY3QobWVzc2FnZXNbMF0pLnRvQ29udGFpbihcIm92ZXJyaWRlc1wiKTtcbiAgICBleHBlY3QobWVzc2FnZXMuc29tZSgobSkgPT4gbS5pbmNsdWRlcyhcImBwcmVmZXJyZWRSZWdpb25gXCIpKSkudG9CZShmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KFwidGhyb3dzIG9uIGFuIGVkZ2UtcnVudGltZSBvdXRwdXRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGN0eCA9IGFzQ29udGV4dChhcHBQbGF5Z3JvdW5kKTtcbiAgICBjdHgub3V0cHV0cy5hcHBSb3V0ZXNbMF0ucnVudGltZSA9IFwiZWRnZVwiO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZChjdHgpKS50b1Rocm93KFxuICAgICAgL2Nhbm5vdCBkZXBsb3kgcm91dGVzIGJ1aWx0IGZvciB0aGUgZWRnZSBydW50aW1lLyxcbiAgICApO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZChjdHgpKS50b1Rocm93KGN0eC5vdXRwdXRzLmFwcFJvdXRlc1swXS5zb3VyY2VQYWdlKTtcbiAgfSk7XG5cbiAgaXQoXCJibGFtZXMgbWlkZGxld2FyZSwgbm90IGAvYCwgZm9yIGVkZ2UtcnVudGltZSBtaWRkbGV3YXJlXCIsICgpID0+IHtcbiAgICBjb25zdCBjdHggPSBhc0NvbnRleHQoYXBwUGxheWdyb3VuZCk7XG4gICAgY29uc3QgbWlkZGxld2FyZSA9IGN0eC5vdXRwdXRzLm1pZGRsZXdhcmU7XG4gICAgaWYgKCFtaWRkbGV3YXJlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaXh0dXJlIGhhcyBubyBtaWRkbGV3YXJlIG91dHB1dFwiKTtcbiAgICB9XG4gICAgLy8gV2hhdCBhIGxlZ2FjeSBgbWlkZGxld2FyZS50c2AgYnVpbGRzIHRvLiBJdHMgYHNvdXJjZVBhZ2VgIGlzIGAvYCwgc28gdGhlXG4gICAgLy8gcmVncmVzc2lvbiBndWFyZGVkIGhlcmUgaXMgdGhlIG1lc3NhZ2UgdGVsbGluZyBhbiBhdXRob3IgdG8gZWRpdCB0aGUgaG9tZVxuICAgIC8vIHBhZ2UuXG4gICAgbWlkZGxld2FyZS5ydW50aW1lID0gXCJlZGdlXCI7XG5cbiAgICBleHBlY3QoKCkgPT4gYnVpbGQoY3R4KSkudG9UaHJvdyhcbiAgICAgIC9jYW5ub3QgZGVwbG95IG1pZGRsZXdhcmUgYnVpbHQgZm9yIHRoZSBlZGdlIHJ1bnRpbWUvLFxuICAgICk7XG4gICAgZXhwZWN0KCgpID0+IGJ1aWxkKGN0eCkpLnRvVGhyb3cobWlkZGxld2FyZS5maWxlUGF0aCk7XG4gICAgLy8gQm90aCB3YXlzIG91dDogYG1pZGRsZXdhcmUudHNgIG9ubHkgZGVmYXVsdHMgdG8gZWRnZS5cbiAgICBleHBlY3QoKCkgPT4gYnVpbGQoY3R4KSkudG9UaHJvdygvcnVudGltZTogXCJub2RlanNcIi8pO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZChjdHgpKS50b1Rocm93KC9wcm94eVxcLnRzLyk7XG4gICAgZXhwZWN0KCgpID0+IGJ1aWxkKGN0eCkpLm5vdC50b1Rocm93KC9lZGdlLW9ubHkvKTtcbiAgICBleHBlY3QoKCkgPT4gYnVpbGQoY3R4KSkubm90LnRvVGhyb3coXG4gICAgICAvY2Fubm90IGRlcGxveSByb3V0ZXMgYnVpbHQgZm9yIHRoZSBlZGdlIHJ1bnRpbWUvLFxuICAgICk7XG4gIH0pO1xuXG4gIGl0KFwidGhyb3dzIHdoZW4gdHdvIG91dHB1dHMgbWFwIG9uZSBrZXkgdG8gZGlmZmVyZW50IGNvbnRlbnRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGN0eCA9IGFzQ29udGV4dChhcHBQbGF5Z3JvdW5kKTtcbiAgICBjb25zdCBbZmlyc3QsIHNlY29uZF0gPSBjdHgub3V0cHV0cy5hcHBQYWdlcztcbiAgICBjb25zdCBrZXkgPSBPYmplY3Qua2V5cyhmaXJzdC5hc3NldHMpWzBdO1xuICAgIGZpcnN0LmFzc2V0c0hhc2hlc1trZXldID0gXCJoYXNoLWFcIjtcbiAgICBzZWNvbmQuYXNzZXRzW2tleV0gPSBmaXJzdC5hc3NldHNba2V5XTtcbiAgICBzZWNvbmQuYXNzZXRzSGFzaGVzW2tleV0gPSBcImhhc2gtYlwiO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZChjdHgpKS50b1Rocm93KC9tYXAgXCJbXlwiXStcIiB0byBkaWZmZXJlbnQgY29udGVudC8pO1xuICB9KTtcblxuICBpdChcInRocm93cyBvbiBhbiBhc3NldCBrZXkgb3V0c2lkZSB0aGUgZGVwbG95bWVudCByb290XCIsICgpID0+IHtcbiAgICBjb25zdCBjdHggPSBhc0NvbnRleHQoYXBwUGxheWdyb3VuZCk7XG4gICAgY3R4Lm91dHB1dHMuYXBwUGFnZXNbMF0uYXNzZXRzW1wiLi4vZXNjYXBlLmpzXCJdID0gXCIvZWxzZXdoZXJlL2VzY2FwZS5qc1wiO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZChjdHgpKS50b1Rocm93KC9vdXRzaWRlIHRoZSBkZXBsb3ltZW50IHJvb3QvKTtcbiAgfSk7XG5cbiAgaXQoXCJ0aHJvd3Mgb24gYW4gYXNzZXQga2V5IHNoYWRvd2luZyB0aGUgcmVzZXJ2ZWQgcnVudGltZSBkaXJlY3RvcnlcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGN0eCA9IGFzQ29udGV4dChhcHBQbGF5Z3JvdW5kKTtcbiAgICBjdHgub3V0cHV0cy5hcHBQYWdlc1swXS5hc3NldHNbYCR7UlVOVElNRV9ESVJfTkFNRX0vbGFtYmRhLm1qc2BdID1cbiAgICAgIFwiL3JlcG8vd2hhdGV2ZXIubWpzXCI7XG4gICAgZXhwZWN0KCgpID0+IGJ1aWxkKGN0eCkpLnRvVGhyb3coXG4gICAgICBuZXcgUmVnRXhwKGBcIiR7UlVOVElNRV9ESVJfTkFNRX0vXCIgaXMgcmVzZXJ2ZWRgKSxcbiAgICApO1xuICB9KTtcblxuICBpdChcInRocm93cyB3aGVuIHR3byBvdXRwdXRzIGNsYWltIG9uZSBwYXRobmFtZSBmcm9tIGRpZmZlcmVudCBmaWxlc1wiLCAoKSA9PiB7XG4gICAgY29uc3QgY3R4ID0gYXNDb250ZXh0KGFwcFBsYXlncm91bmQpO1xuICAgIGN0eC5vdXRwdXRzLmFwcFJvdXRlc1swXS5wYXRobmFtZSA9IGN0eC5vdXRwdXRzLmFwcFBhZ2VzWzBdLnBhdGhuYW1lO1xuICAgIGV4cGVjdCgoKSA9PiBidWlsZChjdHgpKS50b1Rocm93KC9jbGFpbSB0aGUgcGF0aG5hbWUgXCJbXlwiXStcIi8pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcIndyaXRlQnVpbGRPdXRwdXRzXCIsICgpID0+IHtcbiAgLyoqXG4gICAqIEJ1aWxkcyBhIHRocm93YXdheSByZXBvIG9uIGRpc2sgc28gc3RhZ2luZyBjYW4gYmUgZXhlcmNpc2VkIGZvciByZWFsOlxuICAgKiBmaXh0dXJlIHNvdXJjZXMgYXJlIGAvcmVwb2AgcGxhY2Vob2xkZXJzIGFuZCBjYW5ub3QgYmUgY29waWVkLlxuICAgKi9cbiAgLyoqXG4gICAqIEEgYG5leHRgIGluc3RhbGwganVzdCByZWFsIGVub3VnaCBmb3Ige0BsaW5rIGFkZFJ1bnRpbWVOZXh0Q2xvc3VyZX06IHRoZVxuICAgKiBtb2R1bGVzIGBzcmMvcnVudGltZS9pbWFnZS50c2AgcmVxdWlyZXMsIG9uZSBmaWxlIG9ubHkgdGhlIHRyYWNlIHJlYWNoZXMsIGFuZFxuICAgKiBhIHN0YW5kLWluIGZvciBuZXh0J3MgdmVuZG9yZWQgYEB2ZXJjZWwvbmZ0YCB0aGF0IHJlcG9ydHMgdGhlbS4gVHJhY2luZyBmb3JcbiAgICogcmVhbCBpcyBuZXh0J3Mgam9iLCBub3Qgb3Vyczsgd2hhdCBpcyB1bmRlciB0ZXN0IGlzIHRoYXQgdGhlIGNsb3N1cmUgaXNcbiAgICogcmVzb2x2ZWQgZnJvbSB0aGUgcHJvamVjdCBkaXIgYW5kIHN0YWdlZCB1bmRlciByZXBvLXJvb3QtcmVsYXRpdmUga2V5cy5cbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxGYWtlTmV4dChcbiAgICByZXBvUm9vdDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHsgcG5wbT86IGJvb2xlYW4gfSA9IHt9LFxuICApIHtcbiAgICAvLyBVbmRlciBwbnBtLCBgbmV4dGAgbGl2ZXMgaW4gdGhlIHZpcnR1YWwgc3RvcmUgYmVoaW5kIGEgbGluaywgYW5kIGl0cyBvd25cbiAgICAvLyBkZXBlbmRlbmNpZXMgYXJlIGxpbmtzIGJlc2lkZSBpdC5cbiAgICBjb25zdCBzdG9yZU1vZHVsZXMgPSBqb2luKFxuICAgICAgcmVwb1Jvb3QsXG4gICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgXCIucG5wbVwiLFxuICAgICAgXCJuZXh0QDEuMC4wXCIsXG4gICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICk7XG4gICAgY29uc3QgbmV4dFJvb3QgPSBvcHRpb25zLnBucG1cbiAgICAgID8gam9pbihzdG9yZU1vZHVsZXMsIFwibmV4dFwiKVxuICAgICAgOiBqb2luKHJlcG9Sb290LCBcIm5vZGVfbW9kdWxlc1wiLCBcIm5leHRcIik7XG4gICAgaWYgKG9wdGlvbnMucG5wbSkge1xuICAgICAgY29uc3QgbmV4dEVudiA9IGpvaW4oXG4gICAgICAgIHJlcG9Sb290LFxuICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICBcIi5wbnBtXCIsXG4gICAgICAgIFwiQG5leHQrZW52QDEuMC4wXCIsXG4gICAgICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgICAgIFwiQG5leHRcIixcbiAgICAgICAgXCJlbnZcIixcbiAgICAgICk7XG4gICAgICBhd2FpdCBta2RpcihuZXh0RW52LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGF3YWl0IHdyaXRlRmlsZShqb2luKG5leHRFbnYsIFwiaW5kZXguanNcIiksIFwiLy8gQG5leHQvZW52XFxuXCIpO1xuICAgICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgICBqb2luKG5leHRFbnYsIFwicGFja2FnZS5qc29uXCIpLFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh7IG5hbWU6IFwiQG5leHQvZW52XCIsIG1haW46IFwiaW5kZXguanNcIiB9KSxcbiAgICAgICk7XG4gICAgICBhd2FpdCBta2Rpcihqb2luKHN0b3JlTW9kdWxlcywgXCJAbmV4dFwiKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCBzeW1saW5rKFxuICAgICAgICBcIi4uLy4uLy4uL0BuZXh0K2VudkAxLjAuMC9ub2RlX21vZHVsZXMvQG5leHQvZW52XCIsXG4gICAgICAgIGpvaW4oc3RvcmVNb2R1bGVzLCBcIkBuZXh0XCIsIFwiZW52XCIpLFxuICAgICAgKTtcbiAgICAgIGF3YWl0IG1rZGlyKG5leHRSb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGF3YWl0IHN5bWxpbmsoXG4gICAgICAgIFwiLnBucG0vbmV4dEAxLjAuMC9ub2RlX21vZHVsZXMvbmV4dFwiLFxuICAgICAgICBqb2luKHJlcG9Sb290LCBcIm5vZGVfbW9kdWxlc1wiLCBcIm5leHRcIiksXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBmaWxlcyA9IFtcbiAgICAgIFwiZGlzdC9zZXJ2ZXIvY29uZmlnLXNoYXJlZC5qc1wiLFxuICAgICAgXCJkaXN0L3NoYXJlZC9saWIvaW1hZ2UtY29uZmlnLmpzXCIsXG4gICAgICBcImRpc3Qvc2VydmVyL2ltYWdlLW9wdGltaXplci5qc1wiLFxuICAgICAgXCJkaXN0L3NlcnZlci9zZXJ2ZS1zdGF0aWMuanNcIixcbiAgICAgIFwiZGlzdC9zZXJ2ZXIvbGliL3JvdXRlci11dGlscy9pbnN0cnVtZW50YXRpb24tZ2xvYmFscy5leHRlcm5hbC5qc1wiLFxuICAgICAgLy8gUmVhY2hlZCBvbmx5IHRocm91Z2ggdGhlIHRyYWNlLCBpLmUuIHRoZSByZWFzb24gdHJhY2luZyBpcyBuZWVkZWQuXG4gICAgICBcImRpc3Qvc2hhcmVkL2xpYi9tYXRjaC1yZW1vdGUtcGF0dGVybi5qc1wiLFxuICAgIF07XG4gICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICBjb25zdCBwYXRoID0gam9pbihuZXh0Um9vdCwgZmlsZSk7XG4gICAgICBhd2FpdCBta2RpcihkaXJuYW1lKHBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGF3YWl0IHdyaXRlRmlsZShwYXRoLCBgLy8gJHtmaWxlfVxcbmApO1xuICAgIH1cbiAgICAvLyBObyBgZXhwb3J0c2AgZmllbGQ6IGBuZXh0L2Rpc3QvKipgIGlzIHJlcXVpcmVkIGJ5IHBhdGguXG4gICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgam9pbihuZXh0Um9vdCwgXCJwYWNrYWdlLmpzb25cIiksXG4gICAgICBKU09OLnN0cmluZ2lmeSh7IG5hbWU6IFwibmV4dFwiLCB2ZXJzaW9uOiBcIjAuMC4wLXRlc3RcIiB9KSxcbiAgICApO1xuXG4gICAgY29uc3QgdHJhY2VyID0gam9pbihuZXh0Um9vdCwgXCJkaXN0XCIsIFwiY29tcGlsZWRcIiwgXCJAdmVyY2VsXCIsIFwibmZ0XCIpO1xuICAgIGF3YWl0IG1rZGlyKHRyYWNlciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgam9pbih0cmFjZXIsIFwicGFja2FnZS5qc29uXCIpLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoeyBuYW1lOiBcIkB2ZXJjZWwvbmZ0XCIsIG1haW46IFwiaW5kZXguanNcIiB9KSxcbiAgICApO1xuICAgIGF3YWl0IHdyaXRlRmlsZShcbiAgICAgIGpvaW4odHJhY2VyLCBcImluZGV4LmpzXCIpLFxuICAgICAgLy8gUmVhbCBuZnQgcmV0dXJucyBwYXRocyByZWxhdGl2ZSB0byBgYmFzZWAsIHdoaWNoIGlzIHRoZSByZXBvIHJvb3QgdGhlXG4gICAgICAvLyBhZGFwdGVyIHBhc3Nlcy5cbiAgICAgIGBjb25zdCBwcmVmaXggPSAke0pTT04uc3RyaW5naWZ5KHJlbGF0aXZlKHJlcG9Sb290LCBuZXh0Um9vdCkuc3BsaXQoc2VwKS5qb2luKFwiL1wiKSl9O1xcbmAgK1xuICAgICAgICBcImNvbnN0IHsgcmVhbHBhdGhTeW5jIH0gPSByZXF1aXJlKCdub2RlOmZzJyk7XFxuXCIgK1xuICAgICAgICBcImNvbnN0IHsgcmVsYXRpdmUgfSA9IHJlcXVpcmUoJ25vZGU6cGF0aCcpO1xcblwiICtcbiAgICAgICAgXCJleHBvcnRzLm5vZGVGaWxlVHJhY2UgPSBhc3luYyAoZW50cmllcywgeyBiYXNlIH0pID0+IHtcXG5cIiArXG4gICAgICAgIC8vIExpa2UgcmVhbCBuZnQsIHRoZSBlbnRyaWVzIHRoZW1zZWx2ZXMgYXJlIGluIHRoZSBsaXN0LlxuICAgICAgICBcIiAgY29uc3QgdHJhY2VkID0gZW50cmllc1xcblwiICtcbiAgICAgICAgXCIgICAgLm1hcCgoZSkgPT4gcmVsYXRpdmUocmVhbHBhdGhTeW5jKGJhc2UpLCBlKSlcXG5cIiArXG4gICAgICAgIFwiICAgIC5maWx0ZXIoKGUpID0+ICFlLnN0YXJ0c1dpdGgoJy4uJykpO1xcblwiICtcbiAgICAgICAgXCIgIGlmICh0cmFjZWQuc29tZSgoZSkgPT4gZS5lbmRzV2l0aCgnaW1hZ2Utb3B0aW1pemVyLmpzJykpKSB7XFxuXCIgK1xuICAgICAgICBcIiAgICB0cmFjZWQucHVzaChgJHtwcmVmaXh9L2Rpc3Qvc2hhcmVkL2xpYi9tYXRjaC1yZW1vdGUtcGF0dGVybi5qc2ApO1xcblwiICtcbiAgICAgICAgXCIgIH1cXG5cIiArXG4gICAgICAgIFwiICByZXR1cm4geyBmaWxlTGlzdDogbmV3IFNldCh0cmFjZWQpIH07XFxuXCIgK1xuICAgICAgICBcIn07XFxuXCIsXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIG1ha2VSZXBvKFxuICAgIG9wdGlvbnM6IHsgd2l0aE5leHQ/OiBib29sZWFuOyBwbnBtTmV4dD86IGJvb2xlYW4gfSA9IHt9LFxuICApIHtcbiAgICBjb25zdCByZXBvUm9vdCA9IGF3YWl0IG1rZHRlbXAoam9pbih0bXBkaXIoKSwgXCJjZGstbmV4dGpzLXN0YWdpbmctXCIpKTtcbiAgICBpZiAob3B0aW9ucy53aXRoTmV4dCB8fCBvcHRpb25zLnBucG1OZXh0KSB7XG4gICAgICBhd2FpdCBpbnN0YWxsRmFrZU5leHQocmVwb1Jvb3QsIHsgcG5wbTogb3B0aW9ucy5wbnBtTmV4dCB9KTtcbiAgICB9XG4gICAgY29uc3QgcHJvamVjdERpciA9IGpvaW4ocmVwb1Jvb3QsIFwiYXBwXCIpO1xuICAgIGNvbnN0IGRpc3REaXIgPSBqb2luKHByb2plY3REaXIsIFwiLm5leHRcIik7XG4gICAgY29uc3QgZW50cnkgPSBqb2luKGRpc3REaXIsIFwic2VydmVyXCIsIFwiYXBwXCIsIFwicGFnZS5qc1wiKTtcbiAgICBjb25zdCBkZXAgPSBqb2luKHByb2plY3REaXIsIFwibm9kZV9tb2R1bGVzXCIsIFwiZGVwXCIpO1xuICAgIGNvbnN0IHN0b3JlID0gam9pbihyZXBvUm9vdCwgXCJzdG9yZVwiLCBcInBrZ1wiKTtcbiAgICAvLyBwbnBtJ3MgdmlydHVhbCBzdG9yZTogb25lIHBhY2thZ2UgcmVhY2hhYmxlIG9ubHkgZnJvbSBpbnNpZGUgaXQsIGFuZCBvbmVcbiAgICAvLyB0aGF0IGFsc28gaGFzIGEgbG9naWNhbCBwYXRoIChgYXBwL25vZGVfbW9kdWxlcy9kZXBgKS5cbiAgICBjb25zdCB2aXJ0dWFsU3RvcmUgPSBqb2luKHJlcG9Sb290LCBcIm5vZGVfbW9kdWxlc1wiLCBcIi5wbnBtXCIpO1xuICAgIGNvbnN0IGhpZGRlbiA9IGpvaW4oXG4gICAgICB2aXJ0dWFsU3RvcmUsXG4gICAgICBcImhlbHBlcnNAMS4wLjBcIixcbiAgICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgICBcIkBzY29wZVwiLFxuICAgICAgXCJoZWxwZXJzXCIsXG4gICAgKTtcbiAgICBjb25zdCBkZXBJblN0b3JlID0gam9pbih2aXJ0dWFsU3RvcmUsIFwiZGVwQDEuMC4wXCIsIFwibm9kZV9tb2R1bGVzXCIsIFwiZGVwXCIpO1xuICAgIC8vIFRoZSBzaGFwZSB0aGF0IG1ha2VzIGEgc3RvcmUgcGFja2FnZSByZWFjaGFibGUgZnJvbSBhbm90aGVyIHN0b3JlXG4gICAgLy8gcGFja2FnZTogYSBsaW5rIGJldHdlZW4gdHdvIHN0b3JlIGRpcmVjdG9yaWVzLCBubyBmaWxlcyBvZiBpdHMgb3duLlxuICAgIGNvbnN0IGhpZGRlbkxpbmsgPSBqb2luKFxuICAgICAgdmlydHVhbFN0b3JlLFxuICAgICAgXCJkZXBAMS4wLjBcIixcbiAgICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgICBcIkBzY29wZVwiLFxuICAgICAgXCJoZWxwZXJzXCIsXG4gICAgKTtcblxuICAgIGF3YWl0IG1rZGlyKGpvaW4oZGlzdERpciwgXCJzZXJ2ZXJcIiwgXCJhcHBcIiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIC8vIEV2ZXJ5IGRlcGxveW1lbnQgcm9vdCBuZWVkcyB0aGlzLCBhbmQgYGxvYWRSdW50aW1lYCByZWZ1c2VzIHRvIHNlcnZlXG4gICAgLy8gd2l0aG91dCBpdCwgc28gdGhlIHN0YWdpbmcgcGxhbiBjYXJyaWVzIGl0IGluZGVwZW5kZW50bHkgb2YgYW55IG91dHB1dCdzXG4gICAgLy8gdHJhY2VkIGFzc2V0cy5cbiAgICBhd2FpdCB3cml0ZUZpbGUoam9pbihkaXN0RGlyLCBcInJlcXVpcmVkLXNlcnZlci1maWxlcy5qc29uXCIpLCBcInt9XFxuXCIpO1xuICAgIGF3YWl0IG1rZGlyKGRlcCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgbWtkaXIoc3RvcmUsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGF3YWl0IG1rZGlyKGhpZGRlbiwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgbWtkaXIoZGVwSW5TdG9yZSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGVudHJ5LCBcIm1vZHVsZS5leHBvcnRzID0ge307XFxuXCIpO1xuICAgIGF3YWl0IHdyaXRlRmlsZShqb2luKGRlcCwgXCJpbmRleC5qc1wiKSwgXCIvLyBkZXBcXG5cIik7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4oc3RvcmUsIFwiaW5kZXguanNcIiksIFwiLy8gc3RvcmVcXG5cIik7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4oaGlkZGVuLCBcImluZGV4LmpzXCIpLCBcIi8vIGhlbHBlcnNcXG5cIik7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4oZGVwSW5TdG9yZSwgXCJpbmRleC5qc1wiKSwgXCIvLyBkZXBcXG5cIik7XG4gICAgYXdhaXQgbWtkaXIoZGlybmFtZShoaWRkZW5MaW5rKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgc3ltbGluayhcbiAgICAgIGpvaW4oXG4gICAgICAgIFwiLi5cIixcbiAgICAgICAgXCIuLlwiLFxuICAgICAgICBcIi4uXCIsXG4gICAgICAgIFwiaGVscGVyc0AxLjAuMFwiLFxuICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICBcIkBzY29wZVwiLFxuICAgICAgICBcImhlbHBlcnNcIixcbiAgICAgICksXG4gICAgICBoaWRkZW5MaW5rLFxuICAgICk7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4ocHJvamVjdERpciwgXCIuZW52XCIpLCBcIlNIQVJFRD0xXFxuXCIpO1xuICAgIGF3YWl0IHdyaXRlRmlsZShqb2luKHByb2plY3REaXIsIFwiLmVudi5wcm9kdWN0aW9uXCIpLCBcIlBST0Q9MVxcblwiKTtcbiAgICAvLyBBIHJlbGF0aXZlIGxpbmsgd2hvc2UgdGFyZ2V0IGlzIGl0c2VsZiBzdGFnZWQ6IHBucG0ncyBjb21tb24gc2hhcGUuXG4gICAgYXdhaXQgc3ltbGluayhcImRlcFwiLCBqb2luKHByb2plY3REaXIsIFwibm9kZV9tb2R1bGVzXCIsIFwicmVsLWxpbmtcIikpO1xuICAgIC8vIEFuIGFic29sdXRlIGxpbmsgb3V0IG9mIHRoZSB0cmVlOiBzdGFnaW5nIG11c3QgbWF0ZXJpYWxpemUgaXQgaW5zdGVhZC5cbiAgICBhd2FpdCBzeW1saW5rKHN0b3JlLCBqb2luKHByb2plY3REaXIsIFwibm9kZV9tb2R1bGVzXCIsIFwiYWJzLWxpbmtcIikpO1xuXG4gICAgY29uc3Qgb3V0cHV0ID0ge1xuICAgICAgaWQ6IFwiL1wiLFxuICAgICAgcGF0aG5hbWU6IFwiL1wiLFxuICAgICAgc291cmNlUGFnZTogXCIvcGFnZVwiLFxuICAgICAgZmlsZVBhdGg6IGVudHJ5LFxuICAgICAgcnVudGltZTogXCJub2RlanNcIixcbiAgICAgIGNvbmZpZzoge30sXG4gICAgICBhc3NldHM6IHtcbiAgICAgICAgXCJhcHAvbm9kZV9tb2R1bGVzL2RlcC9pbmRleC5qc1wiOiBqb2luKGRlcCwgXCJpbmRleC5qc1wiKSxcbiAgICAgICAgXCJhcHAvbm9kZV9tb2R1bGVzL3JlbC1saW5rXCI6IGpvaW4oXG4gICAgICAgICAgcHJvamVjdERpcixcbiAgICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICAgIFwicmVsLWxpbmtcIixcbiAgICAgICAgKSxcbiAgICAgICAgXCJhcHAvbm9kZV9tb2R1bGVzL2Ficy1saW5rXCI6IGpvaW4oXG4gICAgICAgICAgcHJvamVjdERpcixcbiAgICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICAgIFwiYWJzLWxpbmtcIixcbiAgICAgICAgKSxcbiAgICAgICAgXCJub2RlX21vZHVsZXMvLnBucG0vaGVscGVyc0AxLjAuMC9ub2RlX21vZHVsZXMvQHNjb3BlL2hlbHBlcnMvaW5kZXguanNcIjpcbiAgICAgICAgICBqb2luKGhpZGRlbiwgXCJpbmRleC5qc1wiKSxcbiAgICAgICAgXCJub2RlX21vZHVsZXMvLnBucG0vZGVwQDEuMC4wL25vZGVfbW9kdWxlcy9kZXAvaW5kZXguanNcIjogam9pbihcbiAgICAgICAgICBkZXBJblN0b3JlLFxuICAgICAgICAgIFwiaW5kZXguanNcIixcbiAgICAgICAgKSxcbiAgICAgICAgXCJub2RlX21vZHVsZXMvLnBucG0vZGVwQDEuMC4wL25vZGVfbW9kdWxlcy9Ac2NvcGUvaGVscGVyc1wiOiBoaWRkZW5MaW5rLFxuICAgICAgfSxcbiAgICAgIGFzc2V0c0hhc2hlczoge30sXG4gICAgfTtcblxuICAgIGNvbnN0IGN0eCA9IHtcbiAgICAgIHJlcG9Sb290LFxuICAgICAgcHJvamVjdERpcixcbiAgICAgIGRpc3REaXIsXG4gICAgICBidWlsZElkOiBcInRlc3QtYnVpbGRcIixcbiAgICAgIG5leHRWZXJzaW9uOiBcIjE2LjMuNVwiLFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIGJhc2VQYXRoOiBcIlwiLFxuICAgICAgICB0cmFpbGluZ1NsYXNoOiBmYWxzZSxcbiAgICAgICAgYXNzZXRQcmVmaXg6IFwiXCIsXG4gICAgICAgIGkxOG46IG51bGwsXG4gICAgICB9LFxuICAgICAgcm91dGluZzogeyBkeW5hbWljUm91dGVzOiBbXSB9LFxuICAgICAgb3V0cHV0czoge1xuICAgICAgICBwYWdlczogW10sXG4gICAgICAgIHBhZ2VzQXBpOiBbXSxcbiAgICAgICAgYXBwUGFnZXM6IFtvdXRwdXRdLFxuICAgICAgICBhcHBSb3V0ZXM6IFtdLFxuICAgICAgICBwcmVyZW5kZXJzOiBbXSxcbiAgICAgICAgc3RhdGljRmlsZXM6IFtdLFxuICAgICAgICBtaWRkbGV3YXJlOiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgIH0gYXMgdW5rbm93biBhcyBCdWlsZENvbXBsZXRlQ29udGV4dDtcblxuICAgIHJldHVybiB7IGN0eCwgcmVwb1Jvb3QgfTtcbiAgfVxuXG4gIGl0KFwic3RhZ2VzIHRoZSB0cmVlLCBwcmVzZXJ2ZXMgc3ltbGlua3MsIGFuZCB3cml0ZXMgdGhlIG1hbmlmZXN0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgbWFrZVJlcG8oKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3cml0ZShjdHgpO1xuXG4gICAgZXhwZWN0KHNvbGVSb290KHJlc3VsdCkpLnRvQmUoXG4gICAgICBqb2luKGN0eC5kaXN0RGlyLCBcImNkay1uZXh0anMtYWRhcHRlclwiLCBcImFwcFwiKSxcbiAgICApO1xuXG4gICAgY29uc3Qgc3RhZ2VkID0gKC4uLnBhcnRzOiBzdHJpbmdbXSkgPT4gam9pbihzb2xlUm9vdChyZXN1bHQpLCAuLi5wYXJ0cyk7XG4gICAgYXdhaXQgZXhwZWN0KFxuICAgICAgcmVhZEZpbGUoc3RhZ2VkKFwiYXBwXCIsIFwiLm5leHRcIiwgXCJzZXJ2ZXJcIiwgXCJhcHBcIiwgXCJwYWdlLmpzXCIpLCBcInV0ZjhcIiksXG4gICAgKS5yZXNvbHZlcy50b0NvbnRhaW4oXCJtb2R1bGUuZXhwb3J0c1wiKTtcbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICByZWFkRmlsZShzdGFnZWQoXCJhcHBcIiwgXCJub2RlX21vZHVsZXNcIiwgXCJkZXBcIiwgXCJpbmRleC5qc1wiKSwgXCJ1dGY4XCIpLFxuICAgICkucmVzb2x2ZXMudG9Db250YWluKFwiZGVwXCIpO1xuXG4gICAgLy8gYGNvcHlGaWxlYCBmYWlscyBvdXRyaWdodCBvbiBhIGRpcmVjdG9yeSBzeW1saW5rLCBhbmQgZGVyZWZlcmVuY2luZyB0aGVcbiAgICAvLyBwbnBtIHN0b3JlIHRyaXBsZXMgdGhlIHRyZWUgYWdhaW5zdCB0aGUgMjUwIE1CIHVuemlwcGVkIExhbWJkYSBsaW1pdC5cbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICBsc3RhdChzdGFnZWQoXCJhcHBcIiwgXCJub2RlX21vZHVsZXNcIiwgXCJyZWwtbGlua1wiKSkudGhlbigocykgPT5cbiAgICAgICAgcy5pc1N5bWJvbGljTGluaygpLFxuICAgICAgKSxcbiAgICApLnJlc29sdmVzLnRvQmUodHJ1ZSk7XG4gICAgLy8gUG9pbnRzIG91dHNpZGUgdGhlIGRlcGxveW1lbnQgcm9vdCwgc28gaXQgd291bGQgZGFuZ2xlIGluIExhbWJkYS5cbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICBsc3RhdChzdGFnZWQoXCJhcHBcIiwgXCJub2RlX21vZHVsZXNcIiwgXCJhYnMtbGlua1wiKSkudGhlbigocykgPT5cbiAgICAgICAgcy5pc1N5bWJvbGljTGluaygpLFxuICAgICAgKSxcbiAgICApLnJlc29sdmVzLnRvQmUoZmFsc2UpO1xuICAgIGF3YWl0IGV4cGVjdChcbiAgICAgIHJlYWRGaWxlKHN0YWdlZChcImFwcFwiLCBcIm5vZGVfbW9kdWxlc1wiLCBcImFicy1saW5rXCIsIFwiaW5kZXguanNcIiksIFwidXRmOFwiKSxcbiAgICApLnJlc29sdmVzLnRvQ29udGFpbihcInN0b3JlXCIpO1xuXG4gICAgLy8gYHdyaXRlU3RhbmRhbG9uZURpcmVjdG9yeWAgY29waWVzIHRoZXNlOyBgb25CdWlsZENvbXBsZXRlYCBoYXMgbm9cbiAgICAvLyBlcXVpdmFsZW50LCBzbyBkcm9wcGluZyBgb3V0cHV0OiBcInN0YW5kYWxvbmVcImAgZHJvcHMgdGhlbSBzaWxlbnRseS5cbiAgICBhd2FpdCBleHBlY3QocmVhZEZpbGUoc3RhZ2VkKFwiYXBwXCIsIFwiLmVudlwiKSwgXCJ1dGY4XCIpKS5yZXNvbHZlcy50b0NvbnRhaW4oXG4gICAgICBcIlNIQVJFRD0xXCIsXG4gICAgKTtcbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICByZWFkRmlsZShzdGFnZWQoXCJhcHBcIiwgXCIuZW52LnByb2R1Y3Rpb25cIiksIFwidXRmOFwiKSxcbiAgICApLnJlc29sdmVzLnRvQ29udGFpbihcIlBST0Q9MVwiKTtcblxuICAgIGNvbnN0IHdyaXR0ZW4gPSBKU09OLnBhcnNlKGF3YWl0IHJlYWRGaWxlKHJlc3VsdC5tYW5pZmVzdFBhdGgsIFwidXRmOFwiKSk7XG4gICAgZXhwZWN0KHdyaXR0ZW4pLnRvRXF1YWwoSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShyZXN1bHQubWFuaWZlc3QpKSk7XG4gICAgZXhwZWN0KHdyaXR0ZW4ucmVsYXRpdmVQcm9qZWN0RGlyKS50b0JlKFwiYXBwXCIpO1xuICB9KTtcblxuICBpdChcImxlYXZlcyBzdG9yZS1vbmx5IHBhY2thZ2VzIGluIHRoZSBzdG9yZSwgYmVoaW5kIHRoZWlyIGxpbmtzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgbWFrZVJlcG8oKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3cml0ZShjdHgpO1xuICAgIGNvbnN0IHN0YWdlZCA9ICguLi5wYXJ0czogc3RyaW5nW10pID0+IGpvaW4oc29sZVJvb3QocmVzdWx0KSwgLi4ucGFydHMpO1xuXG4gICAgLy8gTm9kZSByZXNvbHZlcyBgQHNjb3BlL2hlbHBlcnNgIGZyb20gYGRlcGAgdGhyb3VnaCB0aGUgc3RvcmUgbGluaywgYXMgaXRcbiAgICAvLyBkb2VzIGluIHRoZSB3b3Jrc3BhY2UsIHNvIGxvbmcgYXMgbm90aGluZyBkZXJlZmVyZW5jZXMgdGhlIHRyZWUgKHRoZVxuICAgIC8vIEZ1bmN0aW9ucyB6aXAga2VlcHMgbGlua3MgYXMgbGlua3MpLiBBIGNvcHkgYXQgdGhlIHJvb3QgaXMgZGVhZCB3ZWlnaHQuXG4gICAgYXdhaXQgZXhwZWN0KFxuICAgICAgbHN0YXQoc3RhZ2VkKFwibm9kZV9tb2R1bGVzXCIsIFwiQHNjb3BlXCIsIFwiaGVscGVyc1wiKSksXG4gICAgKS5yZWplY3RzLnRvVGhyb3coL0VOT0VOVC8pO1xuICAgIGF3YWl0IGV4cGVjdChcbiAgICAgIGxzdGF0KFxuICAgICAgICBzdGFnZWQoXG4gICAgICAgICAgXCJub2RlX21vZHVsZXNcIixcbiAgICAgICAgICBcIi5wbnBtXCIsXG4gICAgICAgICAgXCJkZXBAMS4wLjBcIixcbiAgICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICAgIFwiQHNjb3BlXCIsXG4gICAgICAgICAgXCJoZWxwZXJzXCIsXG4gICAgICAgICksXG4gICAgICApLnRoZW4oKHMpID0+IHMuaXNTeW1ib2xpY0xpbmsoKSksXG4gICAgKS5yZXNvbHZlcy50b0JlKHRydWUpO1xuICAgIGF3YWl0IGV4cGVjdChcbiAgICAgIHJlYWRGaWxlKFxuICAgICAgICBzdGFnZWQoXG4gICAgICAgICAgXCJub2RlX21vZHVsZXNcIixcbiAgICAgICAgICBcIi5wbnBtXCIsXG4gICAgICAgICAgXCJkZXBAMS4wLjBcIixcbiAgICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICAgIFwiQHNjb3BlXCIsXG4gICAgICAgICAgXCJoZWxwZXJzXCIsXG4gICAgICAgICAgXCJpbmRleC5qc1wiLFxuICAgICAgICApLFxuICAgICAgICBcInV0ZjhcIixcbiAgICAgICksXG4gICAgKS5yZXNvbHZlcy50b0NvbnRhaW4oXCJoZWxwZXJzXCIpO1xuICB9KTtcblxuICBpdChcInN0YWdlcyB0aGUgbmV4dCBjbG9zdXJlIHRoZSBydW50aW1lJ3MgaW1hZ2Ugb3B0aW1pemVyIHJlcXVpcmVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAvLyBgbmV4dCBidWlsZGAgdHJhY2VzIHdoYXQgdGhlICphcHAqIHJlYWNoZXMsIGFuZCBubyBhcHAgcmVhY2hlcyBuZXh0J3NcbiAgICAvLyBpbWFnZSBvcHRpbWl6ZXIsIHNvIHdpdGhvdXQgdGhpcyBldmVyeSAvX25leHQvaW1hZ2UgcmVxdWVzdCA1MDBzIG9uIGFcbiAgICAvLyBNT0RVTEVfTk9UX0ZPVU5EIHRoYXQgbm90aGluZyBpbiB0aGUgYnVpbGQgd2FybmVkIGFib3V0LlxuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCBtYWtlUmVwbyh7IHdpdGhOZXh0OiB0cnVlIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdyaXRlKGN0eCk7XG4gICAgY29uc3Qgc3RhZ2VkID0gKC4uLnBhcnRzOiBzdHJpbmdbXSkgPT4gam9pbihzb2xlUm9vdChyZXN1bHQpLCAuLi5wYXJ0cyk7XG5cbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICByZWFkRmlsZShcbiAgICAgICAgc3RhZ2VkKFwibm9kZV9tb2R1bGVzXCIsIFwibmV4dFwiLCBcImRpc3RcIiwgXCJzZXJ2ZXJcIiwgXCJpbWFnZS1vcHRpbWl6ZXIuanNcIiksXG4gICAgICAgIFwidXRmOFwiLFxuICAgICAgKSxcbiAgICApLnJlc29sdmVzLnRvQ29udGFpbihcImltYWdlLW9wdGltaXplclwiKTtcbiAgICBhd2FpdCBleHBlY3QoXG4gICAgICByZWFkRmlsZShcbiAgICAgICAgc3RhZ2VkKFxuICAgICAgICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgICAgICAgXCJuZXh0XCIsXG4gICAgICAgICAgXCJkaXN0XCIsXG4gICAgICAgICAgXCJzaGFyZWRcIixcbiAgICAgICAgICBcImxpYlwiLFxuICAgICAgICAgIFwibWF0Y2gtcmVtb3RlLXBhdHRlcm4uanNcIixcbiAgICAgICAgKSxcbiAgICAgICAgXCJ1dGY4XCIsXG4gICAgICApLFxuICAgICkucmVzb2x2ZXMudG9Db250YWluKFwibWF0Y2gtcmVtb3RlLXBhdHRlcm5cIik7XG4gIH0pO1xuXG4gIGl0KFwic3RhZ2VzIHRoZSBsaW5rIG5leHQgcmVzb2x2ZXMgQG5leHQvZW52IHRocm91Z2ggdW5kZXIgcG5wbVwiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhlIHRyYWNlIHN0YXJ0cyBhdCBgQG5leHQvZW52YCdzIHJlYWwgcGF0aCBhbmQgc28gbmV2ZXIgcmVjb3JkcyB0aGVcbiAgICAvLyBsaW5rIGJlc2lkZSBgbmV4dGA7IHdpdGhvdXQgaXQgZXZlcnkgY29sZCBzdGFydCB0aHJldyBcIkNhbm5vdCBmaW5kXG4gICAgLy8gbW9kdWxlICdAbmV4dC9lbnYnXCIuXG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IG1ha2VSZXBvKHsgcG5wbU5leHQ6IHRydWUgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd3JpdGUoY3R4KTtcbiAgICBjb25zdCBsaW5rID0gam9pbihcbiAgICAgIHNvbGVSb290KHJlc3VsdCksXG4gICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgXCIucG5wbVwiLFxuICAgICAgXCJuZXh0QDEuMC4wXCIsXG4gICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgXCJAbmV4dFwiLFxuICAgICAgXCJlbnZcIixcbiAgICApO1xuICAgIGV4cGVjdCgoYXdhaXQgbHN0YXQobGluaykpLmlzU3ltYm9saWNMaW5rKCkpLnRvQmUodHJ1ZSk7XG4gICAgYXdhaXQgZXhwZWN0KHJlYWRGaWxlKGpvaW4obGluaywgXCJpbmRleC5qc1wiKSwgXCJ1dGY4XCIpKS5yZXNvbHZlcy50b0NvbnRhaW4oXG4gICAgICBcIkBuZXh0L2VudlwiLFxuICAgICk7XG4gIH0pO1xuXG4gIGl0KFwid2FybnMgaW5zdGVhZCBvZiBmYWlsaW5nIHdoZW4gbmV4dCBjYW5ub3QgYmUgcmVzb2x2ZWQgZm9yIHRyYWNpbmdcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCBtYWtlUmVwbygpO1xuICAgIGNvbnN0IHdhcm4gPSBqZXN0LnNweU9uKGNvbnNvbGUsIFwid2FyblwiKS5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4ge30pO1xuICAgIGF3YWl0IGV4cGVjdCh3cml0ZShjdHgpKS5yZXNvbHZlcy50b0JlRGVmaW5lZCgpO1xuICAgIGV4cGVjdCh3YXJuKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcbiAgICAgIGV4cGVjdC5zdHJpbmdDb250YWluaW5nKFwiL19uZXh0L2ltYWdlIHdpbGwgZmFpbCBhdCBydW50aW1lXCIpLFxuICAgICk7XG4gIH0pO1xuXG4gIGl0KFwicmVtb3ZlcyBhIHByZXZpb3VzIGJ1aWxkJ3MgdHJlZSBiZWZvcmUgc3RhZ2luZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IG1ha2VSZXBvKCk7XG4gICAgY29uc3QgZmlyc3QgPSBhd2FpdCB3cml0ZShjdHgpO1xuICAgIGNvbnN0IHN0YWxlID0gam9pbihzb2xlUm9vdChmaXJzdCksIFwiYXBwXCIsIFwic3RhbGUuanNcIik7XG4gICAgYXdhaXQgd3JpdGVGaWxlKHN0YWxlLCBcIi8vIHJlbW92ZWQgcm91dGVcXG5cIik7XG5cbiAgICBhd2FpdCB3cml0ZShjdHgpO1xuICAgIGF3YWl0IGV4cGVjdChsc3RhdChzdGFsZSkpLnJlamVjdHMudG9UaHJvdygvRU5PRU5ULyk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwid2l0aCBmdW5jdGlvbkdyb3Vwc1wiLCAoKSA9PiB7XG4gICAgLyoqXG4gICAgICogVHdvIHJvdXRlcyB3aXRoIG9uZSBhc3NldCBlYWNoLCBzbyBcInRoZSBncm91cCdzIHRyZWUgaG9sZHMgaXRzIG93biByb3V0ZVxuICAgICAqIGFuZCBub3QgdGhlIG90aGVyJ3NcIiBpcyBjaGVja2FibGUgYnkgZmlsZS4gRGVsaWJlcmF0ZWx5IG5vdCBgbWFrZVJlcG9gJ3NcbiAgICAgKiByZXBvOiBpdHMgc2luZ2xlIG91dHB1dCBjYW5ub3QgYmUgc3BsaXQuXG4gICAgICovXG4gICAgYXN5bmMgZnVuY3Rpb24gbWFrZVNwbGl0dGFibGVSZXBvKFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICB3aXRoTm90Rm91bmQ/OiBib29sZWFuO1xuICAgICAgICB3aXRoUGFnZXNTc3I/OiBib29sZWFuO1xuICAgICAgICB3aXRoTmV4dD86IGJvb2xlYW47XG4gICAgICB9ID0ge30sXG4gICAgKSB7XG4gICAgICBjb25zdCByZXBvUm9vdCA9IGF3YWl0IG1rZHRlbXAoam9pbih0bXBkaXIoKSwgXCJjZGstbmV4dGpzLWdyb3Vwcy1cIikpO1xuICAgICAgaWYgKG9wdGlvbnMud2l0aE5leHQpIHtcbiAgICAgICAgYXdhaXQgaW5zdGFsbEZha2VOZXh0KHJlcG9Sb290KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHByb2plY3REaXIgPSBqb2luKHJlcG9Sb290LCBcImFwcFwiKTtcbiAgICAgIGNvbnN0IGRpc3REaXIgPSBqb2luKHByb2plY3REaXIsIFwiLm5leHRcIik7XG4gICAgICBhd2FpdCBta2Rpcihqb2luKGRpc3REaXIsIFwic2VydmVyXCIsIFwiYXBwXCIpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGF3YWl0IHdyaXRlRmlsZShqb2luKGRpc3REaXIsIFwicmVxdWlyZWQtc2VydmVyLWZpbGVzLmpzb25cIiksIFwie31cXG5cIik7XG5cbiAgICAgIGNvbnN0IG91dHB1dEZvciA9IGFzeW5jIChuYW1lOiBzdHJpbmcsIHBhdGhuYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgZW50cnkgPSBqb2luKGRpc3REaXIsIFwic2VydmVyXCIsIFwiYXBwXCIsIGAke25hbWV9LmpzYCk7XG4gICAgICAgIGNvbnN0IGFzc2V0ID0gam9pbihwcm9qZWN0RGlyLCBcIm5vZGVfbW9kdWxlc1wiLCBuYW1lLCBcImluZGV4LmpzXCIpO1xuICAgICAgICBhd2FpdCBta2RpcihkaXJuYW1lKGFzc2V0KSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZShlbnRyeSwgYC8vICR7bmFtZX1cXG5gKTtcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKGFzc2V0LCBgLy8gJHtuYW1lfSBkZXBcXG5gKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpZDogcGF0aG5hbWUsXG4gICAgICAgICAgcGF0aG5hbWUsXG4gICAgICAgICAgc291cmNlUGFnZTogcGF0aG5hbWUsXG4gICAgICAgICAgZmlsZVBhdGg6IGVudHJ5LFxuICAgICAgICAgIHJ1bnRpbWU6IFwibm9kZWpzXCIsXG4gICAgICAgICAgY29uZmlnOiB7fSxcbiAgICAgICAgICBhc3NldHM6IHsgW2BhcHAvbm9kZV9tb2R1bGVzLyR7bmFtZX0vaW5kZXguanNgXTogYXNzZXQgfSxcbiAgICAgICAgICBhc3NldHNIYXNoZXM6IHt9LFxuICAgICAgICB9O1xuICAgICAgfTtcblxuICAgICAgY29uc3QgY3R4ID0ge1xuICAgICAgICByZXBvUm9vdCxcbiAgICAgICAgcHJvamVjdERpcixcbiAgICAgICAgZGlzdERpcixcbiAgICAgICAgYnVpbGRJZDogXCJ0ZXN0LWJ1aWxkXCIsXG4gICAgICAgIG5leHRWZXJzaW9uOiBcIjE2LjMuNVwiLFxuICAgICAgICBjb25maWc6IHtcbiAgICAgICAgICBiYXNlUGF0aDogXCJcIixcbiAgICAgICAgICB0cmFpbGluZ1NsYXNoOiBmYWxzZSxcbiAgICAgICAgICBhc3NldFByZWZpeDogXCJcIixcbiAgICAgICAgICBpMThuOiBudWxsLFxuICAgICAgICB9LFxuICAgICAgICByb3V0aW5nOiB7IGR5bmFtaWNSb3V0ZXM6IFtdIH0sXG4gICAgICAgIG91dHB1dHM6IHtcbiAgICAgICAgICBwYWdlczogb3B0aW9ucy53aXRoUGFnZXNTc3JcbiAgICAgICAgICAgID8gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgb3V0cHV0Rm9yKFwic3NyXCIsIFwiL3NzclwiKTtcbiAgICAgICAgICAgICAgICAvLyBBIHNlcGFyYXRlIG91dHB1dCwgd2l0aCBpdHMgb3duIGlkLCBiYWNrZWQgYnkgdGhlIHNhbWUgZmlsZS5cbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhUm91dGUgPSBcIi9fbmV4dC9kYXRhL3Rlc3QtYnVpbGQvc3NyLmpzb25cIjtcbiAgICAgICAgICAgICAgICByZXR1cm4gW3BhZ2UsIHsgLi4ucGFnZSwgaWQ6IGRhdGFSb3V0ZSwgcGF0aG5hbWU6IGRhdGFSb3V0ZSB9XTtcbiAgICAgICAgICAgICAgfSkoKVxuICAgICAgICAgICAgOiBbXSxcbiAgICAgICAgICBwYWdlc0FwaTogW10sXG4gICAgICAgICAgYXBwUGFnZXM6IFtcbiAgICAgICAgICAgIGF3YWl0IG91dHB1dEZvcihcImhvbWVcIiwgXCIvXCIpLFxuICAgICAgICAgICAgLi4uKG9wdGlvbnMud2l0aE5vdEZvdW5kXG4gICAgICAgICAgICAgID8gW2F3YWl0IG91dHB1dEZvcihcIm5vdC1mb3VuZFwiLCBcIi9fbm90LWZvdW5kXCIpXVxuICAgICAgICAgICAgICA6IFtdKSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGFwcFJvdXRlczogW2F3YWl0IG91dHB1dEZvcihcInJlcG9ydHNcIiwgXCIvYXBpL3JlcG9ydHMvW2lkXVwiKV0sXG4gICAgICAgICAgcHJlcmVuZGVyczogW10sXG4gICAgICAgICAgc3RhdGljRmlsZXM6IFtdLFxuICAgICAgICAgIG1pZGRsZXdhcmU6IHVuZGVmaW5lZCxcbiAgICAgICAgfSxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBCdWlsZENvbXBsZXRlQ29udGV4dDtcbiAgICAgIHJldHVybiB7IGN0eCB9O1xuICAgIH1cblxuICAgIGNvbnN0IGdyb3VwcyA9IFt7IG5hbWU6IFwicmVwb3J0c1wiLCByb3V0ZXM6IFtcIi9hcGkvcmVwb3J0cy8qKlwiXSB9XTtcblxuICAgIGl0KFwicmVjb3JkcyB0aGUgYXNzaWdubWVudCBpbiB0aGUgbWFuaWZlc3QgZXZlcnkgZ3JvdXAgc2hhcmVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCBtYWtlU3BsaXR0YWJsZVJlcG8oKTtcbiAgICAgIGNvbnN0IHsgbWFuaWZlc3QgfSA9IGJ1aWxkQWRhcHRlck1hbmlmZXN0KGN0eCwge1xuICAgICAgICBidWlsZEN3ZDogY3R4LnByb2plY3REaXIsXG4gICAgICAgIGZ1bmN0aW9uR3JvdXBzOiBncm91cHMsXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChtYW5pZmVzdC5ncm91cHMpLnRvRXF1YWwoe1xuICAgICAgICBkZWZhdWx0OiBbXCIvXCJdLFxuICAgICAgICByZXBvcnRzOiBbXCIvYXBpL3JlcG9ydHMvW2lkXVwiXSxcbiAgICAgIH0pO1xuICAgICAgLy8gV2hhdCBzeW50aCBjb21wYXJlcyBpdHMgb3duIHByb3BzIHdpdGgsIHRvIGNhdGNoIGEgc3RhbGUgYnVpbGQuXG4gICAgICBleHBlY3QobWFuaWZlc3QuZnVuY3Rpb25Hcm91cHMpLnRvRXF1YWwoZ3JvdXBzKTtcbiAgICAgIC8vIEFuZCB3aGF0IGl0IGRlcGxveXMsIGFzIHRoZSBhc3NpZ25tZW50IGNoZWNrZWQgaXQuXG4gICAgICBleHBlY3QobWFuaWZlc3QuYmVoYXZpb3JzKS50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIGdyb3VwOiBcInJlcG9ydHNcIixcbiAgICAgICAgICByb3V0ZTogXCIvYXBpL3JlcG9ydHMvKipcIixcbiAgICAgICAgICBwYXR0ZXJuOiBcImFwaS9yZXBvcnRzLypcIixcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzdGFnZXMgb25lIHRyZWUgcGVyIGdyb3VwLCBlYWNoIGhvbGRpbmcgb25seSBpdHMgb3duIHJvdXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgbWFrZVNwbGl0dGFibGVSZXBvKCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3cml0ZUJ1aWxkT3V0cHV0cyhjdHgsIHtcbiAgICAgICAgYnVpbGRDd2Q6IGN0eC5wcm9qZWN0RGlyLFxuICAgICAgICBmdW5jdGlvbkdyb3VwczogZ3JvdXBzLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChyZXN1bHQuc3RhZ2VkR3JvdXBzLm1hcCgoZ3JvdXApID0+IGdyb3VwLm5hbWUpLnNvcnQoKSkudG9FcXVhbChbXG4gICAgICAgIFwiZGVmYXVsdFwiLFxuICAgICAgICBcInJlcG9ydHNcIixcbiAgICAgIF0pO1xuICAgICAgY29uc3QgcGF0aE9mID0gKG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBncm91cCA9IHJlc3VsdC5zdGFnZWRHcm91cHMuZmluZCgoaXQpID0+IGl0Lm5hbWUgPT09IG5hbWUpO1xuICAgICAgICBpZiAoIWdyb3VwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBzdGFnZWQgZ3JvdXAgXCIke25hbWV9XCJgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ3JvdXAucGF0aDtcbiAgICAgIH07XG4gICAgICAvLyBVbmRlciBgZ3JvdXBzLzxuYW1lPi9gLCBzbyBuZWl0aGVyIGNhbiBjb2xsaWRlIHdpdGggdGhlIHVuc3BsaXQgbGF5b3V0LlxuICAgICAgZXhwZWN0KHBhdGhPZihcInJlcG9ydHNcIikpLnRvQmUoXG4gICAgICAgIGpvaW4oY3R4LmRpc3REaXIsIFwiY2RrLW5leHRqcy1hZGFwdGVyXCIsIFwiZ3JvdXBzXCIsIFwicmVwb3J0c1wiKSxcbiAgICAgICk7XG4gICAgICBleHBlY3QocGF0aE9mKFwiZGVmYXVsdFwiKSkudG9CZShcbiAgICAgICAgam9pbihjdHguZGlzdERpciwgXCJjZGstbmV4dGpzLWFkYXB0ZXJcIiwgXCJncm91cHNcIiwgXCJkZWZhdWx0XCIpLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgaGFzID0gKG5hbWU6IHN0cmluZywgLi4ucGFydHM6IHN0cmluZ1tdKSA9PlxuICAgICAgICBsc3RhdChqb2luKHBhdGhPZihuYW1lKSwgLi4ucGFydHMpKS50aGVuKFxuICAgICAgICAgICgpID0+IHRydWUsXG4gICAgICAgICAgKCkgPT4gZmFsc2UsXG4gICAgICAgICk7XG4gICAgICBhd2FpdCBleHBlY3QoXG4gICAgICAgIGhhcyhcInJlcG9ydHNcIiwgXCJhcHBcIiwgXCIubmV4dFwiLCBcInNlcnZlclwiLCBcImFwcFwiLCBcInJlcG9ydHMuanNcIiksXG4gICAgICApLnJlc29sdmVzLnRvQmUodHJ1ZSk7XG4gICAgICBhd2FpdCBleHBlY3QoXG4gICAgICAgIGhhcyhcInJlcG9ydHNcIiwgXCJhcHBcIiwgXCJub2RlX21vZHVsZXNcIiwgXCJyZXBvcnRzXCIsIFwiaW5kZXguanNcIiksXG4gICAgICApLnJlc29sdmVzLnRvQmUodHJ1ZSk7XG4gICAgICAvLyBUaGUgcG9pbnQgb2Ygc3BsaXR0aW5nOiB0aGUgb3RoZXIgZ3JvdXAncyByb3V0ZSBpcyBhYnNlbnQuXG4gICAgICBhd2FpdCBleHBlY3QoXG4gICAgICAgIGhhcyhcInJlcG9ydHNcIiwgXCJhcHBcIiwgXCIubmV4dFwiLCBcInNlcnZlclwiLCBcImFwcFwiLCBcImhvbWUuanNcIiksXG4gICAgICApLnJlc29sdmVzLnRvQmUoZmFsc2UpO1xuICAgICAgYXdhaXQgZXhwZWN0KFxuICAgICAgICBoYXMoXCJkZWZhdWx0XCIsIFwiYXBwXCIsIFwiLm5leHRcIiwgXCJzZXJ2ZXJcIiwgXCJhcHBcIiwgXCJob21lLmpzXCIpLFxuICAgICAgKS5yZXNvbHZlcy50b0JlKHRydWUpO1xuICAgICAgYXdhaXQgZXhwZWN0KFxuICAgICAgICBoYXMoXCJkZWZhdWx0XCIsIFwiYXBwXCIsIFwiLm5leHRcIiwgXCJzZXJ2ZXJcIiwgXCJhcHBcIiwgXCJyZXBvcnRzLmpzXCIpLFxuICAgICAgKS5yZXNvbHZlcy50b0JlKGZhbHNlKTtcbiAgICAgIC8vIFRoZSBtYW5pZmVzdCBpcyB3cml0dGVuIG9uY2UsIGFib3ZlIHRoZSBncm91cHM7IGBOZXh0anNCdWlsZGAgY29waWVzIGl0XG4gICAgICAvLyBhbmQgdGhlIHJ1bnRpbWUgc2hlbGwgaW50byBlYWNoIGdyb3VwJ3MgcmVzZXJ2ZWQgcnVudGltZSBkaXIgYWZ0ZXJ3YXJkcyxcbiAgICAgIC8vIHNvIG5vIGdyb3VwJ3Mgc3RhZ2VkIHRyZWUgbWF5IGNvbnRhaW4gdGhhdCBkaXJlY3RvcnkgeWV0LlxuICAgICAgZXhwZWN0KHJlc3VsdC5tYW5pZmVzdFBhdGgpLnRvQmUoXG4gICAgICAgIGpvaW4oY3R4LmRpc3REaXIsIFwiY2RrLW5leHRqcy1hZGFwdGVyXCIsIFwibWFuaWZlc3QuanNvblwiKSxcbiAgICAgICk7XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgW1wiZGVmYXVsdFwiLCBcInJlcG9ydHNcIl0pIHtcbiAgICAgICAgYXdhaXQgZXhwZWN0KGhhcyhuYW1lLCBSVU5USU1FX0RJUl9OQU1FKSkucmVzb2x2ZXMudG9CZShmYWxzZSk7XG4gICAgICB9XG4gICAgICAvLyBgcmVxdWlyZWQtc2VydmVyLWZpbGVzLmpzb25gIGlzIG5vdCBhbnkgb3V0cHV0J3MgdHJhY2VkIGFzc2V0LCBzbyBhXG4gICAgICAvLyBncm91cCB0aGF0IHJlYWNoZXMgaXQgb25seSB0aHJvdWdoIHRoZSBvdXRwdXRzIGl0IG93bnMgZG9lcyBub3QgZ2V0IGl0IC1cbiAgICAgIC8vIGFuZCBgbG9hZFJ1bnRpbWVgIHByb2JlcyBmb3IgaXQgYmVmb3JlIHNlcnZpbmcgYW55dGhpbmcsIHNvIHRoZSB3aG9sZVxuICAgICAgLy8gcm9vdCBhbnN3ZXJzIFwidGhlIGRlcGxveW1lbnQgcGFja2FnZSBpcyBpbmNvbXBsZXRlXCIgd2l0aG91dCBpdC5cbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBbXCJkZWZhdWx0XCIsIFwicmVwb3J0c1wiXSkge1xuICAgICAgICBhd2FpdCBleHBlY3QoXG4gICAgICAgICAgaGFzKG5hbWUsIFwiYXBwXCIsIFwiLm5leHRcIiwgXCJyZXF1aXJlZC1zZXJ2ZXItZmlsZXMuanNvblwiKSxcbiAgICAgICAgKS5yZXNvbHZlcy50b0JlKHRydWUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoXCJzdGFnZXMgdGhlIGltYWdlIG9wdGltaXplciBpbnRvIGRlZmF1bHQgb25seSwgc2VydmUtc3RhdGljIGludG8gZXZlcnkgZ3JvdXBcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gT25seSBgZGVmYXVsdGAgYW5zd2VycyBgL19uZXh0L2ltYWdlYCwgYW5kIHRoZSBvcHRpbWl6ZXIgaXMgd2hhdCBwdWxsc1xuICAgICAgLy8gYHNoYXJwYCBpbjsgcHJlcmVuZGVyZWQgYW5kIHN0YXRpYyByZXN1bHRzIGFyZSBzZXJ2ZWQgd2l0aFxuICAgICAgLy8gYHNlcnZlLXN0YXRpY2AgaW4gd2hpY2hldmVyIGdyb3VwIHRoZXkgbGFuZC5cbiAgICAgIGNvbnN0IHsgY3R4IH0gPSBhd2FpdCBtYWtlU3BsaXR0YWJsZVJlcG8oeyB3aXRoTmV4dDogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdyaXRlQnVpbGRPdXRwdXRzKGN0eCwge1xuICAgICAgICBidWlsZEN3ZDogY3R4LnByb2plY3REaXIsXG4gICAgICAgIGZ1bmN0aW9uR3JvdXBzOiBncm91cHMsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGhhcyA9IChuYW1lOiBzdHJpbmcsIGZpbGU6IHN0cmluZykgPT5cbiAgICAgICAgbHN0YXQoXG4gICAgICAgICAgam9pbihcbiAgICAgICAgICAgIHJlc3VsdC5zdGFnZWRHcm91cHMuZmluZCgoaXQpID0+IGl0Lm5hbWUgPT09IG5hbWUpIS5wYXRoLFxuICAgICAgICAgICAgXCJub2RlX21vZHVsZXNcIixcbiAgICAgICAgICAgIFwibmV4dFwiLFxuICAgICAgICAgICAgXCJkaXN0XCIsXG4gICAgICAgICAgICBmaWxlLFxuICAgICAgICAgICksXG4gICAgICAgICkudGhlbihcbiAgICAgICAgICAoKSA9PiB0cnVlLFxuICAgICAgICAgICgpID0+IGZhbHNlLFxuICAgICAgICApO1xuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIFtcbiAgICAgICAgXCJzZXJ2ZXIvaW1hZ2Utb3B0aW1pemVyLmpzXCIsXG4gICAgICAgIFwic2hhcmVkL2xpYi9pbWFnZS1jb25maWcuanNcIixcbiAgICAgICAgXCJzZXJ2ZXIvY29uZmlnLXNoYXJlZC5qc1wiLFxuICAgICAgICBcInNoYXJlZC9saWIvbWF0Y2gtcmVtb3RlLXBhdHRlcm4uanNcIixcbiAgICAgIF0pIHtcbiAgICAgICAgYXdhaXQgZXhwZWN0KGhhcyhcImRlZmF1bHRcIiwgZmlsZSkpLnJlc29sdmVzLnRvQmUodHJ1ZSk7XG4gICAgICAgIGF3YWl0IGV4cGVjdChoYXMoXCJyZXBvcnRzXCIsIGZpbGUpKS5yZXNvbHZlcy50b0JlKGZhbHNlKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBbXCJkZWZhdWx0XCIsIFwicmVwb3J0c1wiXSkge1xuICAgICAgICBhd2FpdCBleHBlY3QoaGFzKG5hbWUsIFwic2VydmVyL3NlcnZlLXN0YXRpYy5qc1wiKSkucmVzb2x2ZXMudG9CZSh0cnVlKTtcbiAgICAgICAgYXdhaXQgZXhwZWN0KFxuICAgICAgICAgIGhhcyhcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBcInNlcnZlci9saWIvcm91dGVyLXV0aWxzL2luc3RydW1lbnRhdGlvbi1nbG9iYWxzLmV4dGVybmFsLmpzXCIsXG4gICAgICAgICAgKSxcbiAgICAgICAgKS5yZXNvbHZlcy50b0JlKHRydWUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoXCJzdGFnZXMgdGhlIG5vdC1mb3VuZCBwYWdlIGludG8gZXZlcnkgZ3JvdXAsIG5vdCBvbmx5IGl0cyBvd25lclwiLCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBUaGUgcnVudGltZSByZW5kZXJzIGEgNDA0IHdpdGggdGhlIG1hbmlmZXN0J3MgYC9fbm90LWZvdW5kYCB3aGVyZXZlciB0aGVcbiAgICAgIC8vIHJlcXVlc3QgbGFuZGVkLCBzbyBgL2FwaS9yZXBvcnRzL25vcGVgIG5lZWRzIGl0IGluIHRoZSByZXBvcnRzIGdyb3VwLlxuICAgICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IG1ha2VTcGxpdHRhYmxlUmVwbyh7IHdpdGhOb3RGb3VuZDogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IHsgZ3JvdXBzOiBzdGFnZWQsIG1hbmlmZXN0IH0gPSBidWlsZEFkYXB0ZXJNYW5pZmVzdChjdHgsIHtcbiAgICAgICAgYnVpbGRDd2Q6IGN0eC5wcm9qZWN0RGlyLFxuICAgICAgICBmdW5jdGlvbkdyb3VwczogZ3JvdXBzLFxuICAgICAgfSk7XG4gICAgICBleHBlY3QobWFuaWZlc3QuZ3JvdXBzPy5kZWZhdWx0KS50b0NvbnRhaW4oXCIvX25vdC1mb3VuZFwiKTtcbiAgICAgIGV4cGVjdChzdGFnZWQubWFwKChncm91cCkgPT4gZ3JvdXAubmFtZSkuc29ydCgpKS50b0VxdWFsKFtcbiAgICAgICAgXCJkZWZhdWx0XCIsXG4gICAgICAgIFwicmVwb3J0c1wiLFxuICAgICAgXSk7XG4gICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIHN0YWdlZCkge1xuICAgICAgICBleHBlY3QoWy4uLmdyb3VwLnN0YWdpbmcua2V5cygpXSkudG9Db250YWluKFxuICAgICAgICAgIFwiYXBwLy5uZXh0L3NlcnZlci9hcHAvbm90LWZvdW5kLmpzXCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdChcImtlZXBzIGEgUGFnZXMgUm91dGVyIHBhZ2UncyBkYXRhIHJvdXRlIGluIHRoZSBwYWdlJ3MgZ3JvdXBcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IG1ha2VTcGxpdHRhYmxlUmVwbyh7IHdpdGhQYWdlc1NzcjogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IHsgZ3JvdXBzOiBzdGFnZWQsIG1hbmlmZXN0IH0gPSBidWlsZEFkYXB0ZXJNYW5pZmVzdChjdHgsIHtcbiAgICAgICAgYnVpbGRDd2Q6IGN0eC5wcm9qZWN0RGlyLFxuICAgICAgICBmdW5jdGlvbkdyb3VwczogW3sgbmFtZTogXCJzc3JcIiwgcm91dGVzOiBbXCIvc3NyXCJdIH1dLFxuICAgICAgfSk7XG4gICAgICBleHBlY3QobWFuaWZlc3QuZ3JvdXBzPy5zc3IpLnRvRXF1YWwoW1xuICAgICAgICBcIi9fbmV4dC9kYXRhL3Rlc3QtYnVpbGQvc3NyLmpzb25cIixcbiAgICAgICAgXCIvc3NyXCIsXG4gICAgICBdKTtcbiAgICAgIGNvbnN0IGRlZmF1bHRHcm91cCA9IHN0YWdlZC5maW5kKChncm91cCkgPT4gZ3JvdXAubmFtZSA9PT0gXCJkZWZhdWx0XCIpITtcbiAgICAgIC8vIE90aGVyd2lzZSB0aGUgcGFnZSBhbmQgaXRzIHRyYWNlIHNoaXAgaW4gdGhlIGRlZmF1bHQgemlwIGFzIHdlbGwuXG4gICAgICBleHBlY3QoWy4uLmRlZmF1bHRHcm91cC5zdGFnaW5nLmtleXMoKV0pLm5vdC50b0NvbnRhaW4oXG4gICAgICAgIFwiYXBwLy5uZXh0L3NlcnZlci9hcHAvc3NyLmpzXCIsXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoXCJyZWZ1c2VzIHRvIHNwbGl0IGFuIGkxOG4gYXBwLCB3aG9zZSByb3V0ZXMgYXJlIGxvY2FsZS1wcmVmaXhlZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB7IGN0eCB9ID0gYXdhaXQgbWFrZVNwbGl0dGFibGVSZXBvKCk7XG4gICAgICBjb25zdCBpMThuQ3R4ID0ge1xuICAgICAgICAuLi5jdHgsXG4gICAgICAgIGNvbmZpZzoge1xuICAgICAgICAgIC4uLmN0eC5jb25maWcsXG4gICAgICAgICAgaTE4bjogeyBsb2NhbGVzOiBbXCJlblwiXSwgZGVmYXVsdExvY2FsZTogXCJlblwiIH0sXG4gICAgICAgIH0sXG4gICAgICB9IGFzIHVua25vd24gYXMgQnVpbGRDb21wbGV0ZUNvbnRleHQ7XG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgYnVpbGRBZGFwdGVyTWFuaWZlc3QoaTE4bkN0eCwge1xuICAgICAgICAgIGJ1aWxkQ3dkOiBjdHgucHJvamVjdERpcixcbiAgICAgICAgICBmdW5jdGlvbkdyb3VwczogZ3JvdXBzLFxuICAgICAgICB9KSxcbiAgICAgICkudG9UaHJvdygvY2Fubm90IGJlIGNvbWJpbmVkIHdpdGggYGkxOG5gLyk7XG4gICAgfSk7XG5cbiAgICBpdChcInRocm93cyBvbiBhIHBhdHRlcm4gdGhhdCBtYXRjaGVzIG5vdGhpbmcsIHJhdGhlciB0aGFuIHNpbGVudGx5IG5vdCBzcGxpdHRpbmdcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgeyBjdHggfSA9IGF3YWl0IG1ha2VTcGxpdHRhYmxlUmVwbygpO1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGJ1aWxkQWRhcHRlck1hbmlmZXN0KGN0eCwge1xuICAgICAgICAgIGJ1aWxkQ3dkOiBjdHgucHJvamVjdERpcixcbiAgICAgICAgICBmdW5jdGlvbkdyb3VwczogW3sgbmFtZTogXCJ0eXBvXCIsIHJvdXRlczogW1wiL2FwaS9yZXBvcnQvKipcIl0gfV0sXG4gICAgICAgIH0pLFxuICAgICAgKS50b1Rocm93KC9tYXRjaGVzIG5vIHJvdXRlIGluIHRoaXMgYnVpbGQvKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==