cdk-nextjs 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +1548 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +852 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +861 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +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 +1213 -0
  157. package/lib/runtime/core.test.d.ts +1 -0
  158. package/lib/runtime/core.test.js +1678 -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 +41595 -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 +55 -0
  213. package/lib/runtime/next-modules.js +124 -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 +41588 -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,1099 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PATH_PATTERN_LITERAL = exports.FUNCTION_GROUPS_ENV_VAR = exports.DEFAULT_FUNCTION_GROUP = void 0;
4
+ exports.parseFunctionGroupsEnv = parseFunctionGroupsEnv;
5
+ exports.assertNoI18nSplitting = assertNoI18nSplitting;
6
+ exports.validateFunctionGroups = validateFunctionGroups;
7
+ exports.assignRoutesToGroups = assignRoutesToGroups;
8
+ exports.routedPatterns = routedPatterns;
9
+ exports.pathPatternsFor = pathPatternsFor;
10
+ exports.interceptedRoute = interceptedRoute;
11
+ exports.cloudFrontPatternRegex = cloudFrontPatternRegex;
12
+ /**
13
+ * `functionGroups` resolution: the rules shared by `next build` and synth.
14
+ *
15
+ * Splitting spans two processes. `onBuildComplete` stages one deployment tree
16
+ * per group while `next build` is still running; the constructs turn the groups
17
+ * into CloudFront behaviors or API Gateway resources at synth. If the two
18
+ * disagree, CloudFront sends a request to a function whose zip lacks its
19
+ * entrypoint — so the build decides both, here, and records the behaviors it
20
+ * checked in the manifest for synth to deploy as they are. Synth still runs
21
+ * {@link validateFunctionGroups}, to fail before a `next build` it would
22
+ * otherwise pay for.
23
+ *
24
+ * Nothing in this file imports `aws-cdk-lib`: it is bundled into the adapter by
25
+ * esbuild. The public JSII struct consumers actually write (`NextjsFunctionGroup`,
26
+ * which adds per-group `overrides`) is in `src/nextjs-compute/nextjs-functions.ts`
27
+ * and is structurally assignable to {@link FunctionGroupSpec}.
28
+ */
29
+ const constants_1 = require("../constants");
30
+ const manifest_1 = require("../runtime/manifest");
31
+ const base_path_1 = require("../utils/base-path");
32
+ /**
33
+ * The implicit group every unassigned route falls into. Reserved as a group
34
+ * name: it is also the construct id suffix and the function whose URL backs the
35
+ * distribution's default behavior.
36
+ */
37
+ exports.DEFAULT_FUNCTION_GROUP = "default";
38
+ /**
39
+ * How the resolved groups reach `onBuildComplete`, which cannot read CDK props —
40
+ * it runs inside `next build`. `CDK_NEXTJS_INIT_CACHE_DIR` is the precedent.
41
+ */
42
+ exports.FUNCTION_GROUPS_ENV_VAR = "CDK_NEXTJS_FUNCTION_GROUPS";
43
+ const ERROR_PREFIX = `${constants_1.LOG_PREFIX} \`functionGroups\`: `;
44
+ const NAME_PATTERN = /^[a-zA-Z0-9-]+$/;
45
+ const SUBTREE_SUFFIX = "/**";
46
+ /**
47
+ * The literal characters a CloudFront path pattern may contain: its alphabet
48
+ * (`A-Z a-z 0-9 _ - . * $ / ~ " ' @ : +` and `&`) less the two wildcards, which
49
+ * `validateRoutePattern` only accepts as a trailing `/**`. `nextjs-distribution.ts`
50
+ * adds the wildcards back to encode `public/` names.
51
+ *
52
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesCacheBehavior.html#DownloadDistValuesPathPattern
53
+ */
54
+ exports.PATH_PATTERN_LITERAL = /[a-zA-Z0-9_\-.$/~"'@:+&]/;
55
+ /**
56
+ * Read {@link FUNCTION_GROUPS_ENV_VAR}. `undefined` — not the empty array — when
57
+ * unset, because "no splitting" and "split into nothing" are different requests
58
+ * and only the first is valid.
59
+ */
60
+ function parseFunctionGroupsEnv(value) {
61
+ return value ? JSON.parse(value) : undefined;
62
+ }
63
+ /**
64
+ * Splitting and `i18n` are mutually exclusive, and it is a CloudFront limit
65
+ * again.
66
+ *
67
+ * With `i18n` configured, every route template is locale-prefixed
68
+ * (`/en/pricing`, `/de/pricing`), so honoring a `/pricing` group would take one
69
+ * behavior *per locale per pattern* — a budget of 75 behaviors spent in a handful
70
+ * of routes. The alternative, a `*` in the locale position, matches any first
71
+ * segment and would capture routes belonging to other groups. Neither is
72
+ * something to do silently, so refuse instead.
73
+ */
74
+ function assertNoI18nSplitting(i18n) {
75
+ if (i18n === null || i18n === undefined) {
76
+ return;
77
+ }
78
+ throw new Error(`${ERROR_PREFIX}\`functionGroups\` cannot be combined with \`i18n\`. ` +
79
+ `With i18n every route is locale-prefixed, so routing a group at the edge ` +
80
+ `would need one CloudFront behavior per locale per pattern, against a ` +
81
+ `quota of 75 for the whole distribution. Deploy one function for every ` +
82
+ `route (omit \`functionGroups\`), or drop \`i18n\`.`);
83
+ }
84
+ /**
85
+ * Reject everything that cannot be honored, at the earliest of the two sides to
86
+ * see it. Called from both, because either can be the first: `next build` runs
87
+ * before synth reads the manifest, but a `skipBuild: true` consumer inverts that.
88
+ */
89
+ function validateFunctionGroups(groups) {
90
+ if (groups.length === 0) {
91
+ throw new Error(`${ERROR_PREFIX}\`functionGroups\` is an empty array. Omit the prop ` +
92
+ `entirely to deploy one function for every route, which is the default.`);
93
+ }
94
+ const seenNames = new Set();
95
+ const patternOwner = new Map();
96
+ for (const group of groups) {
97
+ if (group.name === exports.DEFAULT_FUNCTION_GROUP) {
98
+ throw new Error(`${ERROR_PREFIX}"${exports.DEFAULT_FUNCTION_GROUP}" is a reserved group name: ` +
99
+ `it is the implicit group every unassigned route falls into.`);
100
+ }
101
+ if (!NAME_PATTERN.test(group.name)) {
102
+ throw new Error(`${ERROR_PREFIX}Group name "${group.name}" must match ` +
103
+ `${NAME_PATTERN} — it becomes a construct id and part of a Lambda ` +
104
+ `function name.`);
105
+ }
106
+ if (seenNames.has(group.name)) {
107
+ throw new Error(`${ERROR_PREFIX}Two groups are both named "${group.name}".`);
108
+ }
109
+ seenNames.add(group.name);
110
+ if (group.routes.length === 0) {
111
+ throw new Error(`${ERROR_PREFIX}Group "${group.name}" owns no routes. Every group is a ` +
112
+ `Lambda function, so an empty one would deploy and never be reached.`);
113
+ }
114
+ for (const route of group.routes) {
115
+ validateRoutePattern(route, group.name);
116
+ const owner = patternOwner.get(route);
117
+ if (owner !== undefined) {
118
+ throw new Error(`${ERROR_PREFIX}Pattern "${route}" appears in both group "${owner}" ` +
119
+ `and group "${group.name}". A route can only be packaged into one ` +
120
+ `function. (Overlapping-but-different patterns are fine: "/api/**" ` +
121
+ `in one group and "/api/reports/**" in another resolves ` +
122
+ `longest-first.)`);
123
+ }
124
+ patternOwner.set(route, group.name);
125
+ }
126
+ }
127
+ }
128
+ /**
129
+ * A pattern is an exact static path (`/pricing`) or a subtree (`/api/reports/**`).
130
+ *
131
+ * **Dynamic segments are rejected**, and the reason is CloudFront rather than
132
+ * anything about Next.js. Patterns become behavior path patterns, and CloudFront
133
+ * supports only `*` and `?`, so `/dashboard/[id]` could only ever deploy as
134
+ * `/dashboard/*` — which also matches `/dashboard/settings` and
135
+ * `/dashboard/a/b/c`. If those are in another group, CloudFront routes them to a
136
+ * function whose zip lacks their entrypoint: a crash on a route the consumer
137
+ * explicitly assigned elsewhere. Accepting a syntax whose granularity cannot be
138
+ * honored would be worse than rejecting it.
139
+ *
140
+ * The restriction costs nothing that was achievable anyway. `/dashboard/**` →
141
+ * `/dashboard/*` is the same URL space exactly, and isolating one heavy dynamic
142
+ * route still works as a subtree: `/api/report/**` covers `/api/report/[id]`.
143
+ *
144
+ * `NextjsRegionalFunctions` gets the same restriction even though API Gateway
145
+ * REST could express `/{id}` precisely — so that switching deployment type (to
146
+ * Regional for GovCloud, say) never silently changes how routes are grouped.
147
+ * That one is a consistency choice, not a technical limit.
148
+ */
149
+ function validateRoutePattern(route, groupName) {
150
+ const where = `Group "${groupName}" pattern "${route}"`;
151
+ if (!route.startsWith("/")) {
152
+ throw new Error(`${ERROR_PREFIX}${where} must start with "/". Patterns are URL paths as ` +
153
+ `the browser requests them.`);
154
+ }
155
+ // `/index` is deliberately allowed. For the App Router it is a real route of
156
+ // its own (`app/index/page.tsx`), which `routablePathnames` keeps apart from
157
+ // `/`. For the Pages Router it is the home page under the name `next build`
158
+ // reports it by, one entrypoint registered under `/` as well — and grouping
159
+ // that would leave `/` on the default behavior with a function that lacks the
160
+ // file. Only the assignment can tell the two apart, and its coverage check
161
+ // (`assertEdgeReachesEveryFile`) rejects the second.
162
+ if (route === "/") {
163
+ throw new Error(`${ERROR_PREFIX}${where} cannot be routed. CloudFront has no path ` +
164
+ `pattern that matches only "/" — the default behavior serves it — so the ` +
165
+ `home page always belongs to the "${exports.DEFAULT_FUNCTION_GROUP}" group. ` +
166
+ `Group the routes around it instead.`);
167
+ }
168
+ // `/_next/…` is Next's own URL space — build assets, `/_next/image`, and the
169
+ // Pages Router data routes — and each has its behavior already: the data route
170
+ // of a grouped page follows it (see `pathPatternsFor`), and a `_next/*` behavior
171
+ // would compete with the static-asset and image ones for everything else.
172
+ if (route === "/_next" || route.startsWith("/_next/")) {
173
+ throw new Error(`${ERROR_PREFIX}${where} is under "/_next", which Next.js reserves for ` +
174
+ `build assets, image optimization and data routes. A Pages Router ` +
175
+ `page's "/_next/data/…" route follows the page into its group, so ` +
176
+ `group the page itself instead.`);
177
+ }
178
+ if (route === SUBTREE_SUFFIX) {
179
+ throw new Error(`${ERROR_PREFIX}${where} would own every route, leaving the default ` +
180
+ `group empty. Splitting exists to divide routes between functions; ` +
181
+ `omit \`functionGroups\` to deploy them all in one.`);
182
+ }
183
+ if (/[[\]]/.test(route)) {
184
+ throw new Error(`${ERROR_PREFIX}${where} contains a dynamic segment. Patterns become ` +
185
+ `CloudFront behavior path patterns, which support only "*" and "?", so ` +
186
+ `"${route}" could only deploy as a wildcard that also captures its ` +
187
+ `siblings. Use a subtree instead: "/blog/**" owns "/blog/[slug]".`);
188
+ }
189
+ if (/\((.*)\)/.test(route)) {
190
+ throw new Error(`${ERROR_PREFIX}${where} contains a route group segment. Route groups ` +
191
+ `like "(marketing)" organize files and never appear in a URL, so they ` +
192
+ `cannot be routed on. Use the URL path the route is served at.`);
193
+ }
194
+ const withoutSubtree = route.endsWith(SUBTREE_SUFFIX)
195
+ ? route.slice(0, -SUBTREE_SUFFIX.length)
196
+ : route;
197
+ if (/[*?]/.test(withoutSubtree)) {
198
+ throw new Error(`${ERROR_PREFIX}${where} contains a wildcard somewhere other than a ` +
199
+ `trailing "/**". The only two forms are an exact path ("/pricing") and ` +
200
+ `a subtree ("/api/reports/**").`);
201
+ }
202
+ if (route.includes("//")) {
203
+ throw new Error(`${ERROR_PREFIX}${where} contains an empty path segment.`);
204
+ }
205
+ // A route Next.js serves can still hold a character no path pattern can:
206
+ // `app/über/page.tsx`, `app/a b/page.tsx`, `app/a,b/page.tsx` all build, and
207
+ // the pattern passes every check above. `pathPatternsFor` copies it verbatim,
208
+ // so it reached `addBehavior` untouched and was left for CloudFront to reject,
209
+ // in an error naming neither the group nor the route. The `public/`
210
+ // workaround, one `?` per UTF-8 byte, is not available here: `?` matches *any*
211
+ // byte, so `/über` would deploy as `/??ber` and also send `/xyber` to this
212
+ // group's function, whose zip lacks its entrypoint. That is the sibling capture
213
+ // dynamic segments are rejected for, so the same answer applies.
214
+ const invalid = [...new Set(withoutSubtree)].filter((char) => !exports.PATH_PATTERN_LITERAL.test(char));
215
+ if (invalid.length > 0) {
216
+ throw new Error(`${ERROR_PREFIX}${where} contains ` +
217
+ `${invalid.map((char) => JSON.stringify(char)).join(", ")}, which a ` +
218
+ `CloudFront behavior path pattern cannot contain (allowed: A-Z a-z 0-9 ` +
219
+ `_ - . $ / ~ " ' @ : + &). Escaping it with "?" would also match other ` +
220
+ `routes of the same length. Use a subtree on a parent segment whose ` +
221
+ `name is plain ASCII instead: "/intl/**" owns "/intl/über".`);
222
+ }
223
+ }
224
+ /**
225
+ * Split every route template across the groups, longest matching pattern first,
226
+ * then prove that the edge routes every URL each file serves to the group that
227
+ * file was packaged into.
228
+ *
229
+ * Its `templates` are keyed by group name and always contain
230
+ * {@link DEFAULT_FUNCTION_GROUP}, so callers can iterate them as the complete set
231
+ * of functions to deploy. The default group is allowed to be empty of *templates*
232
+ * — it still serves `/_next/image`, any static file, and anything the
233
+ * distribution's catch-all behavior sends it.
234
+ *
235
+ * `basePath` is prepended to each pattern before matching, because manifest
236
+ * templates are basePath-prefixed and consumers write the routes their app
237
+ * declares.
238
+ *
239
+ * Packaging matches patterns against *templates*, but CloudFront routes *URLs*,
240
+ * and a file answers URLs none of its templates spells: an optional catch-all's
241
+ * parent, the `trailingSlash` form, a Pages Router data URL, every other
242
+ * template it shares (root params synthesize `/en` and `/de` from one
243
+ * `[locale]` page). An interception route is worse: it is never requested at its
244
+ * own path at all. So after matching, intercepting files move to the group of
245
+ * the URL they intercept ({@link reassignInterceptingFiles}), and the result is
246
+ * replayed through the same behaviors `NextjsDistribution` deploys
247
+ * ({@link assertEdgeReachesEveryFile}, {@link assertRewritesStayInGroup}). A URL
248
+ * that would reach a function without its file throws here, during `next build`,
249
+ * rather than answering 404 once deployed.
250
+ */
251
+ function assignRoutesToGroups(groups, entries, options) {
252
+ validateFunctionGroups(groups);
253
+ const basePath = (0, base_path_1.basePathPrefix)(options.basePath);
254
+ // Matched with the very behaviors `NextjsDistribution` deploys for the
255
+ // declared patterns, most specific first, so packaging and the edge share one
256
+ // routing model and the first match is the winner. Data routes are left out:
257
+ // no template is under `/_next`, and which groups have them is decided by
258
+ // this assignment.
259
+ const edgeBase = {
260
+ basePath,
261
+ buildId: options.buildId,
262
+ trailingSlash: options.trailingSlash ?? false,
263
+ };
264
+ const patterns = edgeBehaviors(groups, {}, { ...edgeBase, dataRouteGroups: new Set() });
265
+ const matchedPatterns = new Set();
266
+ // An entrypoint is a *file*; two templates can share one (a Pages Router page
267
+ // and its `/_next/data/<buildId>/…json` sibling). Splitting them across zips
268
+ // would stage the same file twice and route one of them to a function that
269
+ // has it by accident, so ownership is recorded per entrypoint and reused.
270
+ const groupOfEntrypoint = new Map();
271
+ // Which `patterns` index won the entrypoint. `patterns` is sorted
272
+ // most-specific-first, so a lower index is the better claim, and keeping it
273
+ // stops a second template that shares the entrypoint from taking it over with
274
+ // a *broader* pattern. Without it the owner was whichever of the two templates
275
+ // `entries` happened to visit last — the same build grouped differently
276
+ // depending on manifest key order.
277
+ const winningIndexOfEntrypoint = new Map();
278
+ for (const entry of entries) {
279
+ let winner;
280
+ for (const [index, pattern] of patterns.entries()) {
281
+ if (!pattern.regex.test(entry.template)) {
282
+ continue;
283
+ }
284
+ // Every match is recorded, not only the winning one. A pattern fully
285
+ // shadowed by a narrower pattern in another group never wins anything —
286
+ // "/api/**" against an app whose only API routes are under
287
+ // "/api/reports/**" — so recording just the winner left it looking like a
288
+ // typo and threw below, rejecting the very layout the duplicate-pattern
289
+ // error a few lines up documents as supported.
290
+ matchedPatterns.add(`${pattern.group}\u0000${pattern.route}`);
291
+ winner ??= index;
292
+ }
293
+ // An intercepting file's own template (`/feed/(..)photo/[id]`) is not a URL
294
+ // anyone requests, so it does not decide the file's group; the URL it
295
+ // intercepts does, below. Its match still counts against the typo check.
296
+ if (winner === undefined || isInterceptionTemplate(entry.template)) {
297
+ continue;
298
+ }
299
+ const incumbent = winningIndexOfEntrypoint.get(entry.entrypointId);
300
+ if (incumbent === undefined || winner < incumbent) {
301
+ winningIndexOfEntrypoint.set(entry.entrypointId, winner);
302
+ groupOfEntrypoint.set(entry.entrypointId, patterns[winner].group);
303
+ }
304
+ }
305
+ // A pattern matching nothing is a typo, and a typo here is invisible: the
306
+ // route stays in the default group and the split silently does less than it
307
+ // was asked to. Cheap to catch, so catch it.
308
+ for (const group of groups) {
309
+ for (const route of group.routes) {
310
+ if (!matchedPatterns.has(`${group.name}\u0000${route}`)) {
311
+ throw new Error(`${ERROR_PREFIX}Group "${group.name}" pattern "${route}" matches no ` +
312
+ `route in this build. ` +
313
+ optionalCatchAllParentHint(route, entries, basePath) +
314
+ `Patterns match route templates as Next.js declares them (e.g. ` +
315
+ `"/blog/[slug]" is matched by "/blog/**"), and prerendered pages and ` +
316
+ `static assets are served from S3 and need no group.`);
317
+ }
318
+ }
319
+ }
320
+ const edge = {
321
+ ...edgeBase,
322
+ // Only a group that owns a Pages Router page has data URLs to route. Read
323
+ // before interception moves files: those are App Router, never pages.
324
+ dataRouteGroups: new Set(entries
325
+ .filter((entry) => entry.type === "page")
326
+ .map((entry) => groupOfEntrypoint.get(entry.entrypointId) ?? exports.DEFAULT_FUNCTION_GROUP)),
327
+ };
328
+ reassignInterceptingFiles(entries, groupOfEntrypoint, edgeBehaviors(groups, templatesByGroup(groups, entries, groupOfEntrypoint), edge), edge);
329
+ const assigned = templatesByGroup(groups, entries, groupOfEntrypoint);
330
+ // Rebuilt rather than reused: an intercepting file never adds an optional
331
+ // catch-all parent, so this is the same list, but only by that argument.
332
+ const behaviors = edgeBehaviors(groups, assigned, edge);
333
+ const router = {
334
+ fileOfTemplate: fileOfTemplate(entries),
335
+ routing: options.routing,
336
+ };
337
+ assertEdgeReachesEveryFile(entries, groupOfEntrypoint, behaviors, edge, router);
338
+ assertRewritesStayInGroup(groupOfEntrypoint, behaviors, router);
339
+ for (const key of Object.keys(assigned)) {
340
+ assigned[key] = [...assigned[key]].sort();
341
+ }
342
+ return {
343
+ templates: assigned,
344
+ behaviors: behaviors.map(({ group, route, pattern }) => ({
345
+ group,
346
+ route,
347
+ pattern,
348
+ })),
349
+ };
350
+ }
351
+ /**
352
+ * The patterns a group is *routed* on: the ones it declares, plus the parent
353
+ * path of every optional catch-all a subtree pattern moved into it.
354
+ *
355
+ * `/blog/[[...slug]]` serves `/blog` as well as everything under it, and
356
+ * `/blog/**` moves the whole file — but deploys as `blog/*`, which does not
357
+ * match `/blog`. So the parent is routed automatically, as an exact pattern of
358
+ * its own; declaring `/blog` by hand is a pattern with no route of its own and
359
+ * is rejected as a typo, with a hint pointing here. Nothing else a subtree owns
360
+ * needs this: a file whose parent URL is its subtree's base can only be an
361
+ * optional catch-all, since Next.js rejects `app/blog/page.tsx` next to it.
362
+ *
363
+ * @param ownedTemplates the templates assigned to the group, basePath-prefixed
364
+ * as `manifest.groups` records them
365
+ */
366
+ function routedPatterns(routes, ownedTemplates, basePath) {
367
+ const result = [...routes];
368
+ for (const route of routes) {
369
+ if (!route.endsWith(SUBTREE_SUFFIX)) {
370
+ continue;
371
+ }
372
+ const parent = route.slice(0, -SUBTREE_SUFFIX.length);
373
+ const prefix = `${prefixBasePath(parent, basePath)}/`;
374
+ const ownsOptionalCatchAll = ownedTemplates.some((template) => template.startsWith(prefix) &&
375
+ OPTIONAL_CATCH_ALL_SEGMENT.test(template.slice(prefix.length)));
376
+ if (ownsOptionalCatchAll && !result.includes(parent)) {
377
+ result.push(parent);
378
+ }
379
+ }
380
+ return result;
381
+ }
382
+ /**
383
+ * CloudFront path patterns for one group pattern, without a leading slash —
384
+ * the form `NextjsDistribution.getPathPattern` expects, so the basePath is
385
+ * added there rather than here.
386
+ *
387
+ * Two patterns come back when the group owns a Pages Router route: its RSC-era
388
+ * equivalent is a second URL space, `/_next/data/<buildId>/<route>.json`, which
389
+ * the default behavior would otherwise send to the default group.
390
+ *
391
+ * A third comes back for an exact route in a `trailingSlash` app, where the
392
+ * canonical URL is `/pricing/` rather than `/pricing`: the bare pattern does not
393
+ * match it, so without this every request for the route the user actually links to
394
+ * falls through to the default group's function — which, for a Pages Router API
395
+ * route, has no entrypoint for it at all. Subtree patterns need no variant
396
+ * (`pricing/*` already matches `/pricing/`), and neither do the data URLs, which
397
+ * never carry the slash.
398
+ */
399
+ function pathPatternsFor(route, options) {
400
+ const isSubtree = route.endsWith(SUBTREE_SUFFIX);
401
+ const base = isSubtree ? route.slice(0, -SUBTREE_SUFFIX.length) : route;
402
+ const bare = base.replace(/^\//, "");
403
+ const patterns = [isSubtree ? `${bare}/*` : bare];
404
+ if (!isSubtree && options.trailingSlash && bare) {
405
+ patterns.push(`${bare}/`);
406
+ }
407
+ if (options.hasDataRoutes) {
408
+ // The literal build ID, not a `*` for it. CloudFront's `*` also matches
409
+ // `/`, so `_next/data/*/blog/*` claimed `/_next/data/<id>/docs/blog/x.json`
410
+ // too — another group's page, sent to a function without it. Every other
411
+ // pattern is anchored at the start of the path; this one now is as well.
412
+ //
413
+ // It makes these behaviors change whenever the build ID does, which is every
414
+ // deploy unless `deploymentId` pins it. A client still holding the previous
415
+ // build requests `/_next/data/<old id>/…`, which no behavior matches, so it
416
+ // reaches the default function. That is correct rather than merely
417
+ // harmless: `next start` 404s a data request for another build ID
418
+ // (`handleNextDataRequest` in `next/dist/server/base-server.js`) and so does
419
+ // the runtime, which has no pathname for it, and the Pages Router client
420
+ // treats a data 404 as an asset error and hard-navigates to the page
421
+ // (`fetchNextData` → `markAssetError` → `handleRouteInfoError` in
422
+ // `next/dist/shared/lib/router/router.js`), which gets the new build.
423
+ patterns.push(isSubtree
424
+ ? `_next/data/${dataBuildId(options.buildId)}/${bare}/*`
425
+ : `_next/data/${dataBuildId(options.buildId)}/${bare}.json`);
426
+ }
427
+ return patterns;
428
+ }
429
+ /**
430
+ * Rank a CloudFront path pattern so the most specific is added first: literal
431
+ * segments before the first `*` dominate, then an exact pattern before a
432
+ * wildcard one, then total segments, then length. {@link edgeBehaviors} sorts
433
+ * on it.
434
+ *
435
+ * Ranking on the leading literal is what a CloudFront wildcard forces, because
436
+ * it matches across `/` rather than within one segment: an exact `a/b` has to
437
+ * precede the subtree `a/*` that would otherwise swallow it, though the two are
438
+ * the same length and depth. At equal literal depth the exact one still goes
439
+ * first, since a trailingSlash `a/b/` is otherwise outranked by the subtree
440
+ * `a/b/*`, one segment longer, that matches it. Since the data patterns carry
441
+ * the literal build ID, no pattern has a wildcard anywhere but at its end.
442
+ */
443
+ function behaviorSpecificity(pattern) {
444
+ const segments = pattern.split("/").filter(Boolean);
445
+ const firstWildcard = segments.findIndex((segment) => segment.includes("*"));
446
+ const literalDepth = firstWildcard === -1 ? segments.length : firstWildcard;
447
+ const exact = firstWildcard === -1 ? 1 : 0;
448
+ return ((literalDepth * 2 + exact) * 1000000 +
449
+ segments.length * 10000 +
450
+ pattern.length);
451
+ }
452
+ /**
453
+ * The build ID as it goes into a path pattern. A custom `generateBuildId` can
454
+ * return anything, and a character CloudFront cannot spell would otherwise fail
455
+ * the deploy naming neither the build ID nor the group.
456
+ */
457
+ function dataBuildId(buildId) {
458
+ if (!buildId) {
459
+ throw new Error(`${ERROR_PREFIX}Routing a Pages Router app's "/_next/data/<buildId>/…" ` +
460
+ `URLs needs its build ID, and none was passed. This is a cdk-nextjs ` +
461
+ `bug: the build ID comes from the adapter manifest.`);
462
+ }
463
+ const invalid = [...new Set(buildId)].filter((char) => !exports.PATH_PATTERN_LITERAL.test(char) || char === "/");
464
+ if (invalid.length > 0) {
465
+ throw new Error(`${ERROR_PREFIX}The build ID "${buildId}" contains ` +
466
+ `${invalid.map((char) => JSON.stringify(char)).join(", ")}, which a ` +
467
+ `CloudFront path pattern cannot hold, so its "/_next/data" URLs cannot ` +
468
+ `be routed to a group. Make \`generateBuildId\` return only A-Z a-z ` +
469
+ `0-9 _ - . characters.`);
470
+ }
471
+ return buildId;
472
+ }
473
+ /**
474
+ * The typo check's hint for the one exact pattern that was the documented
475
+ * workaround: the parent of an optional catch-all, which has no template.
476
+ */
477
+ function optionalCatchAllParentHint(route, entries, basePath) {
478
+ if (route.endsWith(SUBTREE_SUFFIX)) {
479
+ return "";
480
+ }
481
+ const prefix = `${prefixBasePath(route, basePath)}/`;
482
+ const catchAll = entries.find((entry) => entry.template.startsWith(prefix) &&
483
+ OPTIONAL_CATCH_ALL_SEGMENT.test(entry.template.slice(prefix.length)));
484
+ if (!catchAll) {
485
+ return "";
486
+ }
487
+ return (`"${route}" is served by the optional catch-all "${catchAll.template}", ` +
488
+ `whose subtree pattern "${route}${SUBTREE_SUFFIX}" routes "${route}" as ` +
489
+ `well — use that instead. `);
490
+ }
491
+ /** `/blog/[[...slug]]`'s last segment. */
492
+ const OPTIONAL_CATCH_ALL_SEGMENT = /^\[\[\.\.\.[^\]/]+\]\]$/;
493
+ /**
494
+ * Next.js's interception markers, longest-overlapping first, exactly as
495
+ * `INTERCEPTION_ROUTE_MARKERS` in
496
+ * `next/dist/shared/lib/router/utils/interception-routes.js` orders them.
497
+ */
498
+ const INTERCEPTION_MARKERS = ["(..)(..)", "(.)", "(..)", "(...)"];
499
+ function interceptionMarkerOf(path) {
500
+ for (const segment of path.split("/")) {
501
+ const marker = INTERCEPTION_MARKERS.find((it) => segment.startsWith(it));
502
+ if (marker) {
503
+ return marker;
504
+ }
505
+ }
506
+ return undefined;
507
+ }
508
+ function isInterceptionTemplate(template) {
509
+ return interceptionMarkerOf(template) !== undefined;
510
+ }
511
+ /**
512
+ * The route an interception route intercepts: `/feed/(..)photo/[id]` →
513
+ * `/photo/[id]`. `extractInterceptionRouteInformation` from
514
+ * `next/dist/shared/lib/router/utils/interception-routes.js`, restated because
515
+ * this file is bundled without `next`. The template is already a normalized app
516
+ * path (no route groups, no `@slot`s), so none of its normalization is needed.
517
+ * Next.js's interception rewrite matches exactly this path, and only with a
518
+ * `Next-Url` header — which CloudFront does not route on.
519
+ */
520
+ function interceptedRoute(path) {
521
+ const marker = interceptionMarkerOf(path);
522
+ if (marker === undefined) {
523
+ return undefined;
524
+ }
525
+ const at = path.indexOf(marker);
526
+ const intercepting = path.slice(0, at).split("/").filter(Boolean);
527
+ const rest = path
528
+ .slice(at + marker.length)
529
+ .split("/")
530
+ .filter(Boolean);
531
+ const parent = marker === "(.)"
532
+ ? intercepting
533
+ : marker === "(..)"
534
+ ? intercepting.slice(0, -1)
535
+ : marker === "(..)(..)"
536
+ ? intercepting.slice(0, -2)
537
+ : [];
538
+ return `/${[...parent, ...rest].join("/")}`;
539
+ }
540
+ /**
541
+ * Templates that name what a request is *rewritten* to inside Next.js, never
542
+ * what the browser asks for: the RSC payload (`/pricing.rsc`) and segment
543
+ * prefetches (`/pricing.segments/…`) are requested as `/pricing` with an `RSC`
544
+ * header, which is why `pricing` alone has always routed them.
545
+ */
546
+ function isInternalTemplate(path) {
547
+ return path.endsWith(".rsc") || path.includes(".segments/");
548
+ }
549
+ /**
550
+ * Every group behavior, most specific first: the order CloudFront has to see
551
+ * them in, since it stops at the first match. The assignment returns this list
552
+ * and the constructs deploy it as it is.
553
+ */
554
+ function edgeBehaviors(groups, assigned, edge) {
555
+ return groups
556
+ .flatMap((group) => routedPatterns(group.routes, assigned[group.name] ?? [], edge.basePath).flatMap((route) => pathPatternsFor(route, {
557
+ trailingSlash: edge.trailingSlash,
558
+ buildId: edge.buildId,
559
+ hasDataRoutes: edge.dataRouteGroups.has(group.name),
560
+ }).map((pattern) => ({
561
+ group: group.name,
562
+ route,
563
+ pattern,
564
+ regex: cloudFrontPatternRegex(`${edge.basePath}/${pattern}`),
565
+ }))))
566
+ .sort((a, b) => behaviorSpecificity(b.pattern) - behaviorSpecificity(a.pattern));
567
+ }
568
+ /**
569
+ * CloudFront path pattern matching: anchored at both ends, `*` for any run of
570
+ * characters `/` included, `?` for exactly one, case-sensitive. `pattern` has to
571
+ * carry the leading slash CloudFront implies.
572
+ *
573
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesCacheBehavior.html#DownloadDistValuesPathPattern
574
+ */
575
+ function cloudFrontPatternRegex(pattern) {
576
+ const source = [...pattern]
577
+ .map((char) => char === "*"
578
+ ? ".*"
579
+ : char === "?"
580
+ ? "."
581
+ : char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
582
+ .join("");
583
+ return new RegExp(`^${source}$`);
584
+ }
585
+ /** The behavior CloudFront would pick for `url`, `undefined` for the default one. */
586
+ function edgeBehaviorFor(behaviors, url) {
587
+ return behaviors.find((behavior) => behavior.regex.test(url));
588
+ }
589
+ function templatesByGroup(groups, entries, groupOfEntrypoint) {
590
+ const assigned = {
591
+ [exports.DEFAULT_FUNCTION_GROUP]: [],
592
+ };
593
+ for (const group of groups) {
594
+ assigned[group.name] = [];
595
+ }
596
+ for (const entry of entries) {
597
+ const group = groupOfEntrypoint.get(entry.entrypointId) ?? exports.DEFAULT_FUNCTION_GROUP;
598
+ assigned[group].push(entry.template);
599
+ }
600
+ return assigned;
601
+ }
602
+ /**
603
+ * Put each intercepting file in the group of the URL it intercepts.
604
+ *
605
+ * With `/feed/**` grouped, `app/feed/(..)photo/[id]/page.tsx` matched it and
606
+ * moved to the feed group. But the soft navigation it exists for requests
607
+ * `/photo/1` with a `Next-Url: /feed` header; CloudFront routes on the URL alone,
608
+ * so the request reaches whichever function owns `/photo/*`, where Next.js's
609
+ * interception rewrite (a `beforeFiles` rule on that header) resolves it to the
610
+ * intercepting file — which that function did not have.
611
+ *
612
+ * Moving the file there is always possible unless the intercepted URL space is
613
+ * itself split: `/photo/[id]` in the default group with `/photo/1` grouped
614
+ * elsewhere would need the file in both. That throws.
615
+ */
616
+ function reassignInterceptingFiles(entries, groupOfEntrypoint, behaviors, edge) {
617
+ for (const entry of entries) {
618
+ const path = stripBasePath(entry.template, edge.basePath);
619
+ if (path === undefined || isInternalTemplate(path)) {
620
+ continue;
621
+ }
622
+ const target = interceptedRoute(path);
623
+ if (target === undefined) {
624
+ continue;
625
+ }
626
+ const url = withBasePath(target, edge.basePath);
627
+ const group = edgeBehaviorFor(behaviors, url)?.group ?? exports.DEFAULT_FUNCTION_GROUP;
628
+ const intercepted = templateRegex(url);
629
+ const split = behaviors.find((behavior) => behavior.group !== group &&
630
+ !behavior.pattern.startsWith("_next/data/") &&
631
+ sampleUrl(behavior.route, edge.basePath).some((it) => intercepted.test(it)));
632
+ if (split) {
633
+ throw new Error(`${ERROR_PREFIX}"${entry.entrypointId}" is the interception route ` +
634
+ `"${entry.template}", which Next.js reaches by rewriting a request for ` +
635
+ `"${url}" inside whichever function CloudFront sent it to — so it is ` +
636
+ `packaged with the group that owns "${url}". That URL space is split, ` +
637
+ `though: most of it reaches ${groupLabel(group)}, but group ` +
638
+ `"${split.group}"'s pattern "${split.route}" claims part of it, and ` +
639
+ `one file cannot be in both. Route all of "${target}" to one group.`);
640
+ }
641
+ groupOfEntrypoint.set(entry.entrypointId, group);
642
+ }
643
+ }
644
+ /** A URL a group pattern routes, to test against another route's URL space. */
645
+ function sampleUrl(route, basePath) {
646
+ return route.endsWith(SUBTREE_SUFFIX)
647
+ ? [`${basePath}${route.slice(0, -SUBTREE_SUFFIX.length)}/_`]
648
+ : [`${basePath}${route}`];
649
+ }
650
+ /** The URLs a template stands for, as a regex: `[id]` is one segment, and so on. */
651
+ function templateRegex(template) {
652
+ const source = template
653
+ .split("/")
654
+ .filter(Boolean)
655
+ .map((segment) => [
656
+ `/${segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`,
657
+ "/[^/]+",
658
+ "/.+",
659
+ "(?:/.+)?",
660
+ ][segmentKind(segment)])
661
+ .join("");
662
+ return new RegExp(`^${source || "/"}$`);
663
+ }
664
+ /**
665
+ * Throw unless every URL each file serves reaches the group holding it.
666
+ *
667
+ * Checked for every file, the default group's included: the invariant is "the
668
+ * edge never sends a request to a function without its file", and a group
669
+ * pattern can break it by claiming a URL of a file left in the default group as
670
+ * easily as by leaving one behind. A dynamic template stands for a URL space,
671
+ * not one URL, so it is also checked against the part of that space other
672
+ * groups' patterns capture ({@link capturedDynamicUrls}): a `/[...slug]` left in
673
+ * the default group answers `/blog/a/b` too, which `/blog/**` sends elsewhere.
674
+ *
675
+ * Only the URLs as Next.js spells them are replayed, and that is a known gap
676
+ * rather than an oversight: CloudFront path patterns and API Gateway resources
677
+ * both match case-sensitively, while `@next/routing` matches templates
678
+ * case-insensitively. `/API/reports/1` therefore misses a `/api/reports/**`
679
+ * group and reaches the default function, which resolves it to a template it
680
+ * does not have. Neither edge can be told to fold case, and lowercasing at the
681
+ * edge would break the case-sensitive S3 keys behind `public/`, so there is
682
+ * nothing to check here that could pass; the runtime answers such a request
683
+ * itself (see `ownedRouteError`).
684
+ */
685
+ function assertEdgeReachesEveryFile(entries, groupOfEntrypoint, behaviors, edge, router) {
686
+ const files = new Map();
687
+ for (const entry of entries) {
688
+ const list = files.get(entry.entrypointId) ?? [];
689
+ list.push(entry);
690
+ files.set(entry.entrypointId, list);
691
+ }
692
+ // Deep enough for a sample to get past every template a capturing group
693
+ // could shadow it with.
694
+ const deepest = Math.max(0, ...entries.map((entry) => {
695
+ const path = stripBasePath(entry.template, edge.basePath);
696
+ return path !== undefined && isRoutablePath(path)
697
+ ? path.split("/").filter(Boolean).length
698
+ : 0;
699
+ })) + 1;
700
+ for (const [file, fileEntries] of files) {
701
+ const owner = groupOfEntrypoint.get(file) ?? exports.DEFAULT_FUNCTION_GROUP;
702
+ const misrouted = [];
703
+ for (const entry of fileEntries) {
704
+ for (const url of servedUrls(entry.template, entry.type, edge)) {
705
+ const behavior = edgeBehaviorFor(behaviors, url);
706
+ const group = behavior?.group ?? exports.DEFAULT_FUNCTION_GROUP;
707
+ if (group !== owner && !misrouted.some((it) => it.url === url)) {
708
+ misrouted.push({ url, group, route: behavior?.route });
709
+ }
710
+ }
711
+ for (const it of capturedDynamicUrls(entry, owner, deepest, behaviors, edge, router)) {
712
+ if (!misrouted.some((known) => known.url === it.url)) {
713
+ misrouted.push(it);
714
+ }
715
+ }
716
+ }
717
+ if (misrouted.length > 0) {
718
+ throw new Error(misroutedFileMessage(file, owner, misrouted, edge));
719
+ }
720
+ }
721
+ }
722
+ /**
723
+ * Stands in for "any value" of a dynamic segment in a sample URL. A literal
724
+ * template of that exact name would shadow it, which can only hide a misroute,
725
+ * never invent one.
726
+ */
727
+ const ANY_SEGMENT = "_";
728
+ /**
729
+ * Whether a request can resolve to `path` (basePath stripped) directly: not an
730
+ * RSC or segment rewrite, an interception route, or a data-URL alias (a data URL
731
+ * resolves to the page it names).
732
+ */
733
+ function isRoutablePath(path) {
734
+ return (!isInternalTemplate(path) &&
735
+ !isInterceptionTemplate(path) &&
736
+ !path.startsWith("/_next/data/"));
737
+ }
738
+ /** 0 static, 1 `[param]`, 2 `[...catchAll]`, 3 `[[...optional]]`. */
739
+ function segmentKind(segment) {
740
+ if (OPTIONAL_CATCH_ALL_SEGMENT.test(segment)) {
741
+ return 3;
742
+ }
743
+ if (/^\[\.\.\.[^\]]+\]$/.test(segment)) {
744
+ return 2;
745
+ }
746
+ return /^\[[^\]]+\]$/.test(segment) ? 1 : 0;
747
+ }
748
+ /**
749
+ * The URLs of a *dynamic* template's space that another group's behavior
750
+ * captures, and that Next.js — running in that group's function — still
751
+ * resolves to this template's file.
752
+ *
753
+ * `servedUrls` replays the template as spelled, which is exact for a static
754
+ * route but not for `/[...slug]`: the text `/[...slug]` never matches `blog/*`,
755
+ * yet `/blog/a/b` does, reaches the blog function, and resolves there to
756
+ * `/[...slug]`, which the blog zip lacks. So each other group's behavior is
757
+ * intersected with the template's URL space, one sample URL per shape
758
+ * ({@link sampleTemplatePaths}), and each sample is resolved the way Next.js
759
+ * resolves it ({@link resolveFile}). A more specific template in the capturing
760
+ * group legitimately shadows the sample (`/blog/[slug]` answers `/blog/_`, so
761
+ * only `/blog/_/_` is a misroute); anything it does not shadow is flagged.
762
+ */
763
+ function capturedDynamicUrls(entry, owner, deepest, behaviors, edge, router) {
764
+ const path = stripBasePath(entry.template, edge.basePath);
765
+ if (path === undefined ||
766
+ !path.includes("[") ||
767
+ manifest_1.ERROR_PAGE_SUFFIXES.includes(path) ||
768
+ !isRoutablePath(path)) {
769
+ return [];
770
+ }
771
+ const segments = path.split("/").filter(Boolean);
772
+ const samples = new Set();
773
+ for (const behavior of behaviors) {
774
+ if (behavior.group === owner ||
775
+ behavior.pattern.startsWith("_next/data/")) {
776
+ continue;
777
+ }
778
+ const bare = behavior.pattern.replace(/\/$/, "");
779
+ const isSubtree = bare.endsWith("/*");
780
+ const prefix = (isSubtree ? bare.slice(0, -2) : bare)
781
+ .split("/")
782
+ .filter(Boolean);
783
+ for (const sample of sampleTemplatePaths(segments, prefix, isSubtree, Math.max(deepest, prefix.length + 1))) {
784
+ samples.add(sample);
785
+ }
786
+ }
787
+ const misrouted = [];
788
+ // `resolved` is `url` as Next.js matches it: without the trailing slash.
789
+ const check = (url, resolved) => {
790
+ const behavior = edgeBehaviorFor(behaviors, url);
791
+ const group = behavior?.group ?? exports.DEFAULT_FUNCTION_GROUP;
792
+ if (group === owner || misrouted.some((it) => it.url === url)) {
793
+ return;
794
+ }
795
+ if (resolveFile(resolved, router) === entry.entrypointId) {
796
+ misrouted.push({
797
+ url,
798
+ group,
799
+ route: behavior?.route,
800
+ servedAs: entry.template,
801
+ });
802
+ }
803
+ };
804
+ for (const sample of samples) {
805
+ for (const { url, resolved } of urlVariants(sample, entry.type, edge)) {
806
+ check(url, resolved);
807
+ }
808
+ }
809
+ return misrouted;
810
+ }
811
+ /**
812
+ * Sample paths in both a template's URL space and a behavior's: for a subtree
813
+ * `prefix/*`, every way the template's segments can line up with `prefix` and
814
+ * continue past it, one sample per resulting length up to `maxDepth`, with
815
+ * {@link ANY_SEGMENT} for each dynamic value beyond the prefix. For an exact
816
+ * pattern, the pattern's own path if the template matches it.
817
+ */
818
+ function sampleTemplatePaths(template, prefix, isSubtree, maxDepth) {
819
+ if (!isSubtree) {
820
+ const path = `/${prefix.join("/")}`;
821
+ return templateRegex(`/${template.join("/")}`).test(path) ? [path] : [];
822
+ }
823
+ const valueAt = (at) => at < prefix.length ? prefix[at] : ANY_SEGMENT;
824
+ const results = [];
825
+ const walk = (index, acc) => {
826
+ if (index === template.length) {
827
+ // Exactly the prefix is kept too: `prefix/*` matches its trailing-slash
828
+ // form, which `check` adds for a `trailingSlash` app.
829
+ if (acc.length >= prefix.length) {
830
+ results.push(`/${acc.join("/")}`);
831
+ }
832
+ return;
833
+ }
834
+ const segment = template[index];
835
+ const at = acc.length;
836
+ const kind = segmentKind(segment);
837
+ if (kind === 0) {
838
+ if (at >= prefix.length || prefix[at] === segment) {
839
+ walk(index + 1, [...acc, segment]);
840
+ }
841
+ return;
842
+ }
843
+ if (kind === 1) {
844
+ walk(index + 1, [...acc, valueAt(at)]);
845
+ return;
846
+ }
847
+ for (let count = kind === 2 ? 1 : 0; at + count <= maxDepth; count++) {
848
+ const taken = Array.from({ length: count }, (_, i) => valueAt(at + i));
849
+ walk(index + 1, [...acc, ...taken]);
850
+ }
851
+ };
852
+ walk(0, []);
853
+ return results;
854
+ }
855
+ /**
856
+ * The URLs one template's file answers at the edge.
857
+ *
858
+ * Nothing for the error pages (every group stages them), the RSC and
859
+ * segment-prefetch rewrites (requested at the page's own URL), and interception
860
+ * routes (reached only through the intercepted URL's rewrite). Otherwise the
861
+ * template itself, an optional catch-all's parent, and for each of those the
862
+ * `trailingSlash` form and a Pages Router page's data URL. Only the slash-less
863
+ * data URL: the client never adds one.
864
+ */
865
+ function servedUrls(template, type, edge) {
866
+ const path = stripBasePath(template, edge.basePath);
867
+ if (path === undefined ||
868
+ manifest_1.ERROR_PAGE_SUFFIXES.includes(path) ||
869
+ isInternalTemplate(path) ||
870
+ isInterceptionTemplate(path)) {
871
+ return [];
872
+ }
873
+ if (path.startsWith("/_next/data/")) {
874
+ return [template];
875
+ }
876
+ const paths = [path];
877
+ const optional = /^(.*)\/(\[\[\.\.\.[^\]/]+\]\])$/.exec(path);
878
+ if (optional) {
879
+ paths.push(optional[1] || "/");
880
+ }
881
+ return paths.flatMap((it) => urlVariants(it, type, edge).map(({ url }) => url));
882
+ }
883
+ /**
884
+ * A path's URL, its `trailingSlash` form and a Pages Router page's data URL,
885
+ * each with `resolved`: the URL as Next.js matches it, without the trailing slash.
886
+ */
887
+ function urlVariants(path, type, edge) {
888
+ const url = withBasePath(path, edge.basePath);
889
+ const variants = [{ url, resolved: url }];
890
+ if (edge.trailingSlash && path !== "/") {
891
+ variants.push({ url: `${url}/`, resolved: url });
892
+ }
893
+ if (type === "page" && edge.buildId) {
894
+ const data = `${edge.basePath}/_next/data/${edge.buildId}${path === "/" ? "/index" : path}.json`;
895
+ variants.push({ url: data, resolved: data });
896
+ }
897
+ return variants;
898
+ }
899
+ function misroutedFileMessage(file, owner, misrouted, edge) {
900
+ const where = misrouted
901
+ .map((it) => `"${it.url}" to ${groupLabel(it.group)}` +
902
+ (it.route ? ` (its pattern "${it.route}")` : ""))
903
+ .join(", ");
904
+ const head = `${ERROR_PREFIX}"${file}" is packaged into ${groupLabel(owner)}, but ` +
905
+ `CloudFront would send ${where}, whose function does not have it: a 404 on ` +
906
+ `every such request. Every URL one file serves has to reach the group that ` +
907
+ `holds the file.`;
908
+ const captured = misrouted.filter((it) => it.servedAs !== undefined);
909
+ if (captured.length > 0) {
910
+ const templates = [...new Set(captured.map((it) => `"${it.servedAs}"`))];
911
+ return (`${head} Those URLs are part of the dynamic route ` +
912
+ `${templates.join(", ")} ("${ANY_SEGMENT}" stands for any segment ` +
913
+ `value): the pattern captures them at the edge, and no route packaged ` +
914
+ `into the capturing group is more specific, so Next.js still resolves ` +
915
+ `them to this file. Give that group a route that answers them (a ` +
916
+ `catch-all under its pattern, say), or narrow the pattern.`);
917
+ }
918
+ if (owner === exports.DEFAULT_FUNCTION_GROUP) {
919
+ return (`${head} A pattern claims a URL of a file that no pattern moved: narrow ` +
920
+ `it, or give the group the file's other routes too.`);
921
+ }
922
+ const unroutable = misrouted.filter((it) => suggestedPattern(it.url, edge) === undefined);
923
+ if (unroutable.length > 0) {
924
+ return (`${head} ${unroutable.map((it) => `"${it.url}"`).join(", ")} cannot be ` +
925
+ `routed to any group — CloudFront has no pattern for the home page alone, ` +
926
+ `and a dynamic first segment would need "/**" — so this file can only be ` +
927
+ `served by the "${exports.DEFAULT_FUNCTION_GROUP}" group. Remove the pattern that ` +
928
+ `moved it. (A Pages Router home page is also "/index": one file.)`);
929
+ }
930
+ const suggestions = [
931
+ ...new Set(misrouted.map((it) => suggestedPattern(it.url, edge))),
932
+ ];
933
+ return (`${head} Add ${suggestions.map((it) => `"${it}"`).join(", ")} to group ` +
934
+ `"${owner}"'s routes.`);
935
+ }
936
+ /**
937
+ * The group pattern that would route `url`, `undefined` when none can: a static
938
+ * path routes as itself, a dynamic one as the subtree above its first dynamic
939
+ * segment, and a data URL or `trailingSlash` form as the page it belongs to.
940
+ */
941
+ function suggestedPattern(url, edge) {
942
+ let path = stripBasePath(url, edge.basePath) ?? url;
943
+ const dataPrefix = `/_next/data/${edge.buildId}/`;
944
+ if (path.startsWith(dataPrefix) && path.endsWith(".json")) {
945
+ path = `/${path.slice(dataPrefix.length, -".json".length)}`;
946
+ path = path === "/index" ? "/" : path;
947
+ }
948
+ if (path.length > 1 && path.endsWith("/")) {
949
+ path = path.slice(0, -1);
950
+ }
951
+ const segments = path.split("/").filter(Boolean);
952
+ const firstDynamic = segments.findIndex((segment) => segment.startsWith("["));
953
+ if (segments.length === 0 || firstDynamic === 0) {
954
+ return undefined;
955
+ }
956
+ return firstDynamic === -1
957
+ ? path
958
+ : `/${segments.slice(0, firstDynamic).join("/")}${SUBTREE_SUFFIX}`;
959
+ }
960
+ /**
961
+ * Throw on a `next.config` rewrite whose source reaches one group and whose
962
+ * destination is packaged into another.
963
+ *
964
+ * A rewrite runs inside the function that received the request, so
965
+ * `/old/:path*` → `/new` with `/new/**` grouped and `/old` not sends `/old/x` to
966
+ * the default function, which rewrites it to a file it lacks.
967
+ *
968
+ * Only the rewrites whose destination is a literal path can be resolved to a
969
+ * file here; one built from the source's parameters (`/blog/:slug` →
970
+ * `/posts/:slug`) is skipped, as are external ones. The source is checked at the
971
+ * granularity of its literal prefix: each parameter stands in as a dynamic
972
+ * segment. Rewrites done by middleware (`NextResponse.rewrite`) are code, not
973
+ * config, and cannot be checked at all.
974
+ */
975
+ function assertRewritesStayInGroup(groupOfEntrypoint, behaviors, router) {
976
+ const { routing } = router;
977
+ const phases = [
978
+ [routing.beforeFiles, false],
979
+ // `afterFiles` and `fallback` only apply when no file matched the URL, so a
980
+ // source that is itself a route never reaches the destination.
981
+ [routing.afterFiles, true],
982
+ [routing.fallback, true],
983
+ ];
984
+ for (const [rules, yieldsToFiles] of phases) {
985
+ for (const rule of rules ?? []) {
986
+ const destination = literalDestination(rule.destination);
987
+ // Next.js's own interception rewrites are here too, on `Next-Url`;
988
+ // `reassignInterceptingFiles` has already put their files in place.
989
+ if (destination === undefined || isInterceptionTemplate(destination)) {
990
+ continue;
991
+ }
992
+ const file = resolveFile(destination, router);
993
+ if (file === undefined) {
994
+ continue;
995
+ }
996
+ const target = groupOfEntrypoint.get(file) ?? exports.DEFAULT_FUNCTION_GROUP;
997
+ for (const url of rewriteSourceUrls(rule.source)) {
998
+ if (yieldsToFiles && router.fileOfTemplate.has(url)) {
999
+ continue;
1000
+ }
1001
+ const behavior = edgeBehaviorFor(behaviors, url);
1002
+ const group = behavior?.group ?? exports.DEFAULT_FUNCTION_GROUP;
1003
+ if (group === target) {
1004
+ continue;
1005
+ }
1006
+ throw new Error(`${ERROR_PREFIX}The next.config rewrite from "${rule.source}" to ` +
1007
+ `"${rule.destination}" crosses groups: CloudFront sends "${url}" to ` +
1008
+ `${groupLabel(group)}` +
1009
+ (behavior ? ` (its pattern "${behavior.route}")` : "") +
1010
+ `, and Next.js then serves it with "${file}", which is packaged ` +
1011
+ `into ${groupLabel(target)}. A rewrite is applied inside the ` +
1012
+ `function that received the request, so its source and its ` +
1013
+ `destination have to be routed to the same group.`);
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+ /** A rewrite destination's pathname, `undefined` unless it is a literal local path. */
1019
+ function literalDestination(destination) {
1020
+ if (!destination?.startsWith("/")) {
1021
+ return undefined;
1022
+ }
1023
+ const pathname = destination.split(/[?#]/)[0];
1024
+ if (/[$:]/.test(pathname)) {
1025
+ return undefined;
1026
+ }
1027
+ return pathname.length > 1 ? pathname.replace(/\/$/, "") : pathname;
1028
+ }
1029
+ function fileOfTemplate(entries) {
1030
+ return new Map(entries
1031
+ .filter((entry) => !isInternalTemplate(entry.template))
1032
+ .map((entry) => [entry.template, entry.entrypointId]));
1033
+ }
1034
+ /**
1035
+ * The file Next.js serves `pathname` with: a template of that exact name, or
1036
+ * else the first of Next.js's own dynamic route rules that matches — matched
1037
+ * case-insensitively, as `resolveRoutes` does. `dynamicRoutes` is in Next.js's
1038
+ * priority order (static segment before `[param]` before `[...catchAll]`
1039
+ * before `[[...optional]]`), Pages Router data URLs included.
1040
+ */
1041
+ function resolveFile(pathname, { fileOfTemplate: files, routing }) {
1042
+ const exact = files.get(pathname);
1043
+ if (exact !== undefined) {
1044
+ return exact;
1045
+ }
1046
+ for (const route of routing.dynamicRoutes ?? []) {
1047
+ if (new RegExp(route.sourceRegex, "i").test(pathname)) {
1048
+ const template = route.destination?.split("?")[0];
1049
+ return template === undefined ? undefined : files.get(template);
1050
+ }
1051
+ }
1052
+ return undefined;
1053
+ }
1054
+ /**
1055
+ * The URL shapes a path-to-regexp rewrite source matches, as template-like
1056
+ * paths: each literal segment kept, each parameter replaced by `[name]`, and —
1057
+ * when the last one is optional (`:path*`, `:slug?`) — the path without it too.
1058
+ */
1059
+ function rewriteSourceUrls(source) {
1060
+ if (!source?.startsWith("/")) {
1061
+ return [];
1062
+ }
1063
+ const segments = [];
1064
+ let optionalFrom;
1065
+ for (const segment of source.split("/").slice(1)) {
1066
+ if (!/[:()*?+{}[\]]/.test(segment)) {
1067
+ segments.push(segment);
1068
+ continue;
1069
+ }
1070
+ optionalFrom = /^:\w+[*?]$/.test(segment) ? segments.length : undefined;
1071
+ segments.push(`[${/:(\w+)/.exec(segment)?.[1] ?? "param"}]`);
1072
+ }
1073
+ const urls = [`/${segments.join("/")}`];
1074
+ if (optionalFrom !== undefined) {
1075
+ urls.push(`/${segments.slice(0, optionalFrom).join("/")}`);
1076
+ }
1077
+ return urls;
1078
+ }
1079
+ function groupLabel(group) {
1080
+ return group === exports.DEFAULT_FUNCTION_GROUP
1081
+ ? `the "${exports.DEFAULT_FUNCTION_GROUP}" group`
1082
+ : `group "${group}"`;
1083
+ }
1084
+ function prefixBasePath(route, basePath) {
1085
+ return `${(0, base_path_1.basePathPrefix)(basePath)}${route}`;
1086
+ }
1087
+ /** `template` without `basePath` (`/` for the base itself), `undefined` if outside it. */
1088
+ function stripBasePath(template, basePath) {
1089
+ if (!basePath) {
1090
+ return template;
1091
+ }
1092
+ return (0, base_path_1.hasPathPrefix)(template, basePath)
1093
+ ? template.slice(basePath.length) || "/"
1094
+ : undefined;
1095
+ }
1096
+ function withBasePath(path, basePath) {
1097
+ return path === "/" ? basePath || "/" : `${basePath}${path}`;
1098
+ }
1099
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb24tZ3JvdXBzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FkYXB0ZXIvZnVuY3Rpb24tZ3JvdXBzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWtKQSx3REFJQztBQWFELHNEQVdDO0FBT0Qsd0RBdURDO0FBZ0pELG9EQXVJQztBQWlCRCx3Q0FzQkM7QUFtQkQsMENBc0NDO0FBcUhELDRDQW9CQztBQW9FRCx3REFXQztBQTN6QkQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCw0Q0FBMEM7QUFDMUMsa0RBQTBEO0FBQzFELGtEQUFtRTtBQUVuRTs7OztHQUlHO0FBQ1UsUUFBQSxzQkFBc0IsR0FBRyxTQUFTLENBQUM7QUFFaEQ7OztHQUdHO0FBQ1UsUUFBQSx1QkFBdUIsR0FBRyw0QkFBNEIsQ0FBQztBQWdHcEUsTUFBTSxZQUFZLEdBQUcsR0FBRyxzQkFBVSx1QkFBdUIsQ0FBQztBQUMxRCxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQztBQUN2QyxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUM7QUFDN0I7Ozs7Ozs7R0FPRztBQUNVLFFBQUEsb0JBQW9CLEdBQUcsMEJBQTBCLENBQUM7QUFFL0Q7Ozs7R0FJRztBQUNILFNBQWdCLHNCQUFzQixDQUNwQyxLQUF5QjtJQUV6QixPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsU0FBZ0IscUJBQXFCLENBQUMsSUFBYTtJQUNqRCxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3hDLE9BQU87SUFDVCxDQUFDO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FDYixHQUFHLFlBQVksdURBQXVEO1FBQ3BFLDJFQUEyRTtRQUMzRSx1RUFBdUU7UUFDdkUsd0VBQXdFO1FB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QUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHO1FBQ3hDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDaEIsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLElBQVksRUFBRSxRQUFnQjtJQUNsRCxPQUFPLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsUUFBUSxHQUFHLElBQUksRUFBRSxDQUFDO0FBQy9ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGBmdW5jdGlvbkdyb3Vwc2AgcmVzb2x1dGlvbjogdGhlIHJ1bGVzIHNoYXJlZCBieSBgbmV4dCBidWlsZGAgYW5kIHN5bnRoLlxuICpcbiAqIFNwbGl0dGluZyBzcGFucyB0d28gcHJvY2Vzc2VzLiBgb25CdWlsZENvbXBsZXRlYCBzdGFnZXMgb25lIGRlcGxveW1lbnQgdHJlZVxuICogcGVyIGdyb3VwIHdoaWxlIGBuZXh0IGJ1aWxkYCBpcyBzdGlsbCBydW5uaW5nOyB0aGUgY29uc3RydWN0cyB0dXJuIHRoZSBncm91cHNcbiAqIGludG8gQ2xvdWRGcm9udCBiZWhhdmlvcnMgb3IgQVBJIEdhdGV3YXkgcmVzb3VyY2VzIGF0IHN5bnRoLiBJZiB0aGUgdHdvXG4gKiBkaXNhZ3JlZSwgQ2xvdWRGcm9udCBzZW5kcyBhIHJlcXVlc3QgdG8gYSBmdW5jdGlvbiB3aG9zZSB6aXAgbGFja3MgaXRzXG4gKiBlbnRyeXBvaW50IOKAlCBzbyB0aGUgYnVpbGQgZGVjaWRlcyBib3RoLCBoZXJlLCBhbmQgcmVjb3JkcyB0aGUgYmVoYXZpb3JzIGl0XG4gKiBjaGVja2VkIGluIHRoZSBtYW5pZmVzdCBmb3Igc3ludGggdG8gZGVwbG95IGFzIHRoZXkgYXJlLiBTeW50aCBzdGlsbCBydW5zXG4gKiB7QGxpbmsgdmFsaWRhdGVGdW5jdGlvbkdyb3Vwc30sIHRvIGZhaWwgYmVmb3JlIGEgYG5leHQgYnVpbGRgIGl0IHdvdWxkXG4gKiBvdGhlcndpc2UgcGF5IGZvci5cbiAqXG4gKiBOb3RoaW5nIGluIHRoaXMgZmlsZSBpbXBvcnRzIGBhd3MtY2RrLWxpYmA6IGl0IGlzIGJ1bmRsZWQgaW50byB0aGUgYWRhcHRlciBieVxuICogZXNidWlsZC4gVGhlIHB1YmxpYyBKU0lJIHN0cnVjdCBjb25zdW1lcnMgYWN0dWFsbHkgd3JpdGUgKGBOZXh0anNGdW5jdGlvbkdyb3VwYCxcbiAqIHdoaWNoIGFkZHMgcGVyLWdyb3VwIGBvdmVycmlkZXNgKSBpcyBpbiBgc3JjL25leHRqcy1jb21wdXRlL25leHRqcy1mdW5jdGlvbnMudHNgXG4gKiBhbmQgaXMgc3RydWN0dXJhbGx5IGFzc2lnbmFibGUgdG8ge0BsaW5rIEZ1bmN0aW9uR3JvdXBTcGVjfS5cbiAqL1xuaW1wb3J0IHsgTE9HX1BSRUZJWCB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IEVSUk9SX1BBR0VfU1VGRklYRVMgfSBmcm9tIFwiLi4vcnVudGltZS9tYW5pZmVzdFwiO1xuaW1wb3J0IHsgYmFzZVBhdGhQcmVmaXgsIGhhc1BhdGhQcmVmaXggfSBmcm9tIFwiLi4vdXRpbHMvYmFzZS1wYXRoXCI7XG5cbi8qKlxuICogVGhlIGltcGxpY2l0IGdyb3VwIGV2ZXJ5IHVuYXNzaWduZWQgcm91dGUgZmFsbHMgaW50by4gUmVzZXJ2ZWQgYXMgYSBncm91cFxuICogbmFtZTogaXQgaXMgYWxzbyB0aGUgY29uc3RydWN0IGlkIHN1ZmZpeCBhbmQgdGhlIGZ1bmN0aW9uIHdob3NlIFVSTCBiYWNrcyB0aGVcbiAqIGRpc3RyaWJ1dGlvbidzIGRlZmF1bHQgYmVoYXZpb3IuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0ZVTkNUSU9OX0dST1VQID0gXCJkZWZhdWx0XCI7XG5cbi8qKlxuICogSG93IHRoZSByZXNvbHZlZCBncm91cHMgcmVhY2ggYG9uQnVpbGRDb21wbGV0ZWAsIHdoaWNoIGNhbm5vdCByZWFkIENESyBwcm9wcyDigJRcbiAqIGl0IHJ1bnMgaW5zaWRlIGBuZXh0IGJ1aWxkYC4gYENES19ORVhUSlNfSU5JVF9DQUNIRV9ESVJgIGlzIHRoZSBwcmVjZWRlbnQuXG4gKi9cbmV4cG9ydCBjb25zdCBGVU5DVElPTl9HUk9VUFNfRU5WX1ZBUiA9IFwiQ0RLX05FWFRKU19GVU5DVElPTl9HUk9VUFNcIjtcblxuLyoqIFRoZSBwYXJ0IG9mIGEgZ3JvdXAgdGhlIGJ1aWxkIHNpZGUgbmVlZHMuICovXG5leHBvcnQgaW50ZXJmYWNlIEZ1bmN0aW9uR3JvdXBTcGVjIHtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICByZWFkb25seSByb3V0ZXM6IHN0cmluZ1tdO1xufVxuXG4vKiogT25lIHJvdXRlIHRlbXBsYXRlIGFuZCB0aGUgZW50cnlwb2ludCBpdCBpbnZva2VzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSb3V0ZUVudHJ5IHtcbiAgLyoqIEJhc2VwYXRoLXByZWZpeGVkIHJvdXRlIHRlbXBsYXRlLCBleGFjdGx5IGFzIGBtYW5pZmVzdC5lbnRyeXBvaW50c2Aga2V5cyBpdC4gKi9cbiAgcmVhZG9ubHkgdGVtcGxhdGU6IHN0cmluZztcbiAgLyoqXG4gICAqIFdoYXQgaWRlbnRpZmllcyB0aGUgZW50cnlwb2ludDogdGhlIGJ1aWxkIHNpZGUgcGFzc2VzIGl0cyBgZmlsZVBhdGhgLCBzaW5jZVxuICAgKiB0aGF0IGlzIHdoYXQgZ2V0cyBzdGFnZWQuIFR3byB0ZW1wbGF0ZXMgc2hhcmluZyBvbmUgYXJlIG5ldmVyIHNwbGl0IGFwYXJ0LlxuICAgKi9cbiAgcmVhZG9ubHkgZW50cnlwb2ludElkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZW50cnlwb2ludCdzIGBBZGFwdGVyRW50cnlwb2ludFR5cGVgLiBPbmx5IGBcInBhZ2VcImAgY2hhbmdlcyBhbnl0aGluZzogYVxuICAgKiBQYWdlcyBSb3V0ZXIgcGFnZSBpcyBhbHNvIHJlcXVlc3RlZCBhdCBgL19uZXh0L2RhdGEvPGJ1aWxkSWQ+LzxwYWdlPi5qc29uYCxcbiAgICogc28gdGhhdCBVUkwgaGFzIHRvIHJlYWNoIHRoZSBwYWdlJ3MgZ3JvdXAgdG9vLlxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBPbmUgYmVoYXZpb3IgdGhlIGVkZ2Ugcm91dGVzIGEgZ3JvdXAgb24uIFRoZSBGdW5jdGlvbnMgcm9vdCBjb25zdHJ1Y3RzIGRlcGxveVxuICogZXhhY3RseSB0aGVzZSwgaW4gb3JkZXI6IGEgQ2xvdWRGcm9udCBiZWhhdmlvciBlYWNoLCBvciB0aGUgQVBJIEdhdGV3YXlcbiAqIHJlc291cmNlcyBmb3IgZWFjaCBkaXN0aW5jdCBgcm91dGVgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdyb3VwQmVoYXZpb3Ige1xuICByZWFkb25seSBncm91cDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGdyb3VwIHBhdHRlcm4gKGAvYmxvZy8qKmApIHRoZSBiZWhhdmlvciB3YXMgZ2VuZXJhdGVkIGZyb20sIG9yIHRoZVxuICAgKiBvcHRpb25hbCBjYXRjaC1hbGwgcGFyZW50IHtAbGluayByb3V0ZWRQYXR0ZXJuc30gYWRkZWQuXG4gICAqL1xuICByZWFkb25seSByb3V0ZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIENsb3VkRnJvbnQgcGF0aCBwYXR0ZXJuLCBiZWZvcmUgYmFzZVBhdGggYW5kIHdpdGhvdXQgYSBsZWFkaW5nIHNsYXNoXG4gICAqIChgYmxvZy8qYCwgYF9uZXh0L2RhdGEvPGJ1aWxkSWQ+L2Jsb2cvKmApLlxuICAgKi9cbiAgcmVhZG9ubHkgcGF0dGVybjogc3RyaW5nO1xufVxuXG4vKiogV2hhdCB7QGxpbmsgYXNzaWduUm91dGVzVG9Hcm91cHN9IGRlY2lkZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIEdyb3VwQXNzaWdubWVudCB7XG4gIC8qKiBHcm91cCBuYW1lIOKGkiB0aGUgdGVtcGxhdGVzIHBhY2thZ2VkIGludG8gaXQsIGBkZWZhdWx0YCBpbmNsdWRlZC4gKi9cbiAgcmVhZG9ubHkgdGVtcGxhdGVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG4gIC8qKlxuICAgKiBFdmVyeSBncm91cCBiZWhhdmlvciwgbW9zdCBzcGVjaWZpYyBmaXJzdDogdGhlIG9yZGVyIENsb3VkRnJvbnQgaGFzIHRvIHNlZVxuICAgKiB0aGVtIGluLCBzaW5jZSBpdCBzdG9wcyBhdCB0aGUgZmlyc3QgbWF0Y2guIFJlY29yZGVkIHJhdGhlciB0aGFuXG4gICAqIHJlY29tcHV0ZWQgYXQgc3ludGgsIHNvIHRoZSBiZWhhdmlvcnMgZGVwbG95ZWQgYXJlIHRoZSBvbmVzIHRoaXNcbiAgICogYXNzaWdubWVudCB3YXMgY2hlY2tlZCBhZ2FpbnN0LlxuICAgKi9cbiAgcmVhZG9ubHkgYmVoYXZpb3JzOiBHcm91cEJlaGF2aW9yW107XG59XG5cbi8qKiBXaGF0IHtAbGluayBhc3NpZ25Sb3V0ZXNUb0dyb3Vwc30gbmVlZHMgdG8ga25vdyBiZXNpZGVzIHRoZSByb3V0ZXMuICovXG5leHBvcnQgaW50ZXJmYWNlIEFzc2lnblJvdXRlc09wdGlvbnMge1xuICAvKiogYG5leHQuY29uZmlnYCBgYmFzZVBhdGhgLCB3aGljaCBldmVyeSBtYW5pZmVzdCB0ZW1wbGF0ZSBjYXJyaWVzLiAqL1xuICByZWFkb25seSBiYXNlUGF0aDogc3RyaW5nO1xuICAvKipcbiAgICogTmV4dC5qcydzIGJ1aWxkIElEIOKAlCB0aGUgc2VnbWVudCBpbiBgL19uZXh0L2RhdGEvPGJ1aWxkSWQ+L+KApmAgVVJMcywgd2hpY2ggaXNcbiAgICogYGN0eC5idWlsZElkYCBhbmQgYC5uZXh0L0JVSUxEX0lEYCwgbm90IGNkay1uZXh0anMncyBkZXBsb3ltZW50LXN1ZmZpeGVkXG4gICAqIG9uZS4gUmVxdWlyZWQgd2hlbiBhbnkgZW50cnkgaXMgYSBQYWdlcyBSb3V0ZXIgcGFnZS5cbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkSWQ/OiBzdHJpbmc7XG4gIC8qKiBgbmV4dC5jb25maWdgIGB0cmFpbGluZ1NsYXNoYC4gKi9cbiAgcmVhZG9ubHkgdHJhaWxpbmdTbGFzaD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBgY3R4LnJvdXRpbmdgOiB0aGUgYG5leHQuY29uZmlnYCByZXdyaXRlcyB3aG9zZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uXG4gICAqIGhhdmUgdG8gbGFuZCBpbiBvbmUgZ3JvdXAsIGFuZCBOZXh0LmpzJ3Mgb3duIGR5bmFtaWMgcm91dGUgb3JkZXIsIHdoaWNoXG4gICAqIGRlY2lkZXMgdGhlIHRlbXBsYXRlIGEgVVJMIHJlc29sdmVzIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgcm91dGluZzogUm91dGluZ1J1bGVzO1xufVxuXG4vKiogT25lIGBjdHgucm91dGluZ2AgcmV3cml0ZSwgcmVkdWNlZCB0byB0aGUgZmllbGRzIHJlYWQgaGVyZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmV3cml0ZVJ1bGUge1xuICAvKiogVGhlIHBhdGgtdG8tcmVnZXhwIHNvdXJjZSwgYmFzZVBhdGggaW5jbHVkZWQgKGAvb2xkLzpwYXRoKmApLiAqL1xuICByZWFkb25seSBzb3VyY2U/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlc3RpbmF0aW9uPzogc3RyaW5nO1xufVxuXG4vKiogVGhlIHBhcnQgb2YgYGN0eC5yb3V0aW5nYCB7QGxpbmsgYXNzaWduUm91dGVzVG9Hcm91cHN9IHJlYWRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSb3V0aW5nUnVsZXMge1xuICByZWFkb25seSBiZWZvcmVGaWxlcz86IHJlYWRvbmx5IFJld3JpdGVSdWxlW107XG4gIHJlYWRvbmx5IGFmdGVyRmlsZXM/OiByZWFkb25seSBSZXdyaXRlUnVsZVtdO1xuICByZWFkb25seSBmYWxsYmFjaz86IHJlYWRvbmx5IFJld3JpdGVSdWxlW107XG4gIC8qKiBOZXh0LmpzJ3Mgb3duIHRlbXBsYXRlIG1hdGNoZXJzLCB1c2VkIHRvIHJlc29sdmUgYSByZXdyaXRlJ3MgZGVzdGluYXRpb24uICovXG4gIHJlYWRvbmx5IGR5bmFtaWNSb3V0ZXM/OiByZWFkb25seSB7XG4gICAgcmVhZG9ubHkgc291cmNlUmVnZXg6IHN0cmluZztcbiAgICByZWFkb25seSBkZXN0aW5hdGlvbj86IHN0cmluZztcbiAgfVtdO1xufVxuXG5jb25zdCBFUlJPUl9QUkVGSVggPSBgJHtMT0dfUFJFRklYfSBcXGBmdW5jdGlvbkdyb3Vwc1xcYDogYDtcbmNvbnN0IE5BTUVfUEFUVEVSTiA9IC9eW2EtekEtWjAtOS1dKyQvO1xuY29uc3QgU1VCVFJFRV9TVUZGSVggPSBcIi8qKlwiO1xuLyoqXG4gKiBUaGUgbGl0ZXJhbCBjaGFyYWN0ZXJzIGEgQ2xvdWRGcm9udCBwYXRoIHBhdHRlcm4gbWF5IGNvbnRhaW46IGl0cyBhbHBoYWJldFxuICogKGBBLVogYS16IDAtOSBfIC0gLiAqICQgLyB+IFwiICcgQCA6ICtgIGFuZCBgJmApIGxlc3MgdGhlIHR3byB3aWxkY2FyZHMsIHdoaWNoXG4gKiBgdmFsaWRhdGVSb3V0ZVBhdHRlcm5gIG9ubHkgYWNjZXB0cyBhcyBhIHRyYWlsaW5nIGAvKipgLiBgbmV4dGpzLWRpc3RyaWJ1dGlvbi50c2BcbiAqIGFkZHMgdGhlIHdpbGRjYXJkcyBiYWNrIHRvIGVuY29kZSBgcHVibGljL2AgbmFtZXMuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvRG93bmxvYWREaXN0VmFsdWVzQ2FjaGVCZWhhdmlvci5odG1sI0Rvd25sb2FkRGlzdFZhbHVlc1BhdGhQYXR0ZXJuXG4gKi9cbmV4cG9ydCBjb25zdCBQQVRIX1BBVFRFUk5fTElURVJBTCA9IC9bYS16QS1aMC05X1xcLS4kL35cIidAOismXS87XG5cbi8qKlxuICogUmVhZCB7QGxpbmsgRlVOQ1RJT05fR1JPVVBTX0VOVl9WQVJ9LiBgdW5kZWZpbmVkYCDigJQgbm90IHRoZSBlbXB0eSBhcnJheSDigJQgd2hlblxuICogdW5zZXQsIGJlY2F1c2UgXCJubyBzcGxpdHRpbmdcIiBhbmQgXCJzcGxpdCBpbnRvIG5vdGhpbmdcIiBhcmUgZGlmZmVyZW50IHJlcXVlc3RzXG4gKiBhbmQgb25seSB0aGUgZmlyc3QgaXMgdmFsaWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUZ1bmN0aW9uR3JvdXBzRW52KFxuICB2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuKTogRnVuY3Rpb25Hcm91cFNwZWNbXSB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB2YWx1ZSA/IEpTT04ucGFyc2UodmFsdWUpIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFNwbGl0dGluZyBhbmQgYGkxOG5gIGFyZSBtdXR1YWxseSBleGNsdXNpdmUsIGFuZCBpdCBpcyBhIENsb3VkRnJvbnQgbGltaXRcbiAqIGFnYWluLlxuICpcbiAqIFdpdGggYGkxOG5gIGNvbmZpZ3VyZWQsIGV2ZXJ5IHJvdXRlIHRlbXBsYXRlIGlzIGxvY2FsZS1wcmVmaXhlZFxuICogKGAvZW4vcHJpY2luZ2AsIGAvZGUvcHJpY2luZ2ApLCBzbyBob25vcmluZyBhIGAvcHJpY2luZ2AgZ3JvdXAgd291bGQgdGFrZSBvbmVcbiAqIGJlaGF2aW9yICpwZXIgbG9jYWxlIHBlciBwYXR0ZXJuKiDigJQgYSBidWRnZXQgb2YgNzUgYmVoYXZpb3JzIHNwZW50IGluIGEgaGFuZGZ1bFxuICogb2Ygcm91dGVzLiBUaGUgYWx0ZXJuYXRpdmUsIGEgYCpgIGluIHRoZSBsb2NhbGUgcG9zaXRpb24sIG1hdGNoZXMgYW55IGZpcnN0XG4gKiBzZWdtZW50IGFuZCB3b3VsZCBjYXB0dXJlIHJvdXRlcyBiZWxvbmdpbmcgdG8gb3RoZXIgZ3JvdXBzLiBOZWl0aGVyIGlzXG4gKiBzb21ldGhpbmcgdG8gZG8gc2lsZW50bHksIHNvIHJlZnVzZSBpbnN0ZWFkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0Tm9JMThuU3BsaXR0aW5nKGkxOG46IHVua25vd24pOiB2b2lkIHtcbiAgaWYgKGkxOG4gPT09IG51bGwgfHwgaTE4biA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgJHtFUlJPUl9QUkVGSVh9XFxgZnVuY3Rpb25Hcm91cHNcXGAgY2Fubm90IGJlIGNvbWJpbmVkIHdpdGggXFxgaTE4blxcYC4gYCArXG4gICAgICBgV2l0aCBpMThuIGV2ZXJ5IHJvdXRlIGlzIGxvY2FsZS1wcmVmaXhlZCwgc28gcm91dGluZyBhIGdyb3VwIGF0IHRoZSBlZGdlIGAgK1xuICAgICAgYHdvdWxkIG5lZWQgb25lIENsb3VkRnJvbnQgYmVoYXZpb3IgcGVyIGxvY2FsZSBwZXIgcGF0dGVybiwgYWdhaW5zdCBhIGAgK1xuICAgICAgYHF1b3RhIG9mIDc1IGZvciB0aGUgd2hvbGUgZGlzdHJpYnV0aW9uLiBEZXBsb3kgb25lIGZ1bmN0aW9uIGZvciBldmVyeSBgICtcbiAgICAgIGByb3V0ZSAob21pdCBcXGBmdW5jdGlvbkdyb3Vwc1xcYCksIG9yIGRyb3AgXFxgaTE4blxcYC5gLFxuICApO1xufVxuXG4vKipcbiAqIFJlamVjdCBldmVyeXRoaW5nIHRoYXQgY2Fubm90IGJlIGhvbm9yZWQsIGF0IHRoZSBlYXJsaWVzdCBvZiB0aGUgdHdvIHNpZGVzIHRvXG4gKiBzZWUgaXQuIENhbGxlZCBmcm9tIGJvdGgsIGJlY2F1c2UgZWl0aGVyIGNhbiBiZSB0aGUgZmlyc3Q6IGBuZXh0IGJ1aWxkYCBydW5zXG4gKiBiZWZvcmUgc3ludGggcmVhZHMgdGhlIG1hbmlmZXN0LCBidXQgYSBgc2tpcEJ1aWxkOiB0cnVlYCBjb25zdW1lciBpbnZlcnRzIHRoYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFxuICBncm91cHM6IHJlYWRvbmx5IEZ1bmN0aW9uR3JvdXBTcGVjW10sXG4pOiB2b2lkIHtcbiAgaWYgKGdyb3Vwcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtFUlJPUl9QUkVGSVh9XFxgZnVuY3Rpb25Hcm91cHNcXGAgaXMgYW4gZW1wdHkgYXJyYXkuIE9taXQgdGhlIHByb3AgYCArXG4gICAgICAgIGBlbnRpcmVseSB0byBkZXBsb3kgb25lIGZ1bmN0aW9uIGZvciBldmVyeSByb3V0ZSwgd2hpY2ggaXMgdGhlIGRlZmF1bHQuYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3Qgc2Vlbk5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGNvbnN0IHBhdHRlcm5Pd25lciA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG5cbiAgZm9yIChjb25zdCBncm91cCBvZiBncm91cHMpIHtcbiAgICBpZiAoZ3JvdXAubmFtZSA9PT0gREVGQVVMVF9GVU5DVElPTl9HUk9VUCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtFUlJPUl9QUkVGSVh9XCIke0RFRkFVTFRfRlVOQ1RJT05fR1JPVVB9XCIgaXMgYSByZXNlcnZlZCBncm91cCBuYW1lOiBgICtcbiAgICAgICAgICBgaXQgaXMgdGhlIGltcGxpY2l0IGdyb3VwIGV2ZXJ5IHVuYXNzaWduZWQgcm91dGUgZmFsbHMgaW50by5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFOQU1FX1BBVFRFUk4udGVzdChncm91cC5uYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtFUlJPUl9QUkVGSVh9R3JvdXAgbmFtZSBcIiR7Z3JvdXAubmFtZX1cIiBtdXN0IG1hdGNoIGAgK1xuICAgICAgICAgIGAke05BTUVfUEFUVEVSTn0g4oCUIGl0IGJlY29tZXMgYSBjb25zdHJ1Y3QgaWQgYW5kIHBhcnQgb2YgYSBMYW1iZGEgYCArXG4gICAgICAgICAgYGZ1bmN0aW9uIG5hbWUuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChzZWVuTmFtZXMuaGFzKGdyb3VwLm5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke0VSUk9SX1BSRUZJWH1Ud28gZ3JvdXBzIGFyZSBib3RoIG5hbWVkIFwiJHtncm91cC5uYW1lfVwiLmAsXG4gICAgICApO1xuICAgIH1cbiAgICBzZWVuTmFtZXMuYWRkKGdyb3VwLm5hbWUpO1xuXG4gICAgaWYgKGdyb3VwLnJvdXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7RVJST1JfUFJFRklYfUdyb3VwIFwiJHtncm91cC5uYW1lfVwiIG93bnMgbm8gcm91dGVzLiBFdmVyeSBncm91cCBpcyBhIGAgK1xuICAgICAgICAgIGBMYW1iZGEgZnVuY3Rpb24sIHNvIGFuIGVtcHR5IG9uZSB3b3VsZCBkZXBsb3kgYW5kIG5ldmVyIGJlIHJlYWNoZWQuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGZvciAoY29uc3Qgcm91dGUgb2YgZ3JvdXAucm91dGVzKSB7XG4gICAgICB2YWxpZGF0ZVJvdXRlUGF0dGVybihyb3V0ZSwgZ3JvdXAubmFtZSk7XG4gICAgICBjb25zdCBvd25lciA9IHBhdHRlcm5Pd25lci5nZXQocm91dGUpO1xuICAgICAgaWYgKG93bmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGAke0VSUk9SX1BSRUZJWH1QYXR0ZXJuIFwiJHtyb3V0ZX1cIiBhcHBlYXJzIGluIGJvdGggZ3JvdXAgXCIke293bmVyfVwiIGAgK1xuICAgICAgICAgICAgYGFuZCBncm91cCBcIiR7Z3JvdXAubmFtZX1cIi4gQSByb3V0ZSBjYW4gb25seSBiZSBwYWNrYWdlZCBpbnRvIG9uZSBgICtcbiAgICAgICAgICAgIGBmdW5jdGlvbi4gKE92ZXJsYXBwaW5nLWJ1dC1kaWZmZXJlbnQgcGF0dGVybnMgYXJlIGZpbmU6IFwiL2FwaS8qKlwiIGAgK1xuICAgICAgICAgICAgYGluIG9uZSBncm91cCBhbmQgXCIvYXBpL3JlcG9ydHMvKipcIiBpbiBhbm90aGVyIHJlc29sdmVzIGAgK1xuICAgICAgICAgICAgYGxvbmdlc3QtZmlyc3QuKWAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBwYXR0ZXJuT3duZXIuc2V0KHJvdXRlLCBncm91cC5uYW1lKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBBIHBhdHRlcm4gaXMgYW4gZXhhY3Qgc3RhdGljIHBhdGggKGAvcHJpY2luZ2ApIG9yIGEgc3VidHJlZSAoYC9hcGkvcmVwb3J0cy8qKmApLlxuICpcbiAqICoqRHluYW1pYyBzZWdtZW50cyBhcmUgcmVqZWN0ZWQqKiwgYW5kIHRoZSByZWFzb24gaXMgQ2xvdWRGcm9udCByYXRoZXIgdGhhblxuICogYW55dGhpbmcgYWJvdXQgTmV4dC5qcy4gUGF0dGVybnMgYmVjb21lIGJlaGF2aW9yIHBhdGggcGF0dGVybnMsIGFuZCBDbG91ZEZyb250XG4gKiBzdXBwb3J0cyBvbmx5IGAqYCBhbmQgYD9gLCBzbyBgL2Rhc2hib2FyZC9baWRdYCBjb3VsZCBvbmx5IGV2ZXIgZGVwbG95IGFzXG4gKiBgL2Rhc2hib2FyZC8qYCDigJQgd2hpY2ggYWxzbyBtYXRjaGVzIGAvZGFzaGJvYXJkL3NldHRpbmdzYCBhbmRcbiAqIGAvZGFzaGJvYXJkL2EvYi9jYC4gSWYgdGhvc2UgYXJlIGluIGFub3RoZXIgZ3JvdXAsIENsb3VkRnJvbnQgcm91dGVzIHRoZW0gdG8gYVxuICogZnVuY3Rpb24gd2hvc2UgemlwIGxhY2tzIHRoZWlyIGVudHJ5cG9pbnQ6IGEgY3Jhc2ggb24gYSByb3V0ZSB0aGUgY29uc3VtZXJcbiAqIGV4cGxpY2l0bHkgYXNzaWduZWQgZWxzZXdoZXJlLiBBY2NlcHRpbmcgYSBzeW50YXggd2hvc2UgZ3JhbnVsYXJpdHkgY2Fubm90IGJlXG4gKiBob25vcmVkIHdvdWxkIGJlIHdvcnNlIHRoYW4gcmVqZWN0aW5nIGl0LlxuICpcbiAqIFRoZSByZXN0cmljdGlvbiBjb3N0cyBub3RoaW5nIHRoYXQgd2FzIGFjaGlldmFibGUgYW55d2F5LiBgL2Rhc2hib2FyZC8qKmAg4oaSXG4gKiBgL2Rhc2hib2FyZC8qYCBpcyB0aGUgc2FtZSBVUkwgc3BhY2UgZXhhY3RseSwgYW5kIGlzb2xhdGluZyBvbmUgaGVhdnkgZHluYW1pY1xuICogcm91dGUgc3RpbGwgd29ya3MgYXMgYSBzdWJ0cmVlOiBgL2FwaS9yZXBvcnQvKipgIGNvdmVycyBgL2FwaS9yZXBvcnQvW2lkXWAuXG4gKlxuICogYE5leHRqc1JlZ2lvbmFsRnVuY3Rpb25zYCBnZXRzIHRoZSBzYW1lIHJlc3RyaWN0aW9uIGV2ZW4gdGhvdWdoIEFQSSBHYXRld2F5XG4gKiBSRVNUIGNvdWxkIGV4cHJlc3MgYC97aWR9YCBwcmVjaXNlbHkg4oCUIHNvIHRoYXQgc3dpdGNoaW5nIGRlcGxveW1lbnQgdHlwZSAodG9cbiAqIFJlZ2lvbmFsIGZvciBHb3ZDbG91ZCwgc2F5KSBuZXZlciBzaWxlbnRseSBjaGFuZ2VzIGhvdyByb3V0ZXMgYXJlIGdyb3VwZWQuXG4gKiBUaGF0IG9uZSBpcyBhIGNvbnNpc3RlbmN5IGNob2ljZSwgbm90IGEgdGVjaG5pY2FsIGxpbWl0LlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVJvdXRlUGF0dGVybihyb3V0ZTogc3RyaW5nLCBncm91cE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCB3aGVyZSA9IGBHcm91cCBcIiR7Z3JvdXBOYW1lfVwiIHBhdHRlcm4gXCIke3JvdXRlfVwiYDtcbiAgaWYgKCFyb3V0ZS5zdGFydHNXaXRoKFwiL1wiKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGAke0VSUk9SX1BSRUZJWH0ke3doZXJlfSBtdXN0IHN0YXJ0IHdpdGggXCIvXCIuIFBhdHRlcm5zIGFyZSBVUkwgcGF0aHMgYXMgYCArXG4gICAgICAgIGB0aGUgYnJvd3NlciByZXF1ZXN0cyB0aGVtLmAsXG4gICAgKTtcbiAgfVxuICAvLyBgL2luZGV4YCBpcyBkZWxpYmVyYXRlbHkgYWxsb3dlZC4gRm9yIHRoZSBBcHAgUm91dGVyIGl0IGlzIGEgcmVhbCByb3V0ZSBvZlxuICAvLyBpdHMgb3duIChgYXBwL2luZGV4L3BhZ2UudHN4YCksIHdoaWNoIGByb3V0YWJsZVBhdGhuYW1lc2Aga2VlcHMgYXBhcnQgZnJvbVxuICAvLyBgL2AuIEZvciB0aGUgUGFnZXMgUm91dGVyIGl0IGlzIHRoZSBob21lIHBhZ2UgdW5kZXIgdGhlIG5hbWUgYG5leHQgYnVpbGRgXG4gIC8vIHJlcG9ydHMgaXQgYnksIG9uZSBlbnRyeXBvaW50IHJlZ2lzdGVyZWQgdW5kZXIgYC9gIGFzIHdlbGwg4oCUIGFuZCBncm91cGluZ1xuICAvLyB0aGF0IHdvdWxkIGxlYXZlIGAvYCBvbiB0aGUgZGVmYXVsdCBiZWhhdmlvciB3aXRoIGEgZnVuY3Rpb24gdGhhdCBsYWNrcyB0aGVcbiAgLy8gZmlsZS4gT25seSB0aGUgYXNzaWdubWVudCBjYW4gdGVsbCB0aGUgdHdvIGFwYXJ0LCBhbmQgaXRzIGNvdmVyYWdlIGNoZWNrXG4gIC8vIChgYXNzZXJ0RWRnZVJlYWNoZXNFdmVyeUZpbGVgKSByZWplY3RzIHRoZSBzZWNvbmQuXG4gIGlmIChyb3V0ZSA9PT0gXCIvXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtFUlJPUl9QUkVGSVh9JHt3aGVyZX0gY2Fubm90IGJlIHJvdXRlZC4gQ2xvdWRGcm9udCBoYXMgbm8gcGF0aCBgICtcbiAgICAgICAgYHBhdHRlcm4gdGhhdCBtYXRjaGVzIG9ubHkgXCIvXCIg4oCUIHRoZSBkZWZhdWx0IGJlaGF2aW9yIHNlcnZlcyBpdCDigJQgc28gdGhlIGAgK1xuICAgICAgICBgaG9tZSBwYWdlIGFsd2F5cyBiZWxvbmdzIHRvIHRoZSBcIiR7REVGQVVMVF9GVU5DVElPTl9HUk9VUH1cIiBncm91cC4gYCArXG4gICAgICAgIGBHcm91cCB0aGUgcm91dGVzIGFyb3VuZCBpdCBpbnN0ZWFkLmAsXG4gICAgKTtcbiAgfVxuICAvLyBgL19uZXh0L+KApmAgaXMgTmV4dCdzIG93biBVUkwgc3BhY2Ug4oCUIGJ1aWxkIGFzc2V0cywgYC9fbmV4dC9pbWFnZWAsIGFuZCB0aGVcbiAgLy8gUGFnZXMgUm91dGVyIGRhdGEgcm91dGVzIOKAlCBhbmQgZWFjaCBoYXMgaXRzIGJlaGF2aW9yIGFscmVhZHk6IHRoZSBkYXRhIHJvdXRlXG4gIC8vIG9mIGEgZ3JvdXBlZCBwYWdlIGZvbGxvd3MgaXQgKHNlZSBgcGF0aFBhdHRlcm5zRm9yYCksIGFuZCBhIGBfbmV4dC8qYCBiZWhhdmlvclxuICAvLyB3b3VsZCBjb21wZXRlIHdpdGggdGhlIHN0YXRpYy1hc3NldCBhbmQgaW1hZ2Ugb25lcyBmb3IgZXZlcnl0aGluZyBlbHNlLlxuICBpZiAocm91dGUgPT09IFwiL19uZXh0XCIgfHwgcm91dGUuc3RhcnRzV2l0aChcIi9fbmV4dC9cIikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtFUlJPUl9QUkVGSVh9JHt3aGVyZX0gaXMgdW5kZXIgXCIvX25leHRcIiwgd2hpY2ggTmV4dC5qcyByZXNlcnZlcyBmb3IgYCArXG4gICAgICAgIGBidWlsZCBhc3NldHMsIGltYWdlIG9wdGltaXphdGlvbiBhbmQgZGF0YSByb3V0ZXMuIEEgUGFnZXMgUm91dGVyIGAgK1xuICAgICAgICBgcGFnZSdzIFwiL19uZXh0L2RhdGEv4oCmXCIgcm91dGUgZm9sbG93cyB0aGUgcGFnZSBpbnRvIGl0cyBncm91cCwgc28gYCArXG4gICAgICAgIGBncm91cCB0aGUgcGFnZSBpdHNlbGYgaW5zdGVhZC5gLFxuICAgICk7XG4gIH1cbiAgaWYgKHJvdXRlID09PSBTVUJUUkVFX1NVRkZJWCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGAke0VSUk9SX1BSRUZJWH0ke3doZXJlfSB3b3VsZCBvd24gZXZlcnkgcm91dGUsIGxlYXZpbmcgdGhlIGRlZmF1bHQgYCArXG4gICAgICAgIGBncm91cCBlbXB0eS4gU3BsaXR0aW5nIGV4aXN0cyB0byBkaXZpZGUgcm91dGVzIGJldHdlZW4gZnVuY3Rpb25zOyBgICtcbiAgICAgICAgYG9taXQgXFxgZnVuY3Rpb25Hcm91cHNcXGAgdG8gZGVwbG95IHRoZW0gYWxsIGluIG9uZS5gLFxuICAgICk7XG4gIH1cbiAgaWYgKC9bW1xcXV0vLnRlc3Qocm91dGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7RVJST1JfUFJFRklYfSR7d2hlcmV9IGNvbnRhaW5zIGEgZHluYW1pYyBzZWdtZW50LiBQYXR0ZXJucyBiZWNvbWUgYCArXG4gICAgICAgIGBDbG91ZEZyb250IGJlaGF2aW9yIHBhdGggcGF0dGVybnMsIHdoaWNoIHN1cHBvcnQgb25seSBcIipcIiBhbmQgXCI/XCIsIHNvIGAgK1xuICAgICAgICBgXCIke3JvdXRlfVwiIGNvdWxkIG9ubHkgZGVwbG95IGFzIGEgd2lsZGNhcmQgdGhhdCBhbHNvIGNhcHR1cmVzIGl0cyBgICtcbiAgICAgICAgYHNpYmxpbmdzLiBVc2UgYSBzdWJ0cmVlIGluc3RlYWQ6IFwiL2Jsb2cvKipcIiBvd25zIFwiL2Jsb2cvW3NsdWddXCIuYCxcbiAgICApO1xuICB9XG4gIGlmICgvXFwoKC4qKVxcKS8udGVzdChyb3V0ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtFUlJPUl9QUkVGSVh9JHt3aGVyZX0gY29udGFpbnMgYSByb3V0ZSBncm91cCBzZWdtZW50LiBSb3V0ZSBncm91cHMgYCArXG4gICAgICAgIGBsaWtlIFwiKG1hcmtldGluZylcIiBvcmdhbml6ZSBmaWxlcyBhbmQgbmV2ZXIgYXBwZWFyIGluIGEgVVJMLCBzbyB0aGV5IGAgK1xuICAgICAgICBgY2Fubm90IGJlIHJvdXRlZCBvbi4gVXNlIHRoZSBVUkwgcGF0aCB0aGUgcm91dGUgaXMgc2VydmVkIGF0LmAsXG4gICAgKTtcbiAgfVxuICBjb25zdCB3aXRob3V0U3VidHJlZSA9IHJvdXRlLmVuZHNXaXRoKFNVQlRSRUVfU1VGRklYKVxuICAgID8gcm91dGUuc2xpY2UoMCwgLVNVQlRSRUVfU1VGRklYLmxlbmd0aClcbiAgICA6IHJvdXRlO1xuICBpZiAoL1sqP10vLnRlc3Qod2l0aG91dFN1YnRyZWUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7RVJST1JfUFJFRklYfSR7d2hlcmV9IGNvbnRhaW5zIGEgd2lsZGNhcmQgc29tZXdoZXJlIG90aGVyIHRoYW4gYSBgICtcbiAgICAgICAgYHRyYWlsaW5nIFwiLyoqXCIuIFRoZSBvbmx5IHR3byBmb3JtcyBhcmUgYW4gZXhhY3QgcGF0aCAoXCIvcHJpY2luZ1wiKSBhbmQgYCArXG4gICAgICAgIGBhIHN1YnRyZWUgKFwiL2FwaS9yZXBvcnRzLyoqXCIpLmAsXG4gICAgKTtcbiAgfVxuICBpZiAocm91dGUuaW5jbHVkZXMoXCIvL1wiKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtFUlJPUl9QUkVGSVh9JHt3aGVyZX0gY29udGFpbnMgYW4gZW1wdHkgcGF0aCBzZWdtZW50LmApO1xuICB9XG4gIC8vIEEgcm91dGUgTmV4dC5qcyBzZXJ2ZXMgY2FuIHN0aWxsIGhvbGQgYSBjaGFyYWN0ZXIgbm8gcGF0aCBwYXR0ZXJuIGNhbjpcbiAgLy8gYGFwcC/DvGJlci9wYWdlLnRzeGAsIGBhcHAvYSBiL3BhZ2UudHN4YCwgYGFwcC9hLGIvcGFnZS50c3hgIGFsbCBidWlsZCwgYW5kXG4gIC8vIHRoZSBwYXR0ZXJuIHBhc3NlcyBldmVyeSBjaGVjayBhYm92ZS4gYHBhdGhQYXR0ZXJuc0ZvcmAgY29waWVzIGl0IHZlcmJhdGltLFxuICAvLyBzbyBpdCByZWFjaGVkIGBhZGRCZWhhdmlvcmAgdW50b3VjaGVkIGFuZCB3YXMgbGVmdCBmb3IgQ2xvdWRGcm9udCB0byByZWplY3QsXG4gIC8vIGluIGFuIGVycm9yIG5hbWluZyBuZWl0aGVyIHRoZSBncm91cCBub3IgdGhlIHJvdXRlLiBUaGUgYHB1YmxpYy9gXG4gIC8vIHdvcmthcm91bmQsIG9uZSBgP2AgcGVyIFVURi04IGJ5dGUsIGlzIG5vdCBhdmFpbGFibGUgaGVyZTogYD9gIG1hdGNoZXMgKmFueSpcbiAgLy8gYnl0ZSwgc28gYC/DvGJlcmAgd291bGQgZGVwbG95IGFzIGAvPz9iZXJgIGFuZCBhbHNvIHNlbmQgYC94eWJlcmAgdG8gdGhpc1xuICAvLyBncm91cCdzIGZ1bmN0aW9uLCB3aG9zZSB6aXAgbGFja3MgaXRzIGVudHJ5cG9pbnQuIFRoYXQgaXMgdGhlIHNpYmxpbmcgY2FwdHVyZVxuICAvLyBkeW5hbWljIHNlZ21lbnRzIGFyZSByZWplY3RlZCBmb3IsIHNvIHRoZSBzYW1lIGFuc3dlciBhcHBsaWVzLlxuICBjb25zdCBpbnZhbGlkID0gWy4uLm5ldyBTZXQod2l0aG91dFN1YnRyZWUpXS5maWx0ZXIoXG4gICAgKGNoYXIpID0+ICFQQVRIX1BBVFRFUk5fTElURVJBTC50ZXN0KGNoYXIpLFxuICApO1xuICBpZiAoaW52YWxpZC5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7RVJST1JfUFJFRklYfSR7d2hlcmV9IGNvbnRhaW5zIGAgK1xuICAgICAgICBgJHtpbnZhbGlkLm1hcCgoY2hhcikgPT4gSlNPTi5zdHJpbmdpZnkoY2hhcikpLmpvaW4oXCIsIFwiKX0sIHdoaWNoIGEgYCArXG4gICAgICAgIGBDbG91ZEZyb250IGJlaGF2aW9yIHBhdGggcGF0dGVybiBjYW5ub3QgY29udGFpbiAoYWxsb3dlZDogQS1aIGEteiAwLTkgYCArXG4gICAgICAgIGBfIC0gLiAkIC8gfiBcIiAnIEAgOiArICYpLiBFc2NhcGluZyBpdCB3aXRoIFwiP1wiIHdvdWxkIGFsc28gbWF0Y2ggb3RoZXIgYCArXG4gICAgICAgIGByb3V0ZXMgb2YgdGhlIHNhbWUgbGVuZ3RoLiBVc2UgYSBzdWJ0cmVlIG9uIGEgcGFyZW50IHNlZ21lbnQgd2hvc2UgYCArXG4gICAgICAgIGBuYW1lIGlzIHBsYWluIEFTQ0lJIGluc3RlYWQ6IFwiL2ludGwvKipcIiBvd25zIFwiL2ludGwvw7xiZXJcIi5gLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBTcGxpdCBldmVyeSByb3V0ZSB0ZW1wbGF0ZSBhY3Jvc3MgdGhlIGdyb3VwcywgbG9uZ2VzdCBtYXRjaGluZyBwYXR0ZXJuIGZpcnN0LFxuICogdGhlbiBwcm92ZSB0aGF0IHRoZSBlZGdlIHJvdXRlcyBldmVyeSBVUkwgZWFjaCBmaWxlIHNlcnZlcyB0byB0aGUgZ3JvdXAgdGhhdFxuICogZmlsZSB3YXMgcGFja2FnZWQgaW50by5cbiAqXG4gKiBJdHMgYHRlbXBsYXRlc2AgYXJlIGtleWVkIGJ5IGdyb3VwIG5hbWUgYW5kIGFsd2F5cyBjb250YWluXG4gKiB7QGxpbmsgREVGQVVMVF9GVU5DVElPTl9HUk9VUH0sIHNvIGNhbGxlcnMgY2FuIGl0ZXJhdGUgdGhlbSBhcyB0aGUgY29tcGxldGUgc2V0XG4gKiBvZiBmdW5jdGlvbnMgdG8gZGVwbG95LiBUaGUgZGVmYXVsdCBncm91cCBpcyBhbGxvd2VkIHRvIGJlIGVtcHR5IG9mICp0ZW1wbGF0ZXMqXG4gKiDigJQgaXQgc3RpbGwgc2VydmVzIGAvX25leHQvaW1hZ2VgLCBhbnkgc3RhdGljIGZpbGUsIGFuZCBhbnl0aGluZyB0aGVcbiAqIGRpc3RyaWJ1dGlvbidzIGNhdGNoLWFsbCBiZWhhdmlvciBzZW5kcyBpdC5cbiAqXG4gKiBgYmFzZVBhdGhgIGlzIHByZXBlbmRlZCB0byBlYWNoIHBhdHRlcm4gYmVmb3JlIG1hdGNoaW5nLCBiZWNhdXNlIG1hbmlmZXN0XG4gKiB0ZW1wbGF0ZXMgYXJlIGJhc2VQYXRoLXByZWZpeGVkIGFuZCBjb25zdW1lcnMgd3JpdGUgdGhlIHJvdXRlcyB0aGVpciBhcHBcbiAqIGRlY2xhcmVzLlxuICpcbiAqIFBhY2thZ2luZyBtYXRjaGVzIHBhdHRlcm5zIGFnYWluc3QgKnRlbXBsYXRlcyosIGJ1dCBDbG91ZEZyb250IHJvdXRlcyAqVVJMcyosXG4gKiBhbmQgYSBmaWxlIGFuc3dlcnMgVVJMcyBub25lIG9mIGl0cyB0ZW1wbGF0ZXMgc3BlbGxzOiBhbiBvcHRpb25hbCBjYXRjaC1hbGwnc1xuICogcGFyZW50LCB0aGUgYHRyYWlsaW5nU2xhc2hgIGZvcm0sIGEgUGFnZXMgUm91dGVyIGRhdGEgVVJMLCBldmVyeSBvdGhlclxuICogdGVtcGxhdGUgaXQgc2hhcmVzIChyb290IHBhcmFtcyBzeW50aGVzaXplIGAvZW5gIGFuZCBgL2RlYCBmcm9tIG9uZVxuICogYFtsb2NhbGVdYCBwYWdlKS4gQW4gaW50ZXJjZXB0aW9uIHJvdXRlIGlzIHdvcnNlOiBpdCBpcyBuZXZlciByZXF1ZXN0ZWQgYXQgaXRzXG4gKiBvd24gcGF0aCBhdCBhbGwuIFNvIGFmdGVyIG1hdGNoaW5nLCBpbnRlcmNlcHRpbmcgZmlsZXMgbW92ZSB0byB0aGUgZ3JvdXAgb2ZcbiAqIHRoZSBVUkwgdGhleSBpbnRlcmNlcHQgKHtAbGluayByZWFzc2lnbkludGVyY2VwdGluZ0ZpbGVzfSksIGFuZCB0aGUgcmVzdWx0IGlzXG4gKiByZXBsYXllZCB0aHJvdWdoIHRoZSBzYW1lIGJlaGF2aW9ycyBgTmV4dGpzRGlzdHJpYnV0aW9uYCBkZXBsb3lzXG4gKiAoe0BsaW5rIGFzc2VydEVkZ2VSZWFjaGVzRXZlcnlGaWxlfSwge0BsaW5rIGFzc2VydFJld3JpdGVzU3RheUluR3JvdXB9KS4gQSBVUkxcbiAqIHRoYXQgd291bGQgcmVhY2ggYSBmdW5jdGlvbiB3aXRob3V0IGl0cyBmaWxlIHRocm93cyBoZXJlLCBkdXJpbmcgYG5leHQgYnVpbGRgLFxuICogcmF0aGVyIHRoYW4gYW5zd2VyaW5nIDQwNCBvbmNlIGRlcGxveWVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzaWduUm91dGVzVG9Hcm91cHMoXG4gIGdyb3VwczogcmVhZG9ubHkgRnVuY3Rpb25Hcm91cFNwZWNbXSxcbiAgZW50cmllczogcmVhZG9ubHkgUm91dGVFbnRyeVtdLFxuICBvcHRpb25zOiBBc3NpZ25Sb3V0ZXNPcHRpb25zLFxuKTogR3JvdXBBc3NpZ25tZW50IHtcbiAgdmFsaWRhdGVGdW5jdGlvbkdyb3Vwcyhncm91cHMpO1xuICBjb25zdCBiYXNlUGF0aCA9IGJhc2VQYXRoUHJlZml4KG9wdGlvbnMuYmFzZVBhdGgpO1xuXG4gIC8vIE1hdGNoZWQgd2l0aCB0aGUgdmVyeSBiZWhhdmlvcnMgYE5leHRqc0Rpc3RyaWJ1dGlvbmAgZGVwbG95cyBmb3IgdGhlXG4gIC8vIGRlY2xhcmVkIHBhdHRlcm5zLCBtb3N0IHNwZWNpZmljIGZpcnN0LCBzbyBwYWNrYWdpbmcgYW5kIHRoZSBlZGdlIHNoYXJlIG9uZVxuICAvLyByb3V0aW5nIG1vZGVsIGFuZCB0aGUgZmlyc3QgbWF0Y2ggaXMgdGhlIHdpbm5lci4gRGF0YSByb3V0ZXMgYXJlIGxlZnQgb3V0OlxuICAvLyBubyB0ZW1wbGF0ZSBpcyB1bmRlciBgL19uZXh0YCwgYW5kIHdoaWNoIGdyb3VwcyBoYXZlIHRoZW0gaXMgZGVjaWRlZCBieVxuICAvLyB0aGlzIGFzc2lnbm1lbnQuXG4gIGNvbnN0IGVkZ2VCYXNlID0ge1xuICAgIGJhc2VQYXRoLFxuICAgIGJ1aWxkSWQ6IG9wdGlvbnMuYnVpbGRJZCxcbiAgICB0cmFpbGluZ1NsYXNoOiBvcHRpb25zLnRyYWlsaW5nU2xhc2ggPz8gZmFsc2UsXG4gIH07XG4gIGNvbnN0IHBhdHRlcm5zID0gZWRnZUJlaGF2aW9ycyhcbiAgICBncm91cHMsXG4gICAge30sXG4gICAgeyAuLi5lZGdlQmFzZSwgZGF0YVJvdXRlR3JvdXBzOiBuZXcgU2V0KCkgfSxcbiAgKTtcblxuICBjb25zdCBtYXRjaGVkUGF0dGVybnMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgLy8gQW4gZW50cnlwb2ludCBpcyBhICpmaWxlKjsgdHdvIHRlbXBsYXRlcyBjYW4gc2hhcmUgb25lIChhIFBhZ2VzIFJvdXRlciBwYWdlXG4gIC8vIGFuZCBpdHMgYC9fbmV4dC9kYXRhLzxidWlsZElkPi/igKZqc29uYCBzaWJsaW5nKS4gU3BsaXR0aW5nIHRoZW0gYWNyb3NzIHppcHNcbiAgLy8gd291bGQgc3RhZ2UgdGhlIHNhbWUgZmlsZSB0d2ljZSBhbmQgcm91dGUgb25lIG9mIHRoZW0gdG8gYSBmdW5jdGlvbiB0aGF0XG4gIC8vIGhhcyBpdCBieSBhY2NpZGVudCwgc28gb3duZXJzaGlwIGlzIHJlY29yZGVkIHBlciBlbnRyeXBvaW50IGFuZCByZXVzZWQuXG4gIGNvbnN0IGdyb3VwT2ZFbnRyeXBvaW50ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgLy8gV2hpY2ggYHBhdHRlcm5zYCBpbmRleCB3b24gdGhlIGVudHJ5cG9pbnQuIGBwYXR0ZXJuc2AgaXMgc29ydGVkXG4gIC8vIG1vc3Qtc3BlY2lmaWMtZmlyc3QsIHNvIGEgbG93ZXIgaW5kZXggaXMgdGhlIGJldHRlciBjbGFpbSwgYW5kIGtlZXBpbmcgaXRcbiAgLy8gc3RvcHMgYSBzZWNvbmQgdGVtcGxhdGUgdGhhdCBzaGFyZXMgdGhlIGVudHJ5cG9pbnQgZnJvbSB0YWtpbmcgaXQgb3ZlciB3aXRoXG4gIC8vIGEgKmJyb2FkZXIqIHBhdHRlcm4uIFdpdGhvdXQgaXQgdGhlIG93bmVyIHdhcyB3aGljaGV2ZXIgb2YgdGhlIHR3byB0ZW1wbGF0ZXNcbiAgLy8gYGVudHJpZXNgIGhhcHBlbmVkIHRvIHZpc2l0IGxhc3Qg4oCUIHRoZSBzYW1lIGJ1aWxkIGdyb3VwZWQgZGlmZmVyZW50bHlcbiAgLy8gZGVwZW5kaW5nIG9uIG1hbmlmZXN0IGtleSBvcmRlci5cbiAgY29uc3Qgd2lubmluZ0luZGV4T2ZFbnRyeXBvaW50ID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBsZXQgd2lubmVyOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgZm9yIChjb25zdCBbaW5kZXgsIHBhdHRlcm5dIG9mIHBhdHRlcm5zLmVudHJpZXMoKSkge1xuICAgICAgaWYgKCFwYXR0ZXJuLnJlZ2V4LnRlc3QoZW50cnkudGVtcGxhdGUpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgLy8gRXZlcnkgbWF0Y2ggaXMgcmVjb3JkZWQsIG5vdCBvbmx5IHRoZSB3aW5uaW5nIG9uZS4gQSBwYXR0ZXJuIGZ1bGx5XG4gICAgICAvLyBzaGFkb3dlZCBieSBhIG5hcnJvd2VyIHBhdHRlcm4gaW4gYW5vdGhlciBncm91cCBuZXZlciB3aW5zIGFueXRoaW5nIOKAlFxuICAgICAgLy8gXCIvYXBpLyoqXCIgYWdhaW5zdCBhbiBhcHAgd2hvc2Ugb25seSBBUEkgcm91dGVzIGFyZSB1bmRlclxuICAgICAgLy8gXCIvYXBpL3JlcG9ydHMvKipcIiDigJQgc28gcmVjb3JkaW5nIGp1c3QgdGhlIHdpbm5lciBsZWZ0IGl0IGxvb2tpbmcgbGlrZSBhXG4gICAgICAvLyB0eXBvIGFuZCB0aHJldyBiZWxvdywgcmVqZWN0aW5nIHRoZSB2ZXJ5IGxheW91dCB0aGUgZHVwbGljYXRlLXBhdHRlcm5cbiAgICAgIC8vIGVycm9yIGEgZmV3IGxpbmVzIHVwIGRvY3VtZW50cyBhcyBzdXBwb3J0ZWQuXG4gICAgICBtYXRjaGVkUGF0dGVybnMuYWRkKGAke3BhdHRlcm4uZ3JvdXB9XFx1MDAwMCR7cGF0dGVybi5yb3V0ZX1gKTtcbiAgICAgIHdpbm5lciA/Pz0gaW5kZXg7XG4gICAgfVxuICAgIC8vIEFuIGludGVyY2VwdGluZyBmaWxlJ3Mgb3duIHRlbXBsYXRlIChgL2ZlZWQvKC4uKXBob3RvL1tpZF1gKSBpcyBub3QgYSBVUkxcbiAgICAvLyBhbnlvbmUgcmVxdWVzdHMsIHNvIGl0IGRvZXMgbm90IGRlY2lkZSB0aGUgZmlsZSdzIGdyb3VwOyB0aGUgVVJMIGl0XG4gICAgLy8gaW50ZXJjZXB0cyBkb2VzLCBiZWxvdy4gSXRzIG1hdGNoIHN0aWxsIGNvdW50cyBhZ2FpbnN0IHRoZSB0eXBvIGNoZWNrLlxuICAgIGlmICh3aW5uZXIgPT09IHVuZGVmaW5lZCB8fCBpc0ludGVyY2VwdGlvblRlbXBsYXRlKGVudHJ5LnRlbXBsYXRlKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IGluY3VtYmVudCA9IHdpbm5pbmdJbmRleE9mRW50cnlwb2ludC5nZXQoZW50cnkuZW50cnlwb2ludElkKTtcbiAgICBpZiAoaW5jdW1iZW50ID09PSB1bmRlZmluZWQgfHwgd2lubmVyIDwgaW5jdW1iZW50KSB7XG4gICAgICB3aW5uaW5nSW5kZXhPZkVudHJ5cG9pbnQuc2V0KGVudHJ5LmVudHJ5cG9pbnRJZCwgd2lubmVyKTtcbiAgICAgIGdyb3VwT2ZFbnRyeXBvaW50LnNldChlbnRyeS5lbnRyeXBvaW50SWQsIHBhdHRlcm5zW3dpbm5lcl0uZ3JvdXApO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgcGF0dGVybiBtYXRjaGluZyBub3RoaW5nIGlzIGEgdHlwbywgYW5kIGEgdHlwbyBoZXJlIGlzIGludmlzaWJsZTogdGhlXG4gIC8vIHJvdXRlIHN0YXlzIGluIHRoZSBkZWZhdWx0IGdyb3VwIGFuZCB0aGUgc3BsaXQgc2lsZW50bHkgZG9lcyBsZXNzIHRoYW4gaXRcbiAgLy8gd2FzIGFza2VkIHRvLiBDaGVhcCB0byBjYXRjaCwgc28gY2F0Y2ggaXQuXG4gIGZvciAoY29uc3QgZ3JvdXAgb2YgZ3JvdXBzKSB7XG4gICAgZm9yIChjb25zdCByb3V0ZSBvZiBncm91cC5yb3V0ZXMpIHtcbiAgICAgIGlmICghbWF0Y2hlZFBhdHRlcm5zLmhhcyhgJHtncm91cC5uYW1lfVxcdTAwMDAke3JvdXRlfWApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgJHtFUlJPUl9QUkVGSVh9R3JvdXAgXCIke2dyb3VwLm5hbWV9XCIgcGF0dGVybiBcIiR7cm91dGV9XCIgbWF0Y2hlcyBubyBgICtcbiAgICAgICAgICAgIGByb3V0ZSBpbiB0aGlzIGJ1aWxkLiBgICtcbiAgICAgICAgICAgIG9wdGlvbmFsQ2F0Y2hBbGxQYXJlbnRIaW50KHJvdXRlLCBlbnRyaWVzLCBiYXNlUGF0aCkgK1xuICAgICAgICAgICAgYFBhdHRlcm5zIG1hdGNoIHJvdXRlIHRlbXBsYXRlcyBhcyBOZXh0LmpzIGRlY2xhcmVzIHRoZW0gKGUuZy4gYCArXG4gICAgICAgICAgICBgXCIvYmxvZy9bc2x1Z11cIiBpcyBtYXRjaGVkIGJ5IFwiL2Jsb2cvKipcIiksIGFuZCBwcmVyZW5kZXJlZCBwYWdlcyBhbmQgYCArXG4gICAgICAgICAgICBgc3RhdGljIGFzc2V0cyBhcmUgc2VydmVkIGZyb20gUzMgYW5kIG5lZWQgbm8gZ3JvdXAuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBlZGdlOiBFZGdlT3B0aW9ucyA9IHtcbiAgICAuLi5lZGdlQmFzZSxcbiAgICAvLyBPbmx5IGEgZ3JvdXAgdGhhdCBvd25zIGEgUGFnZXMgUm91dGVyIHBhZ2UgaGFzIGRhdGEgVVJMcyB0byByb3V0ZS4gUmVhZFxuICAgIC8vIGJlZm9yZSBpbnRlcmNlcHRpb24gbW92ZXMgZmlsZXM6IHRob3NlIGFyZSBBcHAgUm91dGVyLCBuZXZlciBwYWdlcy5cbiAgICBkYXRhUm91dGVHcm91cHM6IG5ldyBTZXQoXG4gICAgICBlbnRyaWVzXG4gICAgICAgIC5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS50eXBlID09PSBcInBhZ2VcIilcbiAgICAgICAgLm1hcChcbiAgICAgICAgICAoZW50cnkpID0+XG4gICAgICAgICAgICBncm91cE9mRW50cnlwb2ludC5nZXQoZW50cnkuZW50cnlwb2ludElkKSA/PyBERUZBVUxUX0ZVTkNUSU9OX0dST1VQLFxuICAgICAgICApLFxuICAgICksXG4gIH07XG4gIHJlYXNzaWduSW50ZXJjZXB0aW5nRmlsZXMoXG4gICAgZW50cmllcyxcbiAgICBncm91cE9mRW50cnlwb2ludCxcbiAgICBlZGdlQmVoYXZpb3JzKFxuICAgICAgZ3JvdXBzLFxuICAgICAgdGVtcGxhdGVzQnlHcm91cChncm91cHMsIGVudHJpZXMsIGdyb3VwT2ZFbnRyeXBvaW50KSxcbiAgICAgIGVkZ2UsXG4gICAgKSxcbiAgICBlZGdlLFxuICApO1xuICBjb25zdCBhc3NpZ25lZCA9IHRlbXBsYXRlc0J5R3JvdXAoZ3JvdXBzLCBlbnRyaWVzLCBncm91cE9mRW50cnlwb2ludCk7XG4gIC8vIFJlYnVpbHQgcmF0aGVyIHRoYW4gcmV1c2VkOiBhbiBpbnRlcmNlcHRpbmcgZmlsZSBuZXZlciBhZGRzIGFuIG9wdGlvbmFsXG4gIC8vIGNhdGNoLWFsbCBwYXJlbnQsIHNvIHRoaXMgaXMgdGhlIHNhbWUgbGlzdCwgYnV0IG9ubHkgYnkgdGhhdCBhcmd1bWVudC5cbiAgY29uc3QgYmVoYXZpb3JzID0gZWRnZUJlaGF2aW9ycyhncm91cHMsIGFzc2lnbmVkLCBlZGdlKTtcbiAgY29uc3Qgcm91dGVyOiBSb3V0ZXIgPSB7XG4gICAgZmlsZU9mVGVtcGxhdGU6IGZpbGVPZlRlbXBsYXRlKGVudHJpZXMpLFxuICAgIHJvdXRpbmc6IG9wdGlvbnMucm91dGluZyxcbiAgfTtcbiAgYXNzZXJ0RWRnZVJlYWNoZXNFdmVyeUZpbGUoXG4gICAgZW50cmllcyxcbiAgICBncm91cE9mRW50cnlwb2ludCxcbiAgICBiZWhhdmlvcnMsXG4gICAgZWRnZSxcbiAgICByb3V0ZXIsXG4gICk7XG4gIGFzc2VydFJld3JpdGVzU3RheUluR3JvdXAoZ3JvdXBPZkVudHJ5cG9pbnQsIGJlaGF2aW9ycywgcm91dGVyKTtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhhc3NpZ25lZCkpIHtcbiAgICBhc3NpZ25lZFtrZXldID0gWy4uLmFzc2lnbmVkW2tleV1dLnNvcnQoKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHRlbXBsYXRlczogYXNzaWduZWQsXG4gICAgYmVoYXZpb3JzOiBiZWhhdmlvcnMubWFwKCh7IGdyb3VwLCByb3V0ZSwgcGF0dGVybiB9KSA9PiAoe1xuICAgICAgZ3JvdXAsXG4gICAgICByb3V0ZSxcbiAgICAgIHBhdHRlcm4sXG4gICAgfSkpLFxuICB9O1xufVxuXG4vKipcbiAqIFRoZSBwYXR0ZXJucyBhIGdyb3VwIGlzICpyb3V0ZWQqIG9uOiB0aGUgb25lcyBpdCBkZWNsYXJlcywgcGx1cyB0aGUgcGFyZW50XG4gKiBwYXRoIG9mIGV2ZXJ5IG9wdGlvbmFsIGNhdGNoLWFsbCBhIHN1YnRyZWUgcGF0dGVybiBtb3ZlZCBpbnRvIGl0LlxuICpcbiAqIGAvYmxvZy9bWy4uLnNsdWddXWAgc2VydmVzIGAvYmxvZ2AgYXMgd2VsbCBhcyBldmVyeXRoaW5nIHVuZGVyIGl0LCBhbmRcbiAqIGAvYmxvZy8qKmAgbW92ZXMgdGhlIHdob2xlIGZpbGUg4oCUIGJ1dCBkZXBsb3lzIGFzIGBibG9nLypgLCB3aGljaCBkb2VzIG5vdFxuICogbWF0Y2ggYC9ibG9nYC4gU28gdGhlIHBhcmVudCBpcyByb3V0ZWQgYXV0b21hdGljYWxseSwgYXMgYW4gZXhhY3QgcGF0dGVybiBvZlxuICogaXRzIG93bjsgZGVjbGFyaW5nIGAvYmxvZ2AgYnkgaGFuZCBpcyBhIHBhdHRlcm4gd2l0aCBubyByb3V0ZSBvZiBpdHMgb3duIGFuZFxuICogaXMgcmVqZWN0ZWQgYXMgYSB0eXBvLCB3aXRoIGEgaGludCBwb2ludGluZyBoZXJlLiBOb3RoaW5nIGVsc2UgYSBzdWJ0cmVlIG93bnNcbiAqIG5lZWRzIHRoaXM6IGEgZmlsZSB3aG9zZSBwYXJlbnQgVVJMIGlzIGl0cyBzdWJ0cmVlJ3MgYmFzZSBjYW4gb25seSBiZSBhblxuICogb3B0aW9uYWwgY2F0Y2gtYWxsLCBzaW5jZSBOZXh0LmpzIHJlamVjdHMgYGFwcC9ibG9nL3BhZ2UudHN4YCBuZXh0IHRvIGl0LlxuICpcbiAqIEBwYXJhbSBvd25lZFRlbXBsYXRlcyB0aGUgdGVtcGxhdGVzIGFzc2lnbmVkIHRvIHRoZSBncm91cCwgYmFzZVBhdGgtcHJlZml4ZWRcbiAqICAgYXMgYG1hbmlmZXN0Lmdyb3Vwc2AgcmVjb3JkcyB0aGVtXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3V0ZWRQYXR0ZXJucyhcbiAgcm91dGVzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgb3duZWRUZW1wbGF0ZXM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBiYXNlUGF0aDogc3RyaW5nLFxuKTogc3RyaW5nW10ge1xuICBjb25zdCByZXN1bHQgPSBbLi4ucm91dGVzXTtcbiAgZm9yIChjb25zdCByb3V0ZSBvZiByb3V0ZXMpIHtcbiAgICBpZiAoIXJvdXRlLmVuZHNXaXRoKFNVQlRSRUVfU1VGRklYKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IHBhcmVudCA9IHJvdXRlLnNsaWNlKDAsIC1TVUJUUkVFX1NVRkZJWC5sZW5ndGgpO1xuICAgIGNvbnN0IHByZWZpeCA9IGAke3ByZWZpeEJhc2VQYXRoKHBhcmVudCwgYmFzZVBhdGgpfS9gO1xuICAgIGNvbnN0IG93bnNPcHRpb25hbENhdGNoQWxsID0gb3duZWRUZW1wbGF0ZXMuc29tZShcbiAgICAgICh0ZW1wbGF0ZSkgPT5cbiAgICAgICAgdGVtcGxhdGUuc3RhcnRzV2l0aChwcmVmaXgpICYmXG4gICAgICAgIE9QVElPTkFMX0NBVENIX0FMTF9TRUdNRU5ULnRlc3QodGVtcGxhdGUuc2xpY2UocHJlZml4Lmxlbmd0aCkpLFxuICAgICk7XG4gICAgaWYgKG93bnNPcHRpb25hbENhdGNoQWxsICYmICFyZXN1bHQuaW5jbHVkZXMocGFyZW50KSkge1xuICAgICAgcmVzdWx0LnB1c2gocGFyZW50KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBDbG91ZEZyb250IHBhdGggcGF0dGVybnMgZm9yIG9uZSBncm91cCBwYXR0ZXJuLCB3aXRob3V0IGEgbGVhZGluZyBzbGFzaCDigJRcbiAqIHRoZSBmb3JtIGBOZXh0anNEaXN0cmlidXRpb24uZ2V0UGF0aFBhdHRlcm5gIGV4cGVjdHMsIHNvIHRoZSBiYXNlUGF0aCBpc1xuICogYWRkZWQgdGhlcmUgcmF0aGVyIHRoYW4gaGVyZS5cbiAqXG4gKiBUd28gcGF0dGVybnMgY29tZSBiYWNrIHdoZW4gdGhlIGdyb3VwIG93bnMgYSBQYWdlcyBSb3V0ZXIgcm91dGU6IGl0cyBSU0MtZXJhXG4gKiBlcXVpdmFsZW50IGlzIGEgc2Vjb25kIFVSTCBzcGFjZSwgYC9fbmV4dC9kYXRhLzxidWlsZElkPi88cm91dGU+Lmpzb25gLCB3aGljaFxuICogdGhlIGRlZmF1bHQgYmVoYXZpb3Igd291bGQgb3RoZXJ3aXNlIHNlbmQgdG8gdGhlIGRlZmF1bHQgZ3JvdXAuXG4gKlxuICogQSB0aGlyZCBjb21lcyBiYWNrIGZvciBhbiBleGFjdCByb3V0ZSBpbiBhIGB0cmFpbGluZ1NsYXNoYCBhcHAsIHdoZXJlIHRoZVxuICogY2Fub25pY2FsIFVSTCBpcyBgL3ByaWNpbmcvYCByYXRoZXIgdGhhbiBgL3ByaWNpbmdgOiB0aGUgYmFyZSBwYXR0ZXJuIGRvZXMgbm90XG4gKiBtYXRjaCBpdCwgc28gd2l0aG91dCB0aGlzIGV2ZXJ5IHJlcXVlc3QgZm9yIHRoZSByb3V0ZSB0aGUgdXNlciBhY3R1YWxseSBsaW5rcyB0b1xuICogZmFsbHMgdGhyb3VnaCB0byB0aGUgZGVmYXVsdCBncm91cCdzIGZ1bmN0aW9uIOKAlCB3aGljaCwgZm9yIGEgUGFnZXMgUm91dGVyIEFQSVxuICogcm91dGUsIGhhcyBubyBlbnRyeXBvaW50IGZvciBpdCBhdCBhbGwuIFN1YnRyZWUgcGF0dGVybnMgbmVlZCBubyB2YXJpYW50XG4gKiAoYHByaWNpbmcvKmAgYWxyZWFkeSBtYXRjaGVzIGAvcHJpY2luZy9gKSwgYW5kIG5laXRoZXIgZG8gdGhlIGRhdGEgVVJMcywgd2hpY2hcbiAqIG5ldmVyIGNhcnJ5IHRoZSBzbGFzaC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhdGhQYXR0ZXJuc0ZvcihcbiAgcm91dGU6IHN0cmluZyxcbiAgb3B0aW9uczoge1xuICAgIGhhc0RhdGFSb3V0ZXM6IGJvb2xlYW47XG4gICAgdHJhaWxpbmdTbGFzaD86IGJvb2xlYW47XG4gICAgYnVpbGRJZD86IHN0cmluZztcbiAgfSxcbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgaXNTdWJ0cmVlID0gcm91dGUuZW5kc1dpdGgoU1VCVFJFRV9TVUZGSVgpO1xuICBjb25zdCBiYXNlID0gaXNTdWJ0cmVlID8gcm91dGUuc2xpY2UoMCwgLVNVQlRSRUVfU1VGRklYLmxlbmd0aCkgOiByb3V0ZTtcbiAgY29uc3QgYmFyZSA9IGJhc2UucmVwbGFjZSgvXlxcLy8sIFwiXCIpO1xuICBjb25zdCBwYXR0ZXJucyA9IFtpc1N1YnRyZWUgPyBgJHtiYXJlfS8qYCA6IGJhcmVdO1xuICBpZiAoIWlzU3VidHJlZSAmJiBvcHRpb25zLnRyYWlsaW5nU2xhc2ggJiYgYmFyZSkge1xuICAgIHBhdHRlcm5zLnB1c2goYCR7YmFyZX0vYCk7XG4gIH1cbiAgaWYgKG9wdGlvbnMuaGFzRGF0YVJvdXRlcykge1xuICAgIC8vIFRoZSBsaXRlcmFsIGJ1aWxkIElELCBub3QgYSBgKmAgZm9yIGl0LiBDbG91ZEZyb250J3MgYCpgIGFsc28gbWF0Y2hlc1xuICAgIC8vIGAvYCwgc28gYF9uZXh0L2RhdGEvKi9ibG9nLypgIGNsYWltZWQgYC9fbmV4dC9kYXRhLzxpZD4vZG9jcy9ibG9nL3guanNvbmBcbiAgICAvLyB0b28g4oCUIGFub3RoZXIgZ3JvdXAncyBwYWdlLCBzZW50IHRvIGEgZnVuY3Rpb24gd2l0aG91dCBpdC4gRXZlcnkgb3RoZXJcbiAgICAvLyBwYXR0ZXJuIGlzIGFuY2hvcmVkIGF0IHRoZSBzdGFydCBvZiB0aGUgcGF0aDsgdGhpcyBvbmUgbm93IGlzIGFzIHdlbGwuXG4gICAgLy9cbiAgICAvLyBJdCBtYWtlcyB0aGVzZSBiZWhhdmlvcnMgY2hhbmdlIHdoZW5ldmVyIHRoZSBidWlsZCBJRCBkb2VzLCB3aGljaCBpcyBldmVyeVxuICAgIC8vIGRlcGxveSB1bmxlc3MgYGRlcGxveW1lbnRJZGAgcGlucyBpdC4gQSBjbGllbnQgc3RpbGwgaG9sZGluZyB0aGUgcHJldmlvdXNcbiAgICAvLyBidWlsZCByZXF1ZXN0cyBgL19uZXh0L2RhdGEvPG9sZCBpZD4v4oCmYCwgd2hpY2ggbm8gYmVoYXZpb3IgbWF0Y2hlcywgc28gaXRcbiAgICAvLyByZWFjaGVzIHRoZSBkZWZhdWx0IGZ1bmN0aW9uLiBUaGF0IGlzIGNvcnJlY3QgcmF0aGVyIHRoYW4gbWVyZWx5XG4gICAgLy8gaGFybWxlc3M6IGBuZXh0IHN0YXJ0YCA0MDRzIGEgZGF0YSByZXF1ZXN0IGZvciBhbm90aGVyIGJ1aWxkIElEXG4gICAgLy8gKGBoYW5kbGVOZXh0RGF0YVJlcXVlc3RgIGluIGBuZXh0L2Rpc3Qvc2VydmVyL2Jhc2Utc2VydmVyLmpzYCkgYW5kIHNvIGRvZXNcbiAgICAvLyB0aGUgcnVudGltZSwgd2hpY2ggaGFzIG5vIHBhdGhuYW1lIGZvciBpdCwgYW5kIHRoZSBQYWdlcyBSb3V0ZXIgY2xpZW50XG4gICAgLy8gdHJlYXRzIGEgZGF0YSA0MDQgYXMgYW4gYXNzZXQgZXJyb3IgYW5kIGhhcmQtbmF2aWdhdGVzIHRvIHRoZSBwYWdlXG4gICAgLy8gKGBmZXRjaE5leHREYXRhYCDihpIgYG1hcmtBc3NldEVycm9yYCDihpIgYGhhbmRsZVJvdXRlSW5mb0Vycm9yYCBpblxuICAgIC8vIGBuZXh0L2Rpc3Qvc2hhcmVkL2xpYi9yb3V0ZXIvcm91dGVyLmpzYCksIHdoaWNoIGdldHMgdGhlIG5ldyBidWlsZC5cbiAgICBwYXR0ZXJucy5wdXNoKFxuICAgICAgaXNTdWJ0cmVlXG4gICAgICAgID8gYF9uZXh0L2RhdGEvJHtkYXRhQnVpbGRJZChvcHRpb25zLmJ1aWxkSWQpfS8ke2JhcmV9LypgXG4gICAgICAgIDogYF9uZXh0L2RhdGEvJHtkYXRhQnVpbGRJZChvcHRpb25zLmJ1aWxkSWQpfS8ke2JhcmV9Lmpzb25gLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHBhdHRlcm5zO1xufVxuXG4vKipcbiAqIFJhbmsgYSBDbG91ZEZyb250IHBhdGggcGF0dGVybiBzbyB0aGUgbW9zdCBzcGVjaWZpYyBpcyBhZGRlZCBmaXJzdDogbGl0ZXJhbFxuICogc2VnbWVudHMgYmVmb3JlIHRoZSBmaXJzdCBgKmAgZG9taW5hdGUsIHRoZW4gYW4gZXhhY3QgcGF0dGVybiBiZWZvcmUgYVxuICogd2lsZGNhcmQgb25lLCB0aGVuIHRvdGFsIHNlZ21lbnRzLCB0aGVuIGxlbmd0aC4ge0BsaW5rIGVkZ2VCZWhhdmlvcnN9IHNvcnRzXG4gKiBvbiBpdC5cbiAqXG4gKiBSYW5raW5nIG9uIHRoZSBsZWFkaW5nIGxpdGVyYWwgaXMgd2hhdCBhIENsb3VkRnJvbnQgd2lsZGNhcmQgZm9yY2VzLCBiZWNhdXNlXG4gKiBpdCBtYXRjaGVzIGFjcm9zcyBgL2AgcmF0aGVyIHRoYW4gd2l0aGluIG9uZSBzZWdtZW50OiBhbiBleGFjdCBgYS9iYCBoYXMgdG9cbiAqIHByZWNlZGUgdGhlIHN1YnRyZWUgYGEvKmAgdGhhdCB3b3VsZCBvdGhlcndpc2Ugc3dhbGxvdyBpdCwgdGhvdWdoIHRoZSB0d28gYXJlXG4gKiB0aGUgc2FtZSBsZW5ndGggYW5kIGRlcHRoLiBBdCBlcXVhbCBsaXRlcmFsIGRlcHRoIHRoZSBleGFjdCBvbmUgc3RpbGwgZ29lc1xuICogZmlyc3QsIHNpbmNlIGEgdHJhaWxpbmdTbGFzaCBgYS9iL2AgaXMgb3RoZXJ3aXNlIG91dHJhbmtlZCBieSB0aGUgc3VidHJlZVxuICogYGEvYi8qYCwgb25lIHNlZ21lbnQgbG9uZ2VyLCB0aGF0IG1hdGNoZXMgaXQuIFNpbmNlIHRoZSBkYXRhIHBhdHRlcm5zIGNhcnJ5XG4gKiB0aGUgbGl0ZXJhbCBidWlsZCBJRCwgbm8gcGF0dGVybiBoYXMgYSB3aWxkY2FyZCBhbnl3aGVyZSBidXQgYXQgaXRzIGVuZC5cbiAqL1xuZnVuY3Rpb24gYmVoYXZpb3JTcGVjaWZpY2l0eShwYXR0ZXJuOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCBzZWdtZW50cyA9IHBhdHRlcm4uc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3QgZmlyc3RXaWxkY2FyZCA9IHNlZ21lbnRzLmZpbmRJbmRleCgoc2VnbWVudCkgPT4gc2VnbWVudC5pbmNsdWRlcyhcIipcIikpO1xuICBjb25zdCBsaXRlcmFsRGVwdGggPSBmaXJzdFdpbGRjYXJkID09PSAtMSA/IHNlZ21lbnRzLmxlbmd0aCA6IGZpcnN0V2lsZGNhcmQ7XG4gIGNvbnN0IGV4YWN0ID0gZmlyc3RXaWxkY2FyZCA9PT0gLTEgPyAxIDogMDtcbiAgcmV0dXJuIChcbiAgICAobGl0ZXJhbERlcHRoICogMiArIGV4YWN0KSAqIDEwMDAwMDAgK1xuICAgIHNlZ21lbnRzLmxlbmd0aCAqIDEwMDAwICtcbiAgICBwYXR0ZXJuLmxlbmd0aFxuICApO1xufVxuXG4vKipcbiAqIFRoZSBidWlsZCBJRCBhcyBpdCBnb2VzIGludG8gYSBwYXRoIHBhdHRlcm4uIEEgY3VzdG9tIGBnZW5lcmF0ZUJ1aWxkSWRgIGNhblxuICogcmV0dXJuIGFueXRoaW5nLCBhbmQgYSBjaGFyYWN0ZXIgQ2xvdWRGcm9udCBjYW5ub3Qgc3BlbGwgd291bGQgb3RoZXJ3aXNlIGZhaWxcbiAqIHRoZSBkZXBsb3kgbmFtaW5nIG5laXRoZXIgdGhlIGJ1aWxkIElEIG5vciB0aGUgZ3JvdXAuXG4gKi9cbmZ1bmN0aW9uIGRhdGFCdWlsZElkKGJ1aWxkSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGlmICghYnVpbGRJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGAke0VSUk9SX1BSRUZJWH1Sb3V0aW5nIGEgUGFnZXMgUm91dGVyIGFwcCdzIFwiL19uZXh0L2RhdGEvPGJ1aWxkSWQ+L+KAplwiIGAgK1xuICAgICAgICBgVVJMcyBuZWVkcyBpdHMgYnVpbGQgSUQsIGFuZCBub25lIHdhcyBwYXNzZWQuIFRoaXMgaXMgYSBjZGstbmV4dGpzIGAgK1xuICAgICAgICBgYnVnOiB0aGUgYnVpbGQgSUQgY29tZXMgZnJvbSB0aGUgYWRhcHRlciBtYW5pZmVzdC5gLFxuICAgICk7XG4gIH1cbiAgY29uc3QgaW52YWxpZCA9IFsuLi5uZXcgU2V0KGJ1aWxkSWQpXS5maWx0ZXIoXG4gICAgKGNoYXIpID0+ICFQQVRIX1BBVFRFUk5fTElURVJBTC50ZXN0KGNoYXIpIHx8IGNoYXIgPT09IFwiL1wiLFxuICApO1xuICBpZiAoaW52YWxpZC5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7RVJST1JfUFJFRklYfVRoZSBidWlsZCBJRCBcIiR7YnVpbGRJZH1cIiBjb250YWlucyBgICtcbiAgICAgICAgYCR7aW52YWxpZC5tYXAoKGNoYXIpID0+IEpTT04uc3RyaW5naWZ5KGNoYXIpKS5qb2luKFwiLCBcIil9LCB3aGljaCBhIGAgK1xuICAgICAgICBgQ2xvdWRGcm9udCBwYXRoIHBhdHRlcm4gY2Fubm90IGhvbGQsIHNvIGl0cyBcIi9fbmV4dC9kYXRhXCIgVVJMcyBjYW5ub3QgYCArXG4gICAgICAgIGBiZSByb3V0ZWQgdG8gYSBncm91cC4gTWFrZSBcXGBnZW5lcmF0ZUJ1aWxkSWRcXGAgcmV0dXJuIG9ubHkgQS1aIGEteiBgICtcbiAgICAgICAgYDAtOSBfIC0gLiBjaGFyYWN0ZXJzLmAsXG4gICAgKTtcbiAgfVxuICByZXR1cm4gYnVpbGRJZDtcbn1cblxuLyoqXG4gKiBUaGUgdHlwbyBjaGVjaydzIGhpbnQgZm9yIHRoZSBvbmUgZXhhY3QgcGF0dGVybiB0aGF0IHdhcyB0aGUgZG9jdW1lbnRlZFxuICogd29ya2Fyb3VuZDogdGhlIHBhcmVudCBvZiBhbiBvcHRpb25hbCBjYXRjaC1hbGwsIHdoaWNoIGhhcyBubyB0ZW1wbGF0ZS5cbiAqL1xuZnVuY3Rpb24gb3B0aW9uYWxDYXRjaEFsbFBhcmVudEhpbnQoXG4gIHJvdXRlOiBzdHJpbmcsXG4gIGVudHJpZXM6IHJlYWRvbmx5IFJvdXRlRW50cnlbXSxcbiAgYmFzZVBhdGg6IHN0cmluZyxcbik6IHN0cmluZyB7XG4gIGlmIChyb3V0ZS5lbmRzV2l0aChTVUJUUkVFX1NVRkZJWCkpIHtcbiAgICByZXR1cm4gXCJcIjtcbiAgfVxuICBjb25zdCBwcmVmaXggPSBgJHtwcmVmaXhCYXNlUGF0aChyb3V0ZSwgYmFzZVBhdGgpfS9gO1xuICBjb25zdCBjYXRjaEFsbCA9IGVudHJpZXMuZmluZChcbiAgICAoZW50cnkpID0+XG4gICAgICBlbnRyeS50ZW1wbGF0ZS5zdGFydHNXaXRoKHByZWZpeCkgJiZcbiAgICAgIE9QVElPTkFMX0NBVENIX0FMTF9TRUdNRU5ULnRlc3QoZW50cnkudGVtcGxhdGUuc2xpY2UocHJlZml4Lmxlbmd0aCkpLFxuICApO1xuICBpZiAoIWNhdGNoQWxsKSB7XG4gICAgcmV0dXJuIFwiXCI7XG4gIH1cbiAgcmV0dXJuIChcbiAgICBgXCIke3JvdXRlfVwiIGlzIHNlcnZlZCBieSB0aGUgb3B0aW9uYWwgY2F0Y2gtYWxsIFwiJHtjYXRjaEFsbC50ZW1wbGF0ZX1cIiwgYCArXG4gICAgYHdob3NlIHN1YnRyZWUgcGF0dGVybiBcIiR7cm91dGV9JHtTVUJUUkVFX1NVRkZJWH1cIiByb3V0ZXMgXCIke3JvdXRlfVwiIGFzIGAgK1xuICAgIGB3ZWxsIOKAlCB1c2UgdGhhdCBpbnN0ZWFkLiBgXG4gICk7XG59XG5cbi8qKiBgL2Jsb2cvW1suLi5zbHVnXV1gJ3MgbGFzdCBzZWdtZW50LiAqL1xuY29uc3QgT1BUSU9OQUxfQ0FUQ0hfQUxMX1NFR01FTlQgPSAvXlxcW1xcW1xcLlxcLlxcLlteXFxdL10rXFxdXFxdJC87XG5cbi8qKlxuICogTmV4dC5qcydzIGludGVyY2VwdGlvbiBtYXJrZXJzLCBsb25nZXN0LW92ZXJsYXBwaW5nIGZpcnN0LCBleGFjdGx5IGFzXG4gKiBgSU5URVJDRVBUSU9OX1JPVVRFX01BUktFUlNgIGluXG4gKiBgbmV4dC9kaXN0L3NoYXJlZC9saWIvcm91dGVyL3V0aWxzL2ludGVyY2VwdGlvbi1yb3V0ZXMuanNgIG9yZGVycyB0aGVtLlxuICovXG5jb25zdCBJTlRFUkNFUFRJT05fTUFSS0VSUyA9IFtcIiguLikoLi4pXCIsIFwiKC4pXCIsIFwiKC4uKVwiLCBcIiguLi4pXCJdO1xuXG5mdW5jdGlvbiBpbnRlcmNlcHRpb25NYXJrZXJPZihwYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IHNlZ21lbnQgb2YgcGF0aC5zcGxpdChcIi9cIikpIHtcbiAgICBjb25zdCBtYXJrZXIgPSBJTlRFUkNFUFRJT05fTUFSS0VSUy5maW5kKChpdCkgPT4gc2VnbWVudC5zdGFydHNXaXRoKGl0KSk7XG4gICAgaWYgKG1hcmtlcikge1xuICAgICAgcmV0dXJuIG1hcmtlcjtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gaXNJbnRlcmNlcHRpb25UZW1wbGF0ZSh0ZW1wbGF0ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBpbnRlcmNlcHRpb25NYXJrZXJPZih0ZW1wbGF0ZSkgIT09IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBUaGUgcm91dGUgYW4gaW50ZXJjZXB0aW9uIHJvdXRlIGludGVyY2VwdHM6IGAvZmVlZC8oLi4pcGhvdG8vW2lkXWAg4oaSXG4gKiBgL3Bob3RvL1tpZF1gLiBgZXh0cmFjdEludGVyY2VwdGlvblJvdXRlSW5mb3JtYXRpb25gIGZyb21cbiAqIGBuZXh0L2Rpc3Qvc2hhcmVkL2xpYi9yb3V0ZXIvdXRpbHMvaW50ZXJjZXB0aW9uLXJvdXRlcy5qc2AsIHJlc3RhdGVkIGJlY2F1c2VcbiAqIHRoaXMgZmlsZSBpcyBidW5kbGVkIHdpdGhvdXQgYG5leHRgLiBUaGUgdGVtcGxhdGUgaXMgYWxyZWFkeSBhIG5vcm1hbGl6ZWQgYXBwXG4gKiBwYXRoIChubyByb3V0ZSBncm91cHMsIG5vIGBAc2xvdGBzKSwgc28gbm9uZSBvZiBpdHMgbm9ybWFsaXphdGlvbiBpcyBuZWVkZWQuXG4gKiBOZXh0LmpzJ3MgaW50ZXJjZXB0aW9uIHJld3JpdGUgbWF0Y2hlcyBleGFjdGx5IHRoaXMgcGF0aCwgYW5kIG9ubHkgd2l0aCBhXG4gKiBgTmV4dC1VcmxgIGhlYWRlciDigJQgd2hpY2ggQ2xvdWRGcm9udCBkb2VzIG5vdCByb3V0ZSBvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVyY2VwdGVkUm91dGUocGF0aDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgbWFya2VyID0gaW50ZXJjZXB0aW9uTWFya2VyT2YocGF0aCk7XG4gIGlmIChtYXJrZXIgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3QgYXQgPSBwYXRoLmluZGV4T2YobWFya2VyKTtcbiAgY29uc3QgaW50ZXJjZXB0aW5nID0gcGF0aC5zbGljZSgwLCBhdCkuc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3QgcmVzdCA9IHBhdGhcbiAgICAuc2xpY2UoYXQgKyBtYXJrZXIubGVuZ3RoKVxuICAgIC5zcGxpdChcIi9cIilcbiAgICAuZmlsdGVyKEJvb2xlYW4pO1xuICBjb25zdCBwYXJlbnQgPVxuICAgIG1hcmtlciA9PT0gXCIoLilcIlxuICAgICAgPyBpbnRlcmNlcHRpbmdcbiAgICAgIDogbWFya2VyID09PSBcIiguLilcIlxuICAgICAgICA/IGludGVyY2VwdGluZy5zbGljZSgwLCAtMSlcbiAgICAgICAgOiBtYXJrZXIgPT09IFwiKC4uKSguLilcIlxuICAgICAgICAgID8gaW50ZXJjZXB0aW5nLnNsaWNlKDAsIC0yKVxuICAgICAgICAgIDogW107XG4gIHJldHVybiBgLyR7Wy4uLnBhcmVudCwgLi4ucmVzdF0uam9pbihcIi9cIil9YDtcbn1cblxuLyoqXG4gKiBUZW1wbGF0ZXMgdGhhdCBuYW1lIHdoYXQgYSByZXF1ZXN0IGlzICpyZXdyaXR0ZW4qIHRvIGluc2lkZSBOZXh0LmpzLCBuZXZlclxuICogd2hhdCB0aGUgYnJvd3NlciBhc2tzIGZvcjogdGhlIFJTQyBwYXlsb2FkIChgL3ByaWNpbmcucnNjYCkgYW5kIHNlZ21lbnRcbiAqIHByZWZldGNoZXMgKGAvcHJpY2luZy5zZWdtZW50cy/igKZgKSBhcmUgcmVxdWVzdGVkIGFzIGAvcHJpY2luZ2Agd2l0aCBhbiBgUlNDYFxuICogaGVhZGVyLCB3aGljaCBpcyB3aHkgYHByaWNpbmdgIGFsb25lIGhhcyBhbHdheXMgcm91dGVkIHRoZW0uXG4gKi9cbmZ1bmN0aW9uIGlzSW50ZXJuYWxUZW1wbGF0ZShwYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIHBhdGguZW5kc1dpdGgoXCIucnNjXCIpIHx8IHBhdGguaW5jbHVkZXMoXCIuc2VnbWVudHMvXCIpO1xufVxuXG4vKiogV2hhdCB0aGUgZWRnZSByb3V0ZXMgb24uICovXG5pbnRlcmZhY2UgRWRnZU9wdGlvbnMge1xuICAvKiogV2l0aCBhIGxlYWRpbmcgc2xhc2gsIGBcIlwiYCBmb3Igbm9uZS4gKi9cbiAgcmVhZG9ubHkgYmFzZVBhdGg6IHN0cmluZztcbiAgcmVhZG9ubHkgYnVpbGRJZD86IHN0cmluZztcbiAgcmVhZG9ubHkgdHJhaWxpbmdTbGFzaDogYm9vbGVhbjtcbiAgLyoqIFRoZSBncm91cHMgdGhhdCBvd24gYSBQYWdlcyBSb3V0ZXIgcGFnZSwgYW5kIHNvIGhhdmUgZGF0YSBVUkxzLiAqL1xuICByZWFkb25seSBkYXRhUm91dGVHcm91cHM6IFJlYWRvbmx5U2V0PHN0cmluZz47XG59XG5cbi8qKiBBIHtAbGluayBHcm91cEJlaGF2aW9yfSwgd2l0aCB0aGUgcmVnZXggQ2xvdWRGcm9udCBtYXRjaGVzIGl0IGFzLiAqL1xuaW50ZXJmYWNlIEVkZ2VCZWhhdmlvciBleHRlbmRzIEdyb3VwQmVoYXZpb3Ige1xuICByZWFkb25seSByZWdleDogUmVnRXhwO1xufVxuXG4vKipcbiAqIEV2ZXJ5IGdyb3VwIGJlaGF2aW9yLCBtb3N0IHNwZWNpZmljIGZpcnN0OiB0aGUgb3JkZXIgQ2xvdWRGcm9udCBoYXMgdG8gc2VlXG4gKiB0aGVtIGluLCBzaW5jZSBpdCBzdG9wcyBhdCB0aGUgZmlyc3QgbWF0Y2guIFRoZSBhc3NpZ25tZW50IHJldHVybnMgdGhpcyBsaXN0XG4gKiBhbmQgdGhlIGNvbnN0cnVjdHMgZGVwbG95IGl0IGFzIGl0IGlzLlxuICovXG5mdW5jdGlvbiBlZGdlQmVoYXZpb3JzKFxuICBncm91cHM6IHJlYWRvbmx5IEZ1bmN0aW9uR3JvdXBTcGVjW10sXG4gIGFzc2lnbmVkOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4sXG4gIGVkZ2U6IEVkZ2VPcHRpb25zLFxuKTogRWRnZUJlaGF2aW9yW10ge1xuICByZXR1cm4gZ3JvdXBzXG4gICAgLmZsYXRNYXAoKGdyb3VwKSA9PlxuICAgICAgcm91dGVkUGF0dGVybnMoXG4gICAgICAgIGdyb3VwLnJvdXRlcyxcbiAgICAgICAgYXNzaWduZWRbZ3JvdXAubmFtZV0gPz8gW10sXG4gICAgICAgIGVkZ2UuYmFzZVBhdGgsXG4gICAgICApLmZsYXRNYXAoKHJvdXRlKSA9PlxuICAgICAgICBwYXRoUGF0dGVybnNGb3Iocm91dGUsIHtcbiAgICAgICAgICB0cmFpbGluZ1NsYXNoOiBlZGdlLnRyYWlsaW5nU2xhc2gsXG4gICAgICAgICAgYnVpbGRJZDogZWRnZS5idWlsZElkLFxuICAgICAgICAgIGhhc0RhdGFSb3V0ZXM6IGVkZ2UuZGF0YVJvdXRlR3JvdXBzLmhhcyhncm91cC5uYW1lKSxcbiAgICAgICAgfSkubWFwKChwYXR0ZXJuKSA9PiAoe1xuICAgICAgICAgIGdyb3VwOiBncm91cC5uYW1lLFxuICAgICAgICAgIHJvdXRlLFxuICAgICAgICAgIHBhdHRlcm4sXG4gICAgICAgICAgcmVnZXg6IGNsb3VkRnJvbnRQYXR0ZXJuUmVnZXgoYCR7ZWRnZS5iYXNlUGF0aH0vJHtwYXR0ZXJufWApLFxuICAgICAgICB9KSksXG4gICAgICApLFxuICAgIClcbiAgICAuc29ydChcbiAgICAgIChhLCBiKSA9PiBiZWhhdmlvclNwZWNpZmljaXR5KGIucGF0dGVybikgLSBiZWhhdmlvclNwZWNpZmljaXR5KGEucGF0dGVybiksXG4gICAgKTtcbn1cblxuLyoqXG4gKiBDbG91ZEZyb250IHBhdGggcGF0dGVybiBtYXRjaGluZzogYW5jaG9yZWQgYXQgYm90aCBlbmRzLCBgKmAgZm9yIGFueSBydW4gb2ZcbiAqIGNoYXJhY3RlcnMgYC9gIGluY2x1ZGVkLCBgP2AgZm9yIGV4YWN0bHkgb25lLCBjYXNlLXNlbnNpdGl2ZS4gYHBhdHRlcm5gIGhhcyB0b1xuICogY2FycnkgdGhlIGxlYWRpbmcgc2xhc2ggQ2xvdWRGcm9udCBpbXBsaWVzLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkRnJvbnQvbGF0ZXN0L0RldmVsb3Blckd1aWRlL0Rvd25sb2FkRGlzdFZhbHVlc0NhY2hlQmVoYXZpb3IuaHRtbCNEb3dubG9hZERpc3RWYWx1ZXNQYXRoUGF0dGVyblxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvdWRGcm9udFBhdHRlcm5SZWdleChwYXR0ZXJuOiBzdHJpbmcpOiBSZWdFeHAge1xuICBjb25zdCBzb3VyY2UgPSBbLi4ucGF0dGVybl1cbiAgICAubWFwKChjaGFyKSA9PlxuICAgICAgY2hhciA9PT0gXCIqXCJcbiAgICAgICAgPyBcIi4qXCJcbiAgICAgICAgOiBjaGFyID09PSBcIj9cIlxuICAgICAgICAgID8gXCIuXCJcbiAgICAgICAgICA6IGNoYXIucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csIFwiXFxcXCQmXCIpLFxuICAgIClcbiAgICAuam9pbihcIlwiKTtcbiAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3NvdXJjZX0kYCk7XG59XG5cbi8qKiBUaGUgYmVoYXZpb3IgQ2xvdWRGcm9udCB3b3VsZCBwaWNrIGZvciBgdXJsYCwgYHVuZGVmaW5lZGAgZm9yIHRoZSBkZWZhdWx0IG9uZS4gKi9cbmZ1bmN0aW9uIGVkZ2VCZWhhdmlvckZvcihcbiAgYmVoYXZpb3JzOiByZWFkb25seSBFZGdlQmVoYXZpb3JbXSxcbiAgdXJsOiBzdHJpbmcsXG4pOiBFZGdlQmVoYXZpb3IgfCB1bmRlZmluZWQge1xuICByZXR1cm4gYmVoYXZpb3JzLmZpbmQoKGJlaGF2aW9yKSA9PiBiZWhhdmlvci5yZWdleC50ZXN0KHVybCkpO1xufVxuXG5mdW5jdGlvbiB0ZW1wbGF0ZXNCeUdyb3VwKFxuICBncm91cHM6IHJlYWRvbmx5IEZ1bmN0aW9uR3JvdXBTcGVjW10sXG4gIGVudHJpZXM6IHJlYWRvbmx5IFJvdXRlRW50cnlbXSxcbiAgZ3JvdXBPZkVudHJ5cG9pbnQ6IFJlYWRvbmx5TWFwPHN0cmluZywgc3RyaW5nPixcbik6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiB7XG4gIGNvbnN0IGFzc2lnbmVkOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4gPSB7XG4gICAgW0RFRkFVTFRfRlVOQ1RJT05fR1JPVVBdOiBbXSxcbiAgfTtcbiAgZm9yIChjb25zdCBncm91cCBvZiBncm91cHMpIHtcbiAgICBhc3NpZ25lZFtncm91cC5uYW1lXSA9IFtdO1xuICB9XG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGNvbnN0IGdyb3VwID1cbiAgICAgIGdyb3VwT2ZFbnRyeXBvaW50LmdldChlbnRyeS5lbnRyeXBvaW50SWQpID8/IERFRkFVTFRfRlVOQ1RJT05fR1JPVVA7XG4gICAgYXNzaWduZWRbZ3JvdXBdLnB1c2goZW50cnkudGVtcGxhdGUpO1xuICB9XG4gIHJldHVybiBhc3NpZ25lZDtcbn1cblxuLyoqXG4gKiBQdXQgZWFjaCBpbnRlcmNlcHRpbmcgZmlsZSBpbiB0aGUgZ3JvdXAgb2YgdGhlIFVSTCBpdCBpbnRlcmNlcHRzLlxuICpcbiAqIFdpdGggYC9mZWVkLyoqYCBncm91cGVkLCBgYXBwL2ZlZWQvKC4uKXBob3RvL1tpZF0vcGFnZS50c3hgIG1hdGNoZWQgaXQgYW5kXG4gKiBtb3ZlZCB0byB0aGUgZmVlZCBncm91cC4gQnV0IHRoZSBzb2Z0IG5hdmlnYXRpb24gaXQgZXhpc3RzIGZvciByZXF1ZXN0c1xuICogYC9waG90by8xYCB3aXRoIGEgYE5leHQtVXJsOiAvZmVlZGAgaGVhZGVyOyBDbG91ZEZyb250IHJvdXRlcyBvbiB0aGUgVVJMIGFsb25lLFxuICogc28gdGhlIHJlcXVlc3QgcmVhY2hlcyB3aGljaGV2ZXIgZnVuY3Rpb24gb3ducyBgL3Bob3RvLypgLCB3aGVyZSBOZXh0LmpzJ3NcbiAqIGludGVyY2VwdGlvbiByZXdyaXRlIChhIGBiZWZvcmVGaWxlc2AgcnVsZSBvbiB0aGF0IGhlYWRlcikgcmVzb2x2ZXMgaXQgdG8gdGhlXG4gKiBpbnRlcmNlcHRpbmcgZmlsZSDigJQgd2hpY2ggdGhhdCBmdW5jdGlvbiBkaWQgbm90IGhhdmUuXG4gKlxuICogTW92aW5nIHRoZSBmaWxlIHRoZXJlIGlzIGFsd2F5cyBwb3NzaWJsZSB1bmxlc3MgdGhlIGludGVyY2VwdGVkIFVSTCBzcGFjZSBpc1xuICogaXRzZWxmIHNwbGl0OiBgL3Bob3RvL1tpZF1gIGluIHRoZSBkZWZhdWx0IGdyb3VwIHdpdGggYC9waG90by8xYCBncm91cGVkXG4gKiBlbHNld2hlcmUgd291bGQgbmVlZCB0aGUgZmlsZSBpbiBib3RoLiBUaGF0IHRocm93cy5cbiAqL1xuZnVuY3Rpb24gcmVhc3NpZ25JbnRlcmNlcHRpbmdGaWxlcyhcbiAgZW50cmllczogcmVhZG9ubHkgUm91dGVFbnRyeVtdLFxuICBncm91cE9mRW50cnlwb2ludDogTWFwPHN0cmluZywgc3RyaW5nPixcbiAgYmVoYXZpb3JzOiByZWFkb25seSBFZGdlQmVoYXZpb3JbXSxcbiAgZWRnZTogRWRnZU9wdGlvbnMsXG4pOiB2b2lkIHtcbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgY29uc3QgcGF0aCA9IHN0cmlwQmFzZVBhdGgoZW50cnkudGVtcGxhdGUsIGVkZ2UuYmFzZVBhdGgpO1xuICAgIGlmIChwYXRoID09PSB1bmRlZmluZWQgfHwgaXNJbnRlcm5hbFRlbXBsYXRlKHBhdGgpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgdGFyZ2V0ID0gaW50ZXJjZXB0ZWRSb3V0ZShwYXRoKTtcbiAgICBpZiAodGFyZ2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCB1cmwgPSB3aXRoQmFzZVBhdGgodGFyZ2V0LCBlZGdlLmJhc2VQYXRoKTtcbiAgICBjb25zdCBncm91cCA9XG4gICAgICBlZGdlQmVoYXZpb3JGb3IoYmVoYXZpb3JzLCB1cmwpPy5ncm91cCA/PyBERUZBVUxUX0ZVTkNUSU9OX0dST1VQO1xuICAgIGNvbnN0IGludGVyY2VwdGVkID0gdGVtcGxhdGVSZWdleCh1cmwpO1xuICAgIGNvbnN0IHNwbGl0ID0gYmVoYXZpb3JzLmZpbmQoXG4gICAgICAoYmVoYXZpb3IpID0+XG4gICAgICAgIGJlaGF2aW9yLmdyb3VwICE9PSBncm91cCAmJlxuICAgICAgICAhYmVoYXZpb3IucGF0dGVybi5zdGFydHNXaXRoKFwiX25leHQvZGF0YS9cIikgJiZcbiAgICAgICAgc2FtcGxlVXJsKGJlaGF2aW9yLnJvdXRlLCBlZGdlLmJhc2VQYXRoKS5zb21lKChpdCkgPT5cbiAgICAgICAgICBpbnRlcmNlcHRlZC50ZXN0KGl0KSxcbiAgICAgICAgKSxcbiAgICApO1xuICAgIGlmIChzcGxpdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtFUlJPUl9QUkVGSVh9XCIke2VudHJ5LmVudHJ5cG9pbnRJZH1cIiBpcyB0aGUgaW50ZXJjZXB0aW9uIHJvdXRlIGAgK1xuICAgICAgICAgIGBcIiR7ZW50cnkudGVtcGxhdGV9XCIsIHdoaWNoIE5leHQuanMgcmVhY2hlcyBieSByZXdyaXRpbmcgYSByZXF1ZXN0IGZvciBgICtcbiAgICAgICAgICBgXCIke3VybH1cIiBpbnNpZGUgd2hpY2hldmVyIGZ1bmN0aW9uIENsb3VkRnJvbnQgc2VudCBpdCB0byDigJQgc28gaXQgaXMgYCArXG4gICAgICAgICAgYHBhY2thZ2VkIHdpdGggdGhlIGdyb3VwIHRoYXQgb3ducyBcIiR7dXJsfVwiLiBUaGF0IFVSTCBzcGFjZSBpcyBzcGxpdCwgYCArXG4gICAgICAgICAgYHRob3VnaDogbW9zdCBvZiBpdCByZWFjaGVzICR7Z3JvdXBMYWJlbChncm91cCl9LCBidXQgZ3JvdXAgYCArXG4gICAgICAgICAgYFwiJHtzcGxpdC5ncm91cH1cIidzIHBhdHRlcm4gXCIke3NwbGl0LnJvdXRlfVwiIGNsYWltcyBwYXJ0IG9mIGl0LCBhbmQgYCArXG4gICAgICAgICAgYG9uZSBmaWxlIGNhbm5vdCBiZSBpbiBib3RoLiBSb3V0ZSBhbGwgb2YgXCIke3RhcmdldH1cIiB0byBvbmUgZ3JvdXAuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGdyb3VwT2ZFbnRyeXBvaW50LnNldChlbnRyeS5lbnRyeXBvaW50SWQsIGdyb3VwKTtcbiAgfVxufVxuXG4vKiogQSBVUkwgYSBncm91cCBwYXR0ZXJuIHJvdXRlcywgdG8gdGVzdCBhZ2FpbnN0IGFub3RoZXIgcm91dGUncyBVUkwgc3BhY2UuICovXG5mdW5jdGlvbiBzYW1wbGVVcmwocm91dGU6IHN0cmluZywgYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIHJvdXRlLmVuZHNXaXRoKFNVQlRSRUVfU1VGRklYKVxuICAgID8gW2Ake2Jhc2VQYXRofSR7cm91dGUuc2xpY2UoMCwgLVNVQlRSRUVfU1VGRklYLmxlbmd0aCl9L19gXVxuICAgIDogW2Ake2Jhc2VQYXRofSR7cm91dGV9YF07XG59XG5cbi8qKiBUaGUgVVJMcyBhIHRlbXBsYXRlIHN0YW5kcyBmb3IsIGFzIGEgcmVnZXg6IGBbaWRdYCBpcyBvbmUgc2VnbWVudCwgYW5kIHNvIG9uLiAqL1xuZnVuY3Rpb24gdGVtcGxhdGVSZWdleCh0ZW1wbGF0ZTogc3RyaW5nKTogUmVnRXhwIHtcbiAgY29uc3Qgc291cmNlID0gdGVtcGxhdGVcbiAgICAuc3BsaXQoXCIvXCIpXG4gICAgLmZpbHRlcihCb29sZWFuKVxuICAgIC5tYXAoXG4gICAgICAoc2VnbWVudCkgPT5cbiAgICAgICAgW1xuICAgICAgICAgIGAvJHtzZWdtZW50LnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCBcIlxcXFwkJlwiKX1gLFxuICAgICAgICAgIFwiL1teL10rXCIsXG4gICAgICAgICAgXCIvLitcIixcbiAgICAgICAgICBcIig/Oi8uKyk/XCIsXG4gICAgICAgIF1bc2VnbWVudEtpbmQoc2VnbWVudCldLFxuICAgIClcbiAgICAuam9pbihcIlwiKTtcbiAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3NvdXJjZSB8fCBcIi9cIn0kYCk7XG59XG5cbi8qKlxuICogVGhyb3cgdW5sZXNzIGV2ZXJ5IFVSTCBlYWNoIGZpbGUgc2VydmVzIHJlYWNoZXMgdGhlIGdyb3VwIGhvbGRpbmcgaXQuXG4gKlxuICogQ2hlY2tlZCBmb3IgZXZlcnkgZmlsZSwgdGhlIGRlZmF1bHQgZ3JvdXAncyBpbmNsdWRlZDogdGhlIGludmFyaWFudCBpcyBcInRoZVxuICogZWRnZSBuZXZlciBzZW5kcyBhIHJlcXVlc3QgdG8gYSBmdW5jdGlvbiB3aXRob3V0IGl0cyBmaWxlXCIsIGFuZCBhIGdyb3VwXG4gKiBwYXR0ZXJuIGNhbiBicmVhayBpdCBieSBjbGFpbWluZyBhIFVSTCBvZiBhIGZpbGUgbGVmdCBpbiB0aGUgZGVmYXVsdCBncm91cCBhc1xuICogZWFzaWx5IGFzIGJ5IGxlYXZpbmcgb25lIGJlaGluZC4gQSBkeW5hbWljIHRlbXBsYXRlIHN0YW5kcyBmb3IgYSBVUkwgc3BhY2UsXG4gKiBub3Qgb25lIFVSTCwgc28gaXQgaXMgYWxzbyBjaGVja2VkIGFnYWluc3QgdGhlIHBhcnQgb2YgdGhhdCBzcGFjZSBvdGhlclxuICogZ3JvdXBzJyBwYXR0ZXJucyBjYXB0dXJlICh7QGxpbmsgY2FwdHVyZWREeW5hbWljVXJsc30pOiBhIGAvWy4uLnNsdWddYCBsZWZ0IGluXG4gKiB0aGUgZGVmYXVsdCBncm91cCBhbnN3ZXJzIGAvYmxvZy9hL2JgIHRvbywgd2hpY2ggYC9ibG9nLyoqYCBzZW5kcyBlbHNld2hlcmUuXG4gKlxuICogT25seSB0aGUgVVJMcyBhcyBOZXh0LmpzIHNwZWxscyB0aGVtIGFyZSByZXBsYXllZCwgYW5kIHRoYXQgaXMgYSBrbm93biBnYXBcbiAqIHJhdGhlciB0aGFuIGFuIG92ZXJzaWdodDogQ2xvdWRGcm9udCBwYXRoIHBhdHRlcm5zIGFuZCBBUEkgR2F0ZXdheSByZXNvdXJjZXNcbiAqIGJvdGggbWF0Y2ggY2FzZS1zZW5zaXRpdmVseSwgd2hpbGUgYEBuZXh0L3JvdXRpbmdgIG1hdGNoZXMgdGVtcGxhdGVzXG4gKiBjYXNlLWluc2Vuc2l0aXZlbHkuIGAvQVBJL3JlcG9ydHMvMWAgdGhlcmVmb3JlIG1pc3NlcyBhIGAvYXBpL3JlcG9ydHMvKipgXG4gKiBncm91cCBhbmQgcmVhY2hlcyB0aGUgZGVmYXVsdCBmdW5jdGlvbiwgd2hpY2ggcmVzb2x2ZXMgaXQgdG8gYSB0ZW1wbGF0ZSBpdFxuICogZG9lcyBub3QgaGF2ZS4gTmVpdGhlciBlZGdlIGNhbiBiZSB0b2xkIHRvIGZvbGQgY2FzZSwgYW5kIGxvd2VyY2FzaW5nIGF0IHRoZVxuICogZWRnZSB3b3VsZCBicmVhayB0aGUgY2FzZS1zZW5zaXRpdmUgUzMga2V5cyBiZWhpbmQgYHB1YmxpYy9gLCBzbyB0aGVyZSBpc1xuICogbm90aGluZyB0byBjaGVjayBoZXJlIHRoYXQgY291bGQgcGFzczsgdGhlIHJ1bnRpbWUgYW5zd2VycyBzdWNoIGEgcmVxdWVzdFxuICogaXRzZWxmIChzZWUgYG93bmVkUm91dGVFcnJvcmApLlxuICovXG5mdW5jdGlvbiBhc3NlcnRFZGdlUmVhY2hlc0V2ZXJ5RmlsZShcbiAgZW50cmllczogcmVhZG9ubHkgUm91dGVFbnRyeVtdLFxuICBncm91cE9mRW50cnlwb2ludDogUmVhZG9ubHlNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBiZWhhdmlvcnM6IHJlYWRvbmx5IEVkZ2VCZWhhdmlvcltdLFxuICBlZGdlOiBFZGdlT3B0aW9ucyxcbiAgcm91dGVyOiBSb3V0ZXIsXG4pOiB2b2lkIHtcbiAgY29uc3QgZmlsZXMgPSBuZXcgTWFwPHN0cmluZywgUm91dGVFbnRyeVtdPigpO1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBsaXN0ID0gZmlsZXMuZ2V0KGVudHJ5LmVudHJ5cG9pbnRJZCkgPz8gW107XG4gICAgbGlzdC5wdXNoKGVudHJ5KTtcbiAgICBmaWxlcy5zZXQoZW50cnkuZW50cnlwb2ludElkLCBsaXN0KTtcbiAgfVxuICAvLyBEZWVwIGVub3VnaCBmb3IgYSBzYW1wbGUgdG8gZ2V0IHBhc3QgZXZlcnkgdGVtcGxhdGUgYSBjYXB0dXJpbmcgZ3JvdXBcbiAgLy8gY291bGQgc2hhZG93IGl0IHdpdGguXG4gIGNvbnN0IGRlZXBlc3QgPVxuICAgIE1hdGgubWF4KFxuICAgICAgMCxcbiAgICAgIC4uLmVudHJpZXMubWFwKChlbnRyeSkgPT4ge1xuICAgICAgICBjb25zdCBwYXRoID0gc3RyaXBCYXNlUGF0aChlbnRyeS50ZW1wbGF0ZSwgZWRnZS5iYXNlUGF0aCk7XG4gICAgICAgIHJldHVybiBwYXRoICE9PSB1bmRlZmluZWQgJiYgaXNSb3V0YWJsZVBhdGgocGF0aClcbiAgICAgICAgICA/IHBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKS5sZW5ndGhcbiAgICAgICAgICA6IDA7XG4gICAgICB9KSxcbiAgICApICsgMTtcbiAgZm9yIChjb25zdCBbZmlsZSwgZmlsZUVudHJpZXNdIG9mIGZpbGVzKSB7XG4gICAgY29uc3Qgb3duZXIgPSBncm91cE9mRW50cnlwb2ludC5nZXQoZmlsZSkgPz8gREVGQVVMVF9GVU5DVElPTl9HUk9VUDtcbiAgICBjb25zdCBtaXNyb3V0ZWQ6IE1pc3JvdXRlW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGZpbGVFbnRyaWVzKSB7XG4gICAgICBmb3IgKGNvbnN0IHVybCBvZiBzZXJ2ZWRVcmxzKGVudHJ5LnRlbXBsYXRlLCBlbnRyeS50eXBlLCBlZGdlKSkge1xuICAgICAgICBjb25zdCBiZWhhdmlvciA9IGVkZ2VCZWhhdmlvckZvcihiZWhhdmlvcnMsIHVybCk7XG4gICAgICAgIGNvbnN0IGdyb3VwID0gYmVoYXZpb3I/Lmdyb3VwID8/IERFRkFVTFRfRlVOQ1RJT05fR1JPVVA7XG4gICAgICAgIGlmIChncm91cCAhPT0gb3duZXIgJiYgIW1pc3JvdXRlZC5zb21lKChpdCkgPT4gaXQudXJsID09PSB1cmwpKSB7XG4gICAgICAgICAgbWlzcm91dGVkLnB1c2goeyB1cmwsIGdyb3VwLCByb3V0ZTogYmVoYXZpb3I/LnJvdXRlIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGl0IG9mIGNhcHR1cmVkRHluYW1pY1VybHMoXG4gICAgICAgIGVudHJ5LFxuICAgICAgICBvd25lcixcbiAgICAgICAgZGVlcGVzdCxcbiAgICAgICAgYmVoYXZpb3JzLFxuICAgICAgICBlZGdlLFxuICAgICAgICByb3V0ZXIsXG4gICAgICApKSB7XG4gICAgICAgIGlmICghbWlzcm91dGVkLnNvbWUoKGtub3duKSA9PiBrbm93bi51cmwgPT09IGl0LnVybCkpIHtcbiAgICAgICAgICBtaXNyb3V0ZWQucHVzaChpdCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG1pc3JvdXRlZC5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IobWlzcm91dGVkRmlsZU1lc3NhZ2UoZmlsZSwgb3duZXIsIG1pc3JvdXRlZCwgZWRnZSkpO1xuICAgIH1cbiAgfVxufVxuXG5pbnRlcmZhY2UgTWlzcm91dGUge1xuICByZWFkb25seSB1cmw6IHN0cmluZztcbiAgLyoqIFdoZXJlIENsb3VkRnJvbnQgc2VuZHMgaXQuICovXG4gIHJlYWRvbmx5IGdyb3VwOiBzdHJpbmc7XG4gIC8qKiBUaGUgcGF0dGVybiB0aGF0IHNlbnQgaXQgdGhlcmUsIGB1bmRlZmluZWRgIGZvciB0aGUgZGVmYXVsdCBiZWhhdmlvci4gKi9cbiAgcmVhZG9ubHkgcm91dGU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBTZXQgd2hlbiBgdXJsYCBpcyBhIHNhbXBsZSBvZiBhIGR5bmFtaWMgdGVtcGxhdGUncyBVUkwgc3BhY2UgcmF0aGVyIHRoYW5cbiAgICogYSBVUkwgdGhlIHRlbXBsYXRlIHNwZWxsczogdGhlIHRlbXBsYXRlIE5leHQuanMgcmVzb2x2ZXMgaXQgdG8gdGhlcmUuXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZWRBcz86IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdGFuZHMgaW4gZm9yIFwiYW55IHZhbHVlXCIgb2YgYSBkeW5hbWljIHNlZ21lbnQgaW4gYSBzYW1wbGUgVVJMLiBBIGxpdGVyYWxcbiAqIHRlbXBsYXRlIG9mIHRoYXQgZXhhY3QgbmFtZSB3b3VsZCBzaGFkb3cgaXQsIHdoaWNoIGNhbiBvbmx5IGhpZGUgYSBtaXNyb3V0ZSxcbiAqIG5ldmVyIGludmVudCBvbmUuXG4gKi9cbmNvbnN0IEFOWV9TRUdNRU5UID0gXCJfXCI7XG5cbi8qKlxuICogV2hldGhlciBhIHJlcXVlc3QgY2FuIHJlc29sdmUgdG8gYHBhdGhgIChiYXNlUGF0aCBzdHJpcHBlZCkgZGlyZWN0bHk6IG5vdCBhblxuICogUlNDIG9yIHNlZ21lbnQgcmV3cml0ZSwgYW4gaW50ZXJjZXB0aW9uIHJvdXRlLCBvciBhIGRhdGEtVVJMIGFsaWFzIChhIGRhdGEgVVJMXG4gKiByZXNvbHZlcyB0byB0aGUgcGFnZSBpdCBuYW1lcykuXG4gKi9cbmZ1bmN0aW9uIGlzUm91dGFibGVQYXRoKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgICFpc0ludGVybmFsVGVtcGxhdGUocGF0aCkgJiZcbiAgICAhaXNJbnRlcmNlcHRpb25UZW1wbGF0ZShwYXRoKSAmJlxuICAgICFwYXRoLnN0YXJ0c1dpdGgoXCIvX25leHQvZGF0YS9cIilcbiAgKTtcbn1cblxuLyoqIDAgc3RhdGljLCAxIGBbcGFyYW1dYCwgMiBgWy4uLmNhdGNoQWxsXWAsIDMgYFtbLi4ub3B0aW9uYWxdXWAuICovXG5mdW5jdGlvbiBzZWdtZW50S2luZChzZWdtZW50OiBzdHJpbmcpOiBudW1iZXIge1xuICBpZiAoT1BUSU9OQUxfQ0FUQ0hfQUxMX1NFR01FTlQudGVzdChzZWdtZW50KSkge1xuICAgIHJldHVybiAzO1xuICB9XG4gIGlmICgvXlxcW1xcLlxcLlxcLlteXFxdXStcXF0kLy50ZXN0KHNlZ21lbnQpKSB7XG4gICAgcmV0dXJuIDI7XG4gIH1cbiAgcmV0dXJuIC9eXFxbW15cXF1dK1xcXSQvLnRlc3Qoc2VnbWVudCkgPyAxIDogMDtcbn1cblxuLyoqXG4gKiBUaGUgVVJMcyBvZiBhICpkeW5hbWljKiB0ZW1wbGF0ZSdzIHNwYWNlIHRoYXQgYW5vdGhlciBncm91cCdzIGJlaGF2aW9yXG4gKiBjYXB0dXJlcywgYW5kIHRoYXQgTmV4dC5qcyDigJQgcnVubmluZyBpbiB0aGF0IGdyb3VwJ3MgZnVuY3Rpb24g4oCUIHN0aWxsXG4gKiByZXNvbHZlcyB0byB0aGlzIHRlbXBsYXRlJ3MgZmlsZS5cbiAqXG4gKiBgc2VydmVkVXJsc2AgcmVwbGF5cyB0aGUgdGVtcGxhdGUgYXMgc3BlbGxlZCwgd2hpY2ggaXMgZXhhY3QgZm9yIGEgc3RhdGljXG4gKiByb3V0ZSBidXQgbm90IGZvciBgL1suLi5zbHVnXWA6IHRoZSB0ZXh0IGAvWy4uLnNsdWddYCBuZXZlciBtYXRjaGVzIGBibG9nLypgLFxuICogeWV0IGAvYmxvZy9hL2JgIGRvZXMsIHJlYWNoZXMgdGhlIGJsb2cgZnVuY3Rpb24sIGFuZCByZXNvbHZlcyB0aGVyZSB0b1xuICogYC9bLi4uc2x1Z11gLCB3aGljaCB0aGUgYmxvZyB6aXAgbGFja3MuIFNvIGVhY2ggb3RoZXIgZ3JvdXAncyBiZWhhdmlvciBpc1xuICogaW50ZXJzZWN0ZWQgd2l0aCB0aGUgdGVtcGxhdGUncyBVUkwgc3BhY2UsIG9uZSBzYW1wbGUgVVJMIHBlciBzaGFwZVxuICogKHtAbGluayBzYW1wbGVUZW1wbGF0ZVBhdGhzfSksIGFuZCBlYWNoIHNhbXBsZSBpcyByZXNvbHZlZCB0aGUgd2F5IE5leHQuanNcbiAqIHJlc29sdmVzIGl0ICh7QGxpbmsgcmVzb2x2ZUZpbGV9KS4gQSBtb3JlIHNwZWNpZmljIHRlbXBsYXRlIGluIHRoZSBjYXB0dXJpbmdcbiAqIGdyb3VwIGxlZ2l0aW1hdGVseSBzaGFkb3dzIHRoZSBzYW1wbGUgKGAvYmxvZy9bc2x1Z11gIGFuc3dlcnMgYC9ibG9nL19gLCBzb1xuICogb25seSBgL2Jsb2cvXy9fYCBpcyBhIG1pc3JvdXRlKTsgYW55dGhpbmcgaXQgZG9lcyBub3Qgc2hhZG93IGlzIGZsYWdnZWQuXG4gKi9cbmZ1bmN0aW9uIGNhcHR1cmVkRHluYW1pY1VybHMoXG4gIGVudHJ5OiBSb3V0ZUVudHJ5LFxuICBvd25lcjogc3RyaW5nLFxuICBkZWVwZXN0OiBudW1iZXIsXG4gIGJlaGF2aW9yczogcmVhZG9ubHkgRWRnZUJlaGF2aW9yW10sXG4gIGVkZ2U6IEVkZ2VPcHRpb25zLFxuICByb3V0ZXI6IFJvdXRlcixcbik6IE1pc3JvdXRlW10ge1xuICBjb25zdCBwYXRoID0gc3RyaXBCYXNlUGF0aChlbnRyeS50ZW1wbGF0ZSwgZWRnZS5iYXNlUGF0aCk7XG4gIGlmIChcbiAgICBwYXRoID09PSB1bmRlZmluZWQgfHxcbiAgICAhcGF0aC5pbmNsdWRlcyhcIltcIikgfHxcbiAgICBFUlJPUl9QQUdFX1NVRkZJWEVTLmluY2x1ZGVzKHBhdGgpIHx8XG4gICAgIWlzUm91dGFibGVQYXRoKHBhdGgpXG4gICkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICBjb25zdCBzZWdtZW50cyA9IHBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3Qgc2FtcGxlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IGJlaGF2aW9yIG9mIGJlaGF2aW9ycykge1xuICAgIGlmIChcbiAgICAgIGJlaGF2aW9yLmdyb3VwID09PSBvd25lciB8fFxuICAgICAgYmVoYXZpb3IucGF0dGVybi5zdGFydHNXaXRoKFwiX25leHQvZGF0YS9cIilcbiAgICApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBiYXJlID0gYmVoYXZpb3IucGF0dGVybi5yZXBsYWNlKC9cXC8kLywgXCJcIik7XG4gICAgY29uc3QgaXNTdWJ0cmVlID0gYmFyZS5lbmRzV2l0aChcIi8qXCIpO1xuICAgIGNvbnN0IHByZWZpeCA9IChpc1N1YnRyZWUgPyBiYXJlLnNsaWNlKDAsIC0yKSA6IGJhcmUpXG4gICAgICAuc3BsaXQoXCIvXCIpXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pO1xuICAgIGZvciAoY29uc3Qgc2FtcGxlIG9mIHNhbXBsZVRlbXBsYXRlUGF0aHMoXG4gICAgICBzZWdtZW50cyxcbiAgICAgIHByZWZpeCxcbiAgICAgIGlzU3VidHJlZSxcbiAgICAgIE1hdGgubWF4KGRlZXBlc3QsIHByZWZpeC5sZW5ndGggKyAxKSxcbiAgICApKSB7XG4gICAgICBzYW1wbGVzLmFkZChzYW1wbGUpO1xuICAgIH1cbiAgfVxuICBjb25zdCBtaXNyb3V0ZWQ6IE1pc3JvdXRlW10gPSBbXTtcbiAgLy8gYHJlc29sdmVkYCBpcyBgdXJsYCBhcyBOZXh0LmpzIG1hdGNoZXMgaXQ6IHdpdGhvdXQgdGhlIHRyYWlsaW5nIHNsYXNoLlxuICBjb25zdCBjaGVjayA9ICh1cmw6IHN0cmluZywgcmVzb2x2ZWQ6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IGJlaGF2aW9yID0gZWRnZUJlaGF2aW9yRm9yKGJlaGF2aW9ycywgdXJsKTtcbiAgICBjb25zdCBncm91cCA9IGJlaGF2aW9yPy5ncm91cCA/PyBERUZBVUxUX0ZVTkNUSU9OX0dST1VQO1xuICAgIGlmIChncm91cCA9PT0gb3duZXIgfHwgbWlzcm91dGVkLnNvbWUoKGl0KSA9PiBpdC51cmwgPT09IHVybCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHJlc29sdmVGaWxlKHJlc29sdmVkLCByb3V0ZXIpID09PSBlbnRyeS5lbnRyeXBvaW50SWQpIHtcbiAgICAgIG1pc3JvdXRlZC5wdXNoKHtcbiAgICAgICAgdXJsLFxuICAgICAgICBncm91cCxcbiAgICAgICAgcm91dGU6IGJlaGF2aW9yPy5yb3V0ZSxcbiAgICAgICAgc2VydmVkQXM6IGVudHJ5LnRlbXBsYXRlLFxuICAgICAgfSk7XG4gICAgfVxuICB9O1xuICBmb3IgKGNvbnN0IHNhbXBsZSBvZiBzYW1wbGVzKSB7XG4gICAgZm9yIChjb25zdCB7IHVybCwgcmVzb2x2ZWQgfSBvZiB1cmxWYXJpYW50cyhzYW1wbGUsIGVudHJ5LnR5cGUsIGVkZ2UpKSB7XG4gICAgICBjaGVjayh1cmwsIHJlc29sdmVkKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG1pc3JvdXRlZDtcbn1cblxuLyoqXG4gKiBTYW1wbGUgcGF0aHMgaW4gYm90aCBhIHRlbXBsYXRlJ3MgVVJMIHNwYWNlIGFuZCBhIGJlaGF2aW9yJ3M6IGZvciBhIHN1YnRyZWVcbiAqIGBwcmVmaXgvKmAsIGV2ZXJ5IHdheSB0aGUgdGVtcGxhdGUncyBzZWdtZW50cyBjYW4gbGluZSB1cCB3aXRoIGBwcmVmaXhgIGFuZFxuICogY29udGludWUgcGFzdCBpdCwgb25lIHNhbXBsZSBwZXIgcmVzdWx0aW5nIGxlbmd0aCB1cCB0byBgbWF4RGVwdGhgLCB3aXRoXG4gKiB7QGxpbmsgQU5ZX1NFR01FTlR9IGZvciBlYWNoIGR5bmFtaWMgdmFsdWUgYmV5b25kIHRoZSBwcmVmaXguIEZvciBhbiBleGFjdFxuICogcGF0dGVybiwgdGhlIHBhdHRlcm4ncyBvd24gcGF0aCBpZiB0aGUgdGVtcGxhdGUgbWF0Y2hlcyBpdC5cbiAqL1xuZnVuY3Rpb24gc2FtcGxlVGVtcGxhdGVQYXRocyhcbiAgdGVtcGxhdGU6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBwcmVmaXg6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBpc1N1YnRyZWU6IGJvb2xlYW4sXG4gIG1heERlcHRoOiBudW1iZXIsXG4pOiBzdHJpbmdbXSB7XG4gIGlmICghaXNTdWJ0cmVlKSB7XG4gICAgY29uc3QgcGF0aCA9IGAvJHtwcmVmaXguam9pbihcIi9cIil9YDtcbiAgICByZXR1cm4gdGVtcGxhdGVSZWdleChgLyR7dGVtcGxhdGUuam9pbihcIi9cIil9YCkudGVzdChwYXRoKSA/IFtwYXRoXSA6IFtdO1xuICB9XG4gIGNvbnN0IHZhbHVlQXQgPSAoYXQ6IG51bWJlcikgPT5cbiAgICBhdCA8IHByZWZpeC5sZW5ndGggPyBwcmVmaXhbYXRdIDogQU5ZX1NFR01FTlQ7XG4gIGNvbnN0IHJlc3VsdHM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHdhbGsgPSAoaW5kZXg6IG51bWJlciwgYWNjOiByZWFkb25seSBzdHJpbmdbXSk6IHZvaWQgPT4ge1xuICAgIGlmIChpbmRleCA9PT0gdGVtcGxhdGUubGVuZ3RoKSB7XG4gICAgICAvLyBFeGFjdGx5IHRoZSBwcmVmaXggaXMga2VwdCB0b286IGBwcmVmaXgvKmAgbWF0Y2hlcyBpdHMgdHJhaWxpbmctc2xhc2hcbiAgICAgIC8vIGZvcm0sIHdoaWNoIGBjaGVja2AgYWRkcyBmb3IgYSBgdHJhaWxpbmdTbGFzaGAgYXBwLlxuICAgICAgaWYgKGFjYy5sZW5ndGggPj0gcHJlZml4Lmxlbmd0aCkge1xuICAgICAgICByZXN1bHRzLnB1c2goYC8ke2FjYy5qb2luKFwiL1wiKX1gKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3Qgc2VnbWVudCA9IHRlbXBsYXRlW2luZGV4XTtcbiAgICBjb25zdCBhdCA9IGFjYy5sZW5ndGg7XG4gICAgY29uc3Qga2luZCA9IHNlZ21lbnRLaW5kKHNlZ21lbnQpO1xuICAgIGlmIChraW5kID09PSAwKSB7XG4gICAgICBpZiAoYXQgPj0gcHJlZml4Lmxlbmd0aCB8fCBwcmVmaXhbYXRdID09PSBzZWdtZW50KSB7XG4gICAgICAgIHdhbGsoaW5kZXggKyAxLCBbLi4uYWNjLCBzZWdtZW50XSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChraW5kID09PSAxKSB7XG4gICAgICB3YWxrKGluZGV4ICsgMSwgWy4uLmFjYywgdmFsdWVBdChhdCldKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChsZXQgY291bnQgPSBraW5kID09PSAyID8gMSA6IDA7IGF0ICsgY291bnQgPD0gbWF4RGVwdGg7IGNvdW50KyspIHtcbiAgICAgIGNvbnN0IHRha2VuID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogY291bnQgfSwgKF8sIGkpID0+IHZhbHVlQXQoYXQgKyBpKSk7XG4gICAgICB3YWxrKGluZGV4ICsgMSwgWy4uLmFjYywgLi4udGFrZW5dKTtcbiAgICB9XG4gIH07XG4gIHdhbGsoMCwgW10pO1xuICByZXR1cm4gcmVzdWx0cztcbn1cblxuLyoqXG4gKiBUaGUgVVJMcyBvbmUgdGVtcGxhdGUncyBmaWxlIGFuc3dlcnMgYXQgdGhlIGVkZ2UuXG4gKlxuICogTm90aGluZyBmb3IgdGhlIGVycm9yIHBhZ2VzIChldmVyeSBncm91cCBzdGFnZXMgdGhlbSksIHRoZSBSU0MgYW5kXG4gKiBzZWdtZW50LXByZWZldGNoIHJld3JpdGVzIChyZXF1ZXN0ZWQgYXQgdGhlIHBhZ2UncyBvd24gVVJMKSwgYW5kIGludGVyY2VwdGlvblxuICogcm91dGVzIChyZWFjaGVkIG9ubHkgdGhyb3VnaCB0aGUgaW50ZXJjZXB0ZWQgVVJMJ3MgcmV3cml0ZSkuIE90aGVyd2lzZSB0aGVcbiAqIHRlbXBsYXRlIGl0c2VsZiwgYW4gb3B0aW9uYWwgY2F0Y2gtYWxsJ3MgcGFyZW50LCBhbmQgZm9yIGVhY2ggb2YgdGhvc2UgdGhlXG4gKiBgdHJhaWxpbmdTbGFzaGAgZm9ybSBhbmQgYSBQYWdlcyBSb3V0ZXIgcGFnZSdzIGRhdGEgVVJMLiBPbmx5IHRoZSBzbGFzaC1sZXNzXG4gKiBkYXRhIFVSTDogdGhlIGNsaWVudCBuZXZlciBhZGRzIG9uZS5cbiAqL1xuZnVuY3Rpb24gc2VydmVkVXJscyhcbiAgdGVtcGxhdGU6IHN0cmluZyxcbiAgdHlwZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBlZGdlOiBFZGdlT3B0aW9ucyxcbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgcGF0aCA9IHN0cmlwQmFzZVBhdGgodGVtcGxhdGUsIGVkZ2UuYmFzZVBhdGgpO1xuICBpZiAoXG4gICAgcGF0aCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgRVJST1JfUEFHRV9TVUZGSVhFUy5pbmNsdWRlcyhwYXRoKSB8fFxuICAgIGlzSW50ZXJuYWxUZW1wbGF0ZShwYXRoKSB8fFxuICAgIGlzSW50ZXJjZXB0aW9uVGVtcGxhdGUocGF0aClcbiAgKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGlmIChwYXRoLnN0YXJ0c1dpdGgoXCIvX25leHQvZGF0YS9cIikpIHtcbiAgICByZXR1cm4gW3RlbXBsYXRlXTtcbiAgfVxuICBjb25zdCBwYXRocyA9IFtwYXRoXTtcbiAgY29uc3Qgb3B0aW9uYWwgPSAvXiguKilcXC8oXFxbXFxbXFwuXFwuXFwuW15cXF0vXStcXF1cXF0pJC8uZXhlYyhwYXRoKTtcbiAgaWYgKG9wdGlvbmFsKSB7XG4gICAgcGF0aHMucHVzaChvcHRpb25hbFsxXSB8fCBcIi9cIik7XG4gIH1cbiAgcmV0dXJuIHBhdGhzLmZsYXRNYXAoKGl0KSA9PlxuICAgIHVybFZhcmlhbnRzKGl0LCB0eXBlLCBlZGdlKS5tYXAoKHsgdXJsIH0pID0+IHVybCksXG4gICk7XG59XG5cbi8qKlxuICogQSBwYXRoJ3MgVVJMLCBpdHMgYHRyYWlsaW5nU2xhc2hgIGZvcm0gYW5kIGEgUGFnZXMgUm91dGVyIHBhZ2UncyBkYXRhIFVSTCxcbiAqIGVhY2ggd2l0aCBgcmVzb2x2ZWRgOiB0aGUgVVJMIGFzIE5leHQuanMgbWF0Y2hlcyBpdCwgd2l0aG91dCB0aGUgdHJhaWxpbmcgc2xhc2guXG4gKi9cbmZ1bmN0aW9uIHVybFZhcmlhbnRzKFxuICBwYXRoOiBzdHJpbmcsXG4gIHR5cGU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgZWRnZTogRWRnZU9wdGlvbnMsXG4pOiB7IHVybDogc3RyaW5nOyByZXNvbHZlZDogc3RyaW5nIH1bXSB7XG4gIGNvbnN0IHVybCA9IHdpdGhCYXNlUGF0aChwYXRoLCBlZGdlLmJhc2VQYXRoKTtcbiAgY29uc3QgdmFyaWFudHMgPSBbeyB1cmwsIHJlc29sdmVkOiB1cmwgfV07XG4gIGlmIChlZGdlLnRyYWlsaW5nU2xhc2ggJiYgcGF0aCAhPT0gXCIvXCIpIHtcbiAgICB2YXJpYW50cy5wdXNoKHsgdXJsOiBgJHt1cmx9L2AsIHJlc29sdmVkOiB1cmwgfSk7XG4gIH1cbiAgaWYgKHR5cGUgPT09IFwicGFnZVwiICYmIGVkZ2UuYnVpbGRJZCkge1xuICAgIGNvbnN0IGRhdGEgPSBgJHtlZGdlLmJhc2VQYXRofS9fbmV4dC9kYXRhLyR7ZWRnZS5idWlsZElkfSR7cGF0aCA9PT0gXCIvXCIgPyBcIi9pbmRleFwiIDogcGF0aH0uanNvbmA7XG4gICAgdmFyaWFudHMucHVzaCh7IHVybDogZGF0YSwgcmVzb2x2ZWQ6IGRhdGEgfSk7XG4gIH1cbiAgcmV0dXJuIHZhcmlhbnRzO1xufVxuXG5mdW5jdGlvbiBtaXNyb3V0ZWRGaWxlTWVzc2FnZShcbiAgZmlsZTogc3RyaW5nLFxuICBvd25lcjogc3RyaW5nLFxuICBtaXNyb3V0ZWQ6IHJlYWRvbmx5IE1pc3JvdXRlW10sXG4gIGVkZ2U6IEVkZ2VPcHRpb25zLFxuKTogc3RyaW5nIHtcbiAgY29uc3Qgd2hlcmUgPSBtaXNyb3V0ZWRcbiAgICAubWFwKFxuICAgICAgKGl0KSA9PlxuICAgICAgICBgXCIke2l0LnVybH1cIiB0byAke2dyb3VwTGFiZWwoaXQuZ3JvdXApfWAgK1xuICAgICAgICAoaXQucm91dGUgPyBgIChpdHMgcGF0dGVybiBcIiR7aXQucm91dGV9XCIpYCA6IFwiXCIpLFxuICAgIClcbiAgICAuam9pbihcIiwgXCIpO1xuICBjb25zdCBoZWFkID1cbiAgICBgJHtFUlJPUl9QUkVGSVh9XCIke2ZpbGV9XCIgaXMgcGFja2FnZWQgaW50byAke2dyb3VwTGFiZWwob3duZXIpfSwgYnV0IGAgK1xuICAgIGBDbG91ZEZyb250IHdvdWxkIHNlbmQgJHt3aGVyZX0sIHdob3NlIGZ1bmN0aW9uIGRvZXMgbm90IGhhdmUgaXQ6IGEgNDA0IG9uIGAgK1xuICAgIGBldmVyeSBzdWNoIHJlcXVlc3QuIEV2ZXJ5IFVSTCBvbmUgZmlsZSBzZXJ2ZXMgaGFzIHRvIHJlYWNoIHRoZSBncm91cCB0aGF0IGAgK1xuICAgIGBob2xkcyB0aGUgZmlsZS5gO1xuICBjb25zdCBjYXB0dXJlZCA9IG1pc3JvdXRlZC5maWx0ZXIoKGl0KSA9PiBpdC5zZXJ2ZWRBcyAhPT0gdW5kZWZpbmVkKTtcbiAgaWYgKGNhcHR1cmVkLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCB0ZW1wbGF0ZXMgPSBbLi4ubmV3IFNldChjYXB0dXJlZC5tYXAoKGl0KSA9PiBgXCIke2l0LnNlcnZlZEFzfVwiYCkpXTtcbiAgICByZXR1cm4gKFxuICAgICAgYCR7aGVhZH0gVGhvc2UgVVJMcyBhcmUgcGFydCBvZiB0aGUgZHluYW1pYyByb3V0ZSBgICtcbiAgICAgIGAke3RlbXBsYXRlcy5qb2luKFwiLCBcIil9IChcIiR7QU5ZX1NFR01FTlR9XCIgc3RhbmRzIGZvciBhbnkgc2VnbWVudCBgICtcbiAgICAgIGB2YWx1ZSk6IHRoZSBwYXR0ZXJuIGNhcHR1cmVzIHRoZW0gYXQgdGhlIGVkZ2UsIGFuZCBubyByb3V0ZSBwYWNrYWdlZCBgICtcbiAgICAgIGBpbnRvIHRoZSBjYXB0dXJpbmcgZ3JvdXAgaXMgbW9yZSBzcGVjaWZpYywgc28gTmV4dC5qcyBzdGlsbCByZXNvbHZlcyBgICtcbiAgICAgIGB0aGVtIHRvIHRoaXMgZmlsZS4gR2l2ZSB0aGF0IGdyb3VwIGEgcm91dGUgdGhhdCBhbnN3ZXJzIHRoZW0gKGEgYCArXG4gICAgICBgY2F0Y2gtYWxsIHVuZGVyIGl0cyBwYXR0ZXJuLCBzYXkpLCBvciBuYXJyb3cgdGhlIHBhdHRlcm4uYFxuICAgICk7XG4gIH1cbiAgaWYgKG93bmVyID09PSBERUZBVUxUX0ZVTkNUSU9OX0dST1VQKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIGAke2hlYWR9IEEgcGF0dGVybiBjbGFpbXMgYSBVUkwgb2YgYSBmaWxlIHRoYXQgbm8gcGF0dGVybiBtb3ZlZDogbmFycm93IGAgK1xuICAgICAgYGl0LCBvciBnaXZlIHRoZSBncm91cCB0aGUgZmlsZSdzIG90aGVyIHJvdXRlcyB0b28uYFxuICAgICk7XG4gIH1cbiAgY29uc3QgdW5yb3V0YWJsZSA9IG1pc3JvdXRlZC5maWx0ZXIoXG4gICAgKGl0KSA9PiBzdWdnZXN0ZWRQYXR0ZXJuKGl0LnVybCwgZWRnZSkgPT09IHVuZGVmaW5lZCxcbiAgKTtcbiAgaWYgKHVucm91dGFibGUubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiAoXG4gICAgICBgJHtoZWFkfSAke3Vucm91dGFibGUubWFwKChpdCkgPT4gYFwiJHtpdC51cmx9XCJgKS5qb2luKFwiLCBcIil9IGNhbm5vdCBiZSBgICtcbiAgICAgIGByb3V0ZWQgdG8gYW55IGdyb3VwIOKAlCBDbG91ZEZyb250IGhhcyBubyBwYXR0ZXJuIGZvciB0aGUgaG9tZSBwYWdlIGFsb25lLCBgICtcbiAgICAgIGBhbmQgYSBkeW5hbWljIGZpcnN0IHNlZ21lbnQgd291bGQgbmVlZCBcIi8qKlwiIOKAlCBzbyB0aGlzIGZpbGUgY2FuIG9ubHkgYmUgYCArXG4gICAgICBgc2VydmVkIGJ5IHRoZSBcIiR7REVGQVVMVF9GVU5DVElPTl9HUk9VUH1cIiBncm91cC4gUmVtb3ZlIHRoZSBwYXR0ZXJuIHRoYXQgYCArXG4gICAgICBgbW92ZWQgaXQuIChBIFBhZ2VzIFJvdXRlciBob21lIHBhZ2UgaXMgYWxzbyBcIi9pbmRleFwiOiBvbmUgZmlsZS4pYFxuICAgICk7XG4gIH1cbiAgY29uc3Qgc3VnZ2VzdGlvbnMgPSBbXG4gICAgLi4ubmV3IFNldChtaXNyb3V0ZWQubWFwKChpdCkgPT4gc3VnZ2VzdGVkUGF0dGVybihpdC51cmwsIGVkZ2UpISkpLFxuICBdO1xuICByZXR1cm4gKFxuICAgIGAke2hlYWR9IEFkZCAke3N1Z2dlc3Rpb25zLm1hcCgoaXQpID0+IGBcIiR7aXR9XCJgKS5qb2luKFwiLCBcIil9IHRvIGdyb3VwIGAgK1xuICAgIGBcIiR7b3duZXJ9XCIncyByb3V0ZXMuYFxuICApO1xufVxuXG4vKipcbiAqIFRoZSBncm91cCBwYXR0ZXJuIHRoYXQgd291bGQgcm91dGUgYHVybGAsIGB1bmRlZmluZWRgIHdoZW4gbm9uZSBjYW46IGEgc3RhdGljXG4gKiBwYXRoIHJvdXRlcyBhcyBpdHNlbGYsIGEgZHluYW1pYyBvbmUgYXMgdGhlIHN1YnRyZWUgYWJvdmUgaXRzIGZpcnN0IGR5bmFtaWNcbiAqIHNlZ21lbnQsIGFuZCBhIGRhdGEgVVJMIG9yIGB0cmFpbGluZ1NsYXNoYCBmb3JtIGFzIHRoZSBwYWdlIGl0IGJlbG9uZ3MgdG8uXG4gKi9cbmZ1bmN0aW9uIHN1Z2dlc3RlZFBhdHRlcm4odXJsOiBzdHJpbmcsIGVkZ2U6IEVkZ2VPcHRpb25zKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgbGV0IHBhdGggPSBzdHJpcEJhc2VQYXRoKHVybCwgZWRnZS5iYXNlUGF0aCkgPz8gdXJsO1xuICBjb25zdCBkYXRhUHJlZml4ID0gYC9fbmV4dC9kYXRhLyR7ZWRnZS5idWlsZElkfS9gO1xuICBpZiAocGF0aC5zdGFydHNXaXRoKGRhdGFQcmVmaXgpICYmIHBhdGguZW5kc1dpdGgoXCIuanNvblwiKSkge1xuICAgIHBhdGggPSBgLyR7cGF0aC5zbGljZShkYXRhUHJlZml4Lmxlbmd0aCwgLVwiLmpzb25cIi5sZW5ndGgpfWA7XG4gICAgcGF0aCA9IHBhdGggPT09IFwiL2luZGV4XCIgPyBcIi9cIiA6IHBhdGg7XG4gIH1cbiAgaWYgKHBhdGgubGVuZ3RoID4gMSAmJiBwYXRoLmVuZHNXaXRoKFwiL1wiKSkge1xuICAgIHBhdGggPSBwYXRoLnNsaWNlKDAsIC0xKTtcbiAgfVxuICBjb25zdCBzZWdtZW50cyA9IHBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3QgZmlyc3REeW5hbWljID0gc2VnbWVudHMuZmluZEluZGV4KChzZWdtZW50KSA9PiBzZWdtZW50LnN0YXJ0c1dpdGgoXCJbXCIpKTtcbiAgaWYgKHNlZ21lbnRzLmxlbmd0aCA9PT0gMCB8fCBmaXJzdER5bmFtaWMgPT09IDApIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBmaXJzdER5bmFtaWMgPT09IC0xXG4gICAgPyBwYXRoXG4gICAgOiBgLyR7c2VnbWVudHMuc2xpY2UoMCwgZmlyc3REeW5hbWljKS5qb2luKFwiL1wiKX0ke1NVQlRSRUVfU1VGRklYfWA7XG59XG5cbi8qKlxuICogVGhyb3cgb24gYSBgbmV4dC5jb25maWdgIHJld3JpdGUgd2hvc2Ugc291cmNlIHJlYWNoZXMgb25lIGdyb3VwIGFuZCB3aG9zZVxuICogZGVzdGluYXRpb24gaXMgcGFja2FnZWQgaW50byBhbm90aGVyLlxuICpcbiAqIEEgcmV3cml0ZSBydW5zIGluc2lkZSB0aGUgZnVuY3Rpb24gdGhhdCByZWNlaXZlZCB0aGUgcmVxdWVzdCwgc29cbiAqIGAvb2xkLzpwYXRoKmAg4oaSIGAvbmV3YCB3aXRoIGAvbmV3LyoqYCBncm91cGVkIGFuZCBgL29sZGAgbm90IHNlbmRzIGAvb2xkL3hgIHRvXG4gKiB0aGUgZGVmYXVsdCBmdW5jdGlvbiwgd2hpY2ggcmV3cml0ZXMgaXQgdG8gYSBmaWxlIGl0IGxhY2tzLlxuICpcbiAqIE9ubHkgdGhlIHJld3JpdGVzIHdob3NlIGRlc3RpbmF0aW9uIGlzIGEgbGl0ZXJhbCBwYXRoIGNhbiBiZSByZXNvbHZlZCB0byBhXG4gKiBmaWxlIGhlcmU7IG9uZSBidWlsdCBmcm9tIHRoZSBzb3VyY2UncyBwYXJhbWV0ZXJzIChgL2Jsb2cvOnNsdWdgIOKGklxuICogYC9wb3N0cy86c2x1Z2ApIGlzIHNraXBwZWQsIGFzIGFyZSBleHRlcm5hbCBvbmVzLiBUaGUgc291cmNlIGlzIGNoZWNrZWQgYXQgdGhlXG4gKiBncmFudWxhcml0eSBvZiBpdHMgbGl0ZXJhbCBwcmVmaXg6IGVhY2ggcGFyYW1ldGVyIHN0YW5kcyBpbiBhcyBhIGR5bmFtaWNcbiAqIHNlZ21lbnQuIFJld3JpdGVzIGRvbmUgYnkgbWlkZGxld2FyZSAoYE5leHRSZXNwb25zZS5yZXdyaXRlYCkgYXJlIGNvZGUsIG5vdFxuICogY29uZmlnLCBhbmQgY2Fubm90IGJlIGNoZWNrZWQgYXQgYWxsLlxuICovXG5mdW5jdGlvbiBhc3NlcnRSZXdyaXRlc1N0YXlJbkdyb3VwKFxuICBncm91cE9mRW50cnlwb2ludDogUmVhZG9ubHlNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBiZWhhdmlvcnM6IHJlYWRvbmx5IEVkZ2VCZWhhdmlvcltdLFxuICByb3V0ZXI6IFJvdXRlcixcbik6IHZvaWQge1xuICBjb25zdCB7IHJvdXRpbmcgfSA9IHJvdXRlcjtcbiAgY29uc3QgcGhhc2VzOiBbcmVhZG9ubHkgUmV3cml0ZVJ1bGVbXSB8IHVuZGVmaW5lZCwgYm9vbGVhbl1bXSA9IFtcbiAgICBbcm91dGluZy5iZWZvcmVGaWxlcywgZmFsc2VdLFxuICAgIC8vIGBhZnRlckZpbGVzYCBhbmQgYGZhbGxiYWNrYCBvbmx5IGFwcGx5IHdoZW4gbm8gZmlsZSBtYXRjaGVkIHRoZSBVUkwsIHNvIGFcbiAgICAvLyBzb3VyY2UgdGhhdCBpcyBpdHNlbGYgYSByb3V0ZSBuZXZlciByZWFjaGVzIHRoZSBkZXN0aW5hdGlvbi5cbiAgICBbcm91dGluZy5hZnRlckZpbGVzLCB0cnVlXSxcbiAgICBbcm91dGluZy5mYWxsYmFjaywgdHJ1ZV0sXG4gIF07XG4gIGZvciAoY29uc3QgW3J1bGVzLCB5aWVsZHNUb0ZpbGVzXSBvZiBwaGFzZXMpIHtcbiAgICBmb3IgKGNvbnN0IHJ1bGUgb2YgcnVsZXMgPz8gW10pIHtcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uID0gbGl0ZXJhbERlc3RpbmF0aW9uKHJ1bGUuZGVzdGluYXRpb24pO1xuICAgICAgLy8gTmV4dC5qcydzIG93biBpbnRlcmNlcHRpb24gcmV3cml0ZXMgYXJlIGhlcmUgdG9vLCBvbiBgTmV4dC1VcmxgO1xuICAgICAgLy8gYHJlYXNzaWduSW50ZXJjZXB0aW5nRmlsZXNgIGhhcyBhbHJlYWR5IHB1dCB0aGVpciBmaWxlcyBpbiBwbGFjZS5cbiAgICAgIGlmIChkZXN0aW5hdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGlzSW50ZXJjZXB0aW9uVGVtcGxhdGUoZGVzdGluYXRpb24pKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZmlsZSA9IHJlc29sdmVGaWxlKGRlc3RpbmF0aW9uLCByb3V0ZXIpO1xuICAgICAgaWYgKGZpbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRhcmdldCA9IGdyb3VwT2ZFbnRyeXBvaW50LmdldChmaWxlKSA/PyBERUZBVUxUX0ZVTkNUSU9OX0dST1VQO1xuICAgICAgZm9yIChjb25zdCB1cmwgb2YgcmV3cml0ZVNvdXJjZVVybHMocnVsZS5zb3VyY2UpKSB7XG4gICAgICAgIGlmICh5aWVsZHNUb0ZpbGVzICYmIHJvdXRlci5maWxlT2ZUZW1wbGF0ZS5oYXModXJsKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJlaGF2aW9yID0gZWRnZUJlaGF2aW9yRm9yKGJlaGF2aW9ycywgdXJsKTtcbiAgICAgICAgY29uc3QgZ3JvdXAgPSBiZWhhdmlvcj8uZ3JvdXAgPz8gREVGQVVMVF9GVU5DVElPTl9HUk9VUDtcbiAgICAgICAgaWYgKGdyb3VwID09PSB0YXJnZXQpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYCR7RVJST1JfUFJFRklYfVRoZSBuZXh0LmNvbmZpZyByZXdyaXRlIGZyb20gXCIke3J1bGUuc291cmNlfVwiIHRvIGAgK1xuICAgICAgICAgICAgYFwiJHtydWxlLmRlc3RpbmF0aW9ufVwiIGNyb3NzZXMgZ3JvdXBzOiBDbG91ZEZyb250IHNlbmRzIFwiJHt1cmx9XCIgdG8gYCArXG4gICAgICAgICAgICBgJHtncm91cExhYmVsKGdyb3VwKX1gICtcbiAgICAgICAgICAgIChiZWhhdmlvciA/IGAgKGl0cyBwYXR0ZXJuIFwiJHtiZWhhdmlvci5yb3V0ZX1cIilgIDogXCJcIikgK1xuICAgICAgICAgICAgYCwgYW5kIE5leHQuanMgdGhlbiBzZXJ2ZXMgaXQgd2l0aCBcIiR7ZmlsZX1cIiwgd2hpY2ggaXMgcGFja2FnZWQgYCArXG4gICAgICAgICAgICBgaW50byAke2dyb3VwTGFiZWwodGFyZ2V0KX0uIEEgcmV3cml0ZSBpcyBhcHBsaWVkIGluc2lkZSB0aGUgYCArXG4gICAgICAgICAgICBgZnVuY3Rpb24gdGhhdCByZWNlaXZlZCB0aGUgcmVxdWVzdCwgc28gaXRzIHNvdXJjZSBhbmQgaXRzIGAgK1xuICAgICAgICAgICAgYGRlc3RpbmF0aW9uIGhhdmUgdG8gYmUgcm91dGVkIHRvIHRoZSBzYW1lIGdyb3VwLmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKiBBIHJld3JpdGUgZGVzdGluYXRpb24ncyBwYXRobmFtZSwgYHVuZGVmaW5lZGAgdW5sZXNzIGl0IGlzIGEgbGl0ZXJhbCBsb2NhbCBwYXRoLiAqL1xuZnVuY3Rpb24gbGl0ZXJhbERlc3RpbmF0aW9uKFxuICBkZXN0aW5hdGlvbjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFkZXN0aW5hdGlvbj8uc3RhcnRzV2l0aChcIi9cIikpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGNvbnN0IHBhdGhuYW1lID0gZGVzdGluYXRpb24uc3BsaXQoL1s/I10vKVswXTtcbiAgaWYgKC9bJDpdLy50ZXN0KHBhdGhuYW1lKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIHBhdGhuYW1lLmxlbmd0aCA+IDEgPyBwYXRobmFtZS5yZXBsYWNlKC9cXC8kLywgXCJcIikgOiBwYXRobmFtZTtcbn1cblxuLyoqIFdoYXQge0BsaW5rIHJlc29sdmVGaWxlfSByZXNvbHZlcyBhZ2FpbnN0LiAqL1xuaW50ZXJmYWNlIFJvdXRlciB7XG4gIC8qKiBUZW1wbGF0ZSDihpIgdGhlIGZpbGUgYmVoaW5kIGl0LCBsZXNzIHRoZSBSU0MgYW5kIHNlZ21lbnQgcmV3cml0ZXMuICovXG4gIHJlYWRvbmx5IGZpbGVPZlRlbXBsYXRlOiBSZWFkb25seU1hcDxzdHJpbmcsIHN0cmluZz47XG4gIHJlYWRvbmx5IHJvdXRpbmc6IFJvdXRpbmdSdWxlcztcbn1cblxuZnVuY3Rpb24gZmlsZU9mVGVtcGxhdGUoZW50cmllczogcmVhZG9ubHkgUm91dGVFbnRyeVtdKTogTWFwPHN0cmluZywgc3RyaW5nPiB7XG4gIHJldHVybiBuZXcgTWFwKFxuICAgIGVudHJpZXNcbiAgICAgIC5maWx0ZXIoKGVudHJ5KSA9PiAhaXNJbnRlcm5hbFRlbXBsYXRlKGVudHJ5LnRlbXBsYXRlKSlcbiAgICAgIC5tYXAoKGVudHJ5KSA9PiBbZW50cnkudGVtcGxhdGUsIGVudHJ5LmVudHJ5cG9pbnRJZF0pLFxuICApO1xufVxuXG4vKipcbiAqIFRoZSBmaWxlIE5leHQuanMgc2VydmVzIGBwYXRobmFtZWAgd2l0aDogYSB0ZW1wbGF0ZSBvZiB0aGF0IGV4YWN0IG5hbWUsIG9yXG4gKiBlbHNlIHRoZSBmaXJzdCBvZiBOZXh0LmpzJ3Mgb3duIGR5bmFtaWMgcm91dGUgcnVsZXMgdGhhdCBtYXRjaGVzIOKAlCBtYXRjaGVkXG4gKiBjYXNlLWluc2Vuc2l0aXZlbHksIGFzIGByZXNvbHZlUm91dGVzYCBkb2VzLiBgZHluYW1pY1JvdXRlc2AgaXMgaW4gTmV4dC5qcydzXG4gKiBwcmlvcml0eSBvcmRlciAoc3RhdGljIHNlZ21lbnQgYmVmb3JlIGBbcGFyYW1dYCBiZWZvcmUgYFsuLi5jYXRjaEFsbF1gXG4gKiBiZWZvcmUgYFtbLi4ub3B0aW9uYWxdXWApLCBQYWdlcyBSb3V0ZXIgZGF0YSBVUkxzIGluY2x1ZGVkLlxuICovXG5mdW5jdGlvbiByZXNvbHZlRmlsZShcbiAgcGF0aG5hbWU6IHN0cmluZyxcbiAgeyBmaWxlT2ZUZW1wbGF0ZTogZmlsZXMsIHJvdXRpbmcgfTogUm91dGVyLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZXhhY3QgPSBmaWxlcy5nZXQocGF0aG5hbWUpO1xuICBpZiAoZXhhY3QgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBleGFjdDtcbiAgfVxuICBmb3IgKGNvbnN0IHJvdXRlIG9mIHJvdXRpbmcuZHluYW1pY1JvdXRlcyA/PyBbXSkge1xuICAgIGlmIChuZXcgUmVnRXhwKHJvdXRlLnNvdXJjZVJlZ2V4LCBcImlcIikudGVzdChwYXRobmFtZSkpIHtcbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gcm91dGUuZGVzdGluYXRpb24/LnNwbGl0KFwiP1wiKVswXTtcbiAgICAgIHJldHVybiB0ZW1wbGF0ZSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogZmlsZXMuZ2V0KHRlbXBsYXRlKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBUaGUgVVJMIHNoYXBlcyBhIHBhdGgtdG8tcmVnZXhwIHJld3JpdGUgc291cmNlIG1hdGNoZXMsIGFzIHRlbXBsYXRlLWxpa2VcbiAqIHBhdGhzOiBlYWNoIGxpdGVyYWwgc2VnbWVudCBrZXB0LCBlYWNoIHBhcmFtZXRlciByZXBsYWNlZCBieSBgW25hbWVdYCwgYW5kIOKAlFxuICogd2hlbiB0aGUgbGFzdCBvbmUgaXMgb3B0aW9uYWwgKGA6cGF0aCpgLCBgOnNsdWc/YCkg4oCUIHRoZSBwYXRoIHdpdGhvdXQgaXQgdG9vLlxuICovXG5mdW5jdGlvbiByZXdyaXRlU291cmNlVXJscyhzb3VyY2U6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZ1tdIHtcbiAgaWYgKCFzb3VyY2U/LnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IHNlZ21lbnRzOiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgb3B0aW9uYWxGcm9tOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3Qgc2VnbWVudCBvZiBzb3VyY2Uuc3BsaXQoXCIvXCIpLnNsaWNlKDEpKSB7XG4gICAgaWYgKCEvWzooKSo/K3t9W1xcXV0vLnRlc3Qoc2VnbWVudCkpIHtcbiAgICAgIHNlZ21lbnRzLnB1c2goc2VnbWVudCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgb3B0aW9uYWxGcm9tID0gL146XFx3K1sqP10kLy50ZXN0KHNlZ21lbnQpID8gc2VnbWVudHMubGVuZ3RoIDogdW5kZWZpbmVkO1xuICAgIHNlZ21lbnRzLnB1c2goYFskey86KFxcdyspLy5leGVjKHNlZ21lbnQpPy5bMV0gPz8gXCJwYXJhbVwifV1gKTtcbiAgfVxuICBjb25zdCB1cmxzID0gW2AvJHtzZWdtZW50cy5qb2luKFwiL1wiKX1gXTtcbiAgaWYgKG9wdGlvbmFsRnJvbSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdXJscy5wdXNoKGAvJHtzZWdtZW50cy5zbGljZSgwLCBvcHRpb25hbEZyb20pLmpvaW4oXCIvXCIpfWApO1xuICB9XG4gIHJldHVybiB1cmxzO1xufVxuXG5mdW5jdGlvbiBncm91cExhYmVsKGdyb3VwOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gZ3JvdXAgPT09IERFRkFVTFRfRlVOQ1RJT05fR1JPVVBcbiAgICA/IGB0aGUgXCIke0RFRkFVTFRfRlVOQ1RJT05fR1JPVVB9XCIgZ3JvdXBgXG4gICAgOiBgZ3JvdXAgXCIke2dyb3VwfVwiYDtcbn1cblxuZnVuY3Rpb24gcHJlZml4QmFzZVBhdGgocm91dGU6IHN0cmluZywgYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtiYXNlUGF0aFByZWZpeChiYXNlUGF0aCl9JHtyb3V0ZX1gO1xufVxuXG4vKiogYHRlbXBsYXRlYCB3aXRob3V0IGBiYXNlUGF0aGAgKGAvYCBmb3IgdGhlIGJhc2UgaXRzZWxmKSwgYHVuZGVmaW5lZGAgaWYgb3V0c2lkZSBpdC4gKi9cbmZ1bmN0aW9uIHN0cmlwQmFzZVBhdGgodGVtcGxhdGU6IHN0cmluZywgYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghYmFzZVBhdGgpIHtcbiAgICByZXR1cm4gdGVtcGxhdGU7XG4gIH1cbiAgcmV0dXJuIGhhc1BhdGhQcmVmaXgodGVtcGxhdGUsIGJhc2VQYXRoKVxuICAgID8gdGVtcGxhdGUuc2xpY2UoYmFzZVBhdGgubGVuZ3RoKSB8fCBcIi9cIlxuICAgIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiB3aXRoQmFzZVBhdGgocGF0aDogc3RyaW5nLCBiYXNlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGggPT09IFwiL1wiID8gYmFzZVBhdGggfHwgXCIvXCIgOiBgJHtiYXNlUGF0aH0ke3BhdGh9YDtcbn1cbiJdfQ==