cdk-nextjs 0.6.2 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2404 -2723
- package/.jsii.tabl.json +1 -1
- package/API.md +1681 -1930
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +667 -4
- package/docs/caching-guide.md +156 -112
- package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
- package/docs/development-guide.md +1 -1
- package/docs/harness-coverage.md +598 -0
- package/docs/init-cache-deployment.md +32 -1
- package/docs/next-build-output-guide.md +30 -20
- package/examples/README.md +5 -1
- package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
- package/lib/adapter/__fixtures__/app-playground.json +4917 -0
- package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
- package/lib/adapter/adapter.mjs +1551 -185
- package/lib/adapter/adapter.test.js +106 -0
- package/lib/adapter/aws-cache-store.d.ts +489 -0
- package/lib/adapter/aws-cache-store.js +1004 -0
- package/lib/adapter/aws-cache-store.test.d.ts +1 -0
- package/lib/adapter/aws-cache-store.test.js +361 -0
- package/lib/adapter/build-outputs.d.ts +80 -0
- package/lib/adapter/build-outputs.js +857 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +863 -0
- package/lib/adapter/cache-handler.d.ts +9 -2
- package/lib/adapter/cache-handler.js +72 -96
- package/lib/adapter/cache-handler.mjs +18956 -17774
- package/lib/adapter/cache-handler.test.js +263 -31
- package/lib/adapter/cache-kinds.d.ts +32 -0
- package/lib/adapter/cache-kinds.js +35 -0
- package/lib/adapter/cache-kinds.test.d.ts +1 -0
- package/lib/adapter/cache-kinds.test.js +69 -0
- package/lib/adapter/cache-utils.d.ts +90 -0
- package/lib/adapter/cache-utils.js +199 -4
- package/lib/adapter/cache-utils.test.d.ts +1 -0
- package/lib/adapter/cache-utils.test.js +179 -0
- package/lib/adapter/function-groups.d.ts +215 -0
- package/lib/adapter/function-groups.js +1099 -0
- package/lib/adapter/function-groups.test.d.ts +1 -0
- package/lib/adapter/function-groups.test.js +743 -0
- package/lib/adapter/init-cache.d.ts +6 -0
- package/lib/adapter/init-cache.js +245 -0
- package/lib/adapter/init-cache.test.d.ts +1 -0
- package/lib/adapter/init-cache.test.js +137 -0
- package/lib/adapter/local-file-cache-handler.d.ts +23 -0
- package/lib/adapter/local-file-cache-handler.js +52 -1
- package/lib/adapter/memory-cache-handler.d.ts +26 -17
- package/lib/adapter/memory-cache-handler.js +32 -50
- package/lib/adapter/memory-cache-handler.test.js +105 -85
- package/lib/adapter/s3-cache-handler.d.ts +179 -40
- package/lib/adapter/s3-cache-handler.js +807 -277
- package/lib/adapter/s3-cache-handler.test.js +1186 -31
- package/lib/adapter/use-cache-common.d.ts +90 -0
- package/lib/adapter/use-cache-common.js +250 -0
- package/lib/adapter/use-cache-common.test.d.ts +1 -0
- package/lib/adapter/use-cache-common.test.js +646 -0
- package/lib/adapter/use-cache-default-handler.d.ts +24 -0
- package/lib/adapter/use-cache-default-handler.js +90 -0
- package/lib/adapter/use-cache-default-handler.mjs +38645 -0
- package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
- package/lib/adapter/use-cache-handlers.test.js +349 -0
- package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
- package/lib/adapter/use-cache-remote-handler.js +186 -0
- package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
- package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
- package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
- package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
- package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
- package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +8 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +2 -4
- package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
- package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
- package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
- package/lib/lambdas/post-deploy/prune-s3.js +41 -12
- package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
- package/lib/nextjs-api.d.ts +102 -18
- package/lib/nextjs-api.js +338 -38
- package/lib/nextjs-api.test.js +537 -1
- package/lib/nextjs-build/global-containers.Dockerfile +15 -10
- package/lib/nextjs-build/nextjs-build.d.ts +339 -63
- package/lib/nextjs-build/nextjs-build.js +684 -327
- package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
- package/lib/nextjs-build/nextjs-build.test.js +412 -0
- package/lib/nextjs-build/patch-fetch.js +1 -1
- package/lib/nextjs-build/patch-fetch.test.js +166 -11
- package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
- package/lib/nextjs-cache.d.ts +82 -4
- package/lib/nextjs-cache.js +186 -10
- package/lib/nextjs-cache.test.js +176 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
- package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
- package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
- package/lib/nextjs-compute/nextjs-containers.js +57 -20
- package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
- package/lib/nextjs-compute/nextjs-functions.js +113 -67
- package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
- package/lib/nextjs-distribution.d.ts +194 -23
- package/lib/nextjs-distribution.js +535 -62
- package/lib/nextjs-distribution.test.d.ts +1 -0
- package/lib/nextjs-distribution.test.js +697 -0
- package/lib/nextjs-post-deploy.d.ts +13 -5
- package/lib/nextjs-post-deploy.js +13 -10
- package/lib/nextjs-post-deploy.test.d.ts +1 -0
- package/lib/nextjs-post-deploy.test.js +34 -0
- package/lib/nextjs-static-assets.d.ts +17 -4
- package/lib/nextjs-static-assets.js +22 -5
- package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
- package/lib/root-constructs/nextjs-base-construct.js +139 -47
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -71
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -70
- package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
- package/lib/root-constructs/nextjs-regional-containers.js +8 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -26
- package/lib/runtime/api-gateway-path.d.ts +34 -0
- package/lib/runtime/api-gateway-path.js +71 -0
- package/lib/runtime/api-gateway-path.test.d.ts +1 -0
- package/lib/runtime/api-gateway-path.test.js +65 -0
- package/lib/runtime/case-redirect.d.ts +22 -0
- package/lib/runtime/case-redirect.js +63 -0
- package/lib/runtime/case-redirect.test.d.ts +1 -0
- package/lib/runtime/case-redirect.test.js +32 -0
- package/lib/runtime/core.d.ts +234 -0
- package/lib/runtime/core.js +1216 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1686 -0
- package/lib/runtime/deployment-root.d.ts +13 -0
- package/lib/runtime/deployment-root.js +29 -0
- package/lib/runtime/dispatch.d.ts +331 -0
- package/lib/runtime/dispatch.js +751 -0
- package/lib/runtime/dispatch.test.d.ts +1 -0
- package/lib/runtime/dispatch.test.js +853 -0
- package/lib/runtime/entrypoints.d.ts +57 -0
- package/lib/runtime/entrypoints.js +115 -0
- package/lib/runtime/http/abort-signal.d.ts +6 -0
- package/lib/runtime/http/abort-signal.js +19 -0
- package/lib/runtime/http/abort-signal.test.d.ts +1 -0
- package/lib/runtime/http/abort-signal.test.js +49 -0
- package/lib/runtime/http/node-server.d.ts +38 -0
- package/lib/runtime/http/node-server.js +99 -0
- package/lib/runtime/http/node-server.test.d.ts +1 -0
- package/lib/runtime/http/node-server.test.js +96 -0
- package/lib/runtime/http/node-sink.d.ts +16 -0
- package/lib/runtime/http/node-sink.js +48 -0
- package/lib/runtime/http/node-sink.test.d.ts +1 -0
- package/lib/runtime/http/node-sink.test.js +66 -0
- package/lib/runtime/http/request.d.ts +62 -0
- package/lib/runtime/http/request.js +134 -0
- package/lib/runtime/http/request.test.d.ts +1 -0
- package/lib/runtime/http/request.test.js +103 -0
- package/lib/runtime/http/response.d.ts +77 -0
- package/lib/runtime/http/response.js +229 -0
- package/lib/runtime/http/response.test.d.ts +1 -0
- package/lib/runtime/http/response.test.js +178 -0
- package/lib/runtime/http/sink.d.ts +73 -0
- package/lib/runtime/http/sink.js +188 -0
- package/lib/runtime/http/sink.test.d.ts +1 -0
- package/lib/runtime/http/sink.test.js +257 -0
- package/lib/runtime/image-utils.d.ts +78 -0
- package/lib/runtime/image-utils.js +129 -0
- package/lib/runtime/image-utils.test.d.ts +1 -0
- package/lib/runtime/image-utils.test.js +237 -0
- package/lib/runtime/image.d.ts +76 -0
- package/lib/runtime/image.js +296 -0
- package/lib/runtime/image.test.d.ts +1 -0
- package/lib/runtime/image.test.js +405 -0
- package/lib/runtime/lambda-event.d.ts +4 -0
- package/lib/runtime/lambda-event.js +113 -0
- package/lib/runtime/lambda-event.test.d.ts +1 -0
- package/lib/runtime/lambda-event.test.js +119 -0
- package/lib/runtime/lambda.mjs +41600 -0
- package/lib/runtime/load-module.d.ts +8 -0
- package/lib/runtime/load-module.js +35 -0
- package/lib/runtime/manifest.d.ts +215 -0
- package/lib/runtime/manifest.js +118 -0
- package/lib/runtime/middleware.d.ts +43 -0
- package/lib/runtime/middleware.js +113 -0
- package/lib/runtime/middleware.test.d.ts +1 -0
- package/lib/runtime/middleware.test.js +259 -0
- package/lib/runtime/next-modules.d.ts +71 -0
- package/lib/runtime/next-modules.js +144 -0
- package/lib/runtime/next-modules.test.d.ts +1 -0
- package/lib/runtime/next-modules.test.js +34 -0
- package/lib/runtime/public-files.d.ts +32 -0
- package/lib/runtime/public-files.js +117 -0
- package/lib/runtime/public-files.test.d.ts +1 -0
- package/lib/runtime/public-files.test.js +97 -0
- package/lib/runtime/server.mjs +41593 -0
- package/lib/runtime/static-files.d.ts +50 -0
- package/lib/runtime/static-files.js +266 -0
- package/lib/runtime/static-files.test.d.ts +1 -0
- package/lib/runtime/static-files.test.js +118 -0
- package/lib/runtime/util.d.ts +28 -0
- package/lib/runtime/util.js +79 -0
- package/lib/utils/base-path.d.ts +106 -13
- package/lib/utils/base-path.js +254 -41
- package/lib/utils/base-path.test.js +219 -51
- package/lib/utils/get-architecture.d.ts +7 -8
- package/lib/utils/get-architecture.js +12 -13
- package/lib/utils/zip-directory.d.ts +14 -0
- package/lib/utils/zip-directory.js +121 -0
- package/lib/utils/zip-directory.test.d.ts +1 -0
- package/lib/utils/zip-directory.test.js +99 -0
- package/package.json +22 -3
- package/scripts/capture-adapter-fixture.mjs +325 -0
- package/scripts/e2e-deploy.sh +398 -0
- package/scripts/e2e-harness/README.md +707 -0
- package/scripts/e2e-harness/app.js +370 -0
- package/scripts/e2e-harness/common.sh +249 -0
- package/scripts/e2e-harness/screen.mjs +302 -0
- package/scripts/e2e-harness/stage-proxy.mjs +145 -0
- package/scripts/e2e-harness/type-filters.mjs +47 -0
- package/scripts/e2e-logs.sh +75 -0
- package/scripts/e2e-offline.sh +91 -0
- package/scripts/e2e-sweep.sh +370 -0
- package/scripts/e2e-warm.sh +114 -0
- package/scripts/zero-config-build.mjs +418 -0
- package/docs/1k-concurrent-users-executions.png +0 -0
- package/docs/plans/adapter-runtime-release.md +0 -362
- package/docs/plans/phase-0-image-function-opt-in.md +0 -295
- package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
- package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
- package/lib/image-optimization/handler-utils.d.ts +0 -34
- package/lib/image-optimization/handler-utils.js +0 -83
- package/lib/image-optimization/handler-utils.test.js +0 -178
- package/lib/nextjs-build/functions.Dockerfile +0 -31
- package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
- package/lib/nextjs-compute/nextjs-image-function.js +0 -59
- package/lib/utils/experimental-flags.d.ts +0 -24
- package/lib/utils/experimental-flags.js +0 -30
- /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
7
|
+
const route_regex_1 = require("next/dist/shared/lib/router/utils/route-regex");
|
|
8
|
+
const sorted_routes_1 = require("next/dist/shared/lib/router/utils/sorted-routes");
|
|
9
|
+
const app_playground_json_1 = __importDefault(require("./__fixtures__/app-playground.json"));
|
|
10
|
+
const pages_i18n_json_1 = __importDefault(require("./__fixtures__/pages-i18n.json"));
|
|
11
|
+
const build_outputs_1 = require("./build-outputs");
|
|
12
|
+
const function_groups_1 = require("./function-groups");
|
|
13
|
+
/** One entrypoint per template unless a test says otherwise. */
|
|
14
|
+
const routes = (...templates) => templates.map((template) => ({ template, entrypointId: template }));
|
|
15
|
+
const BUILD_ID = "abc123";
|
|
16
|
+
/**
|
|
17
|
+
* `ctx.routing.dynamicRoutes` as `next build` derives it from `entries`: Next's
|
|
18
|
+
* own route sort and regexes, data URLs included.
|
|
19
|
+
*/
|
|
20
|
+
function nextRouting(entries, basePath) {
|
|
21
|
+
const dataPrefix = `${basePath}/_next/data/${BUILD_ID}/`;
|
|
22
|
+
const dynamic = [...new Set(entries.map((entry) => entry.template))].filter((template) => template.includes("[") &&
|
|
23
|
+
!template.endsWith(".rsc") &&
|
|
24
|
+
!/\(\.{1,3}\)/.test(template));
|
|
25
|
+
const route = (template) => ({
|
|
26
|
+
sourceRegex: (0, route_regex_1.getNamedRouteRegex)(template, {
|
|
27
|
+
prefixRouteKeys: true,
|
|
28
|
+
includeSuffix: true,
|
|
29
|
+
}).namedRegex,
|
|
30
|
+
destination: template,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
dynamicRoutes: [
|
|
34
|
+
// Sorted by the page they name: Next's sort reads `[slug].json` as static.
|
|
35
|
+
...(0, sorted_routes_1.getSortedRouteObjects)(dynamic.filter((template) => template.startsWith(dataPrefix)), (template) => `/${template.slice(dataPrefix.length, -".json".length)}`).map(route),
|
|
36
|
+
...(0, sorted_routes_1.getSortedRoutes)(dynamic.filter((template) => !template.startsWith(dataPrefix))).map(route),
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const assignment = (groups, entries, basePath = "", options = {}) => (0, function_groups_1.assignRoutesToGroups)(groups, entries, {
|
|
41
|
+
basePath,
|
|
42
|
+
buildId: BUILD_ID,
|
|
43
|
+
...options,
|
|
44
|
+
routing: { ...nextRouting(entries, basePath), ...options.routing },
|
|
45
|
+
});
|
|
46
|
+
const assign = (...args) => assignment(...args).templates;
|
|
47
|
+
/** The path patterns of the behaviors the assignment returns, in order. */
|
|
48
|
+
const patternsOf = (...args) => assignment(...args).behaviors.map(({ pattern }) => pattern);
|
|
49
|
+
/**
|
|
50
|
+
* A captured `onBuildComplete` fixture's routes, exactly as `buildAdapterManifest`
|
|
51
|
+
* hands them to the assignment, plus the rest of what it passes.
|
|
52
|
+
*/
|
|
53
|
+
function fixtureRoutes(fixture) {
|
|
54
|
+
const ctx = structuredClone(fixture);
|
|
55
|
+
const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
|
|
56
|
+
const { manifest } = (0, build_outputs_1.buildAdapterManifest)(ctx, { buildCwd: ctx.projectDir });
|
|
57
|
+
warn.mockRestore();
|
|
58
|
+
const entries = Object.entries(manifest.entrypoints).map(([template, entrypoint]) => ({
|
|
59
|
+
template,
|
|
60
|
+
entrypointId: entrypoint.filePath,
|
|
61
|
+
type: entrypoint.type,
|
|
62
|
+
}));
|
|
63
|
+
return {
|
|
64
|
+
entries,
|
|
65
|
+
options: {
|
|
66
|
+
basePath: ctx.config.basePath || "",
|
|
67
|
+
buildId: ctx.buildId,
|
|
68
|
+
trailingSlash: ctx.config.trailingSlash === true,
|
|
69
|
+
routing: ctx.routing,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
describe("validateFunctionGroups", () => {
|
|
74
|
+
it("rejects an empty array rather than treating it as no splitting", () => {
|
|
75
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([])).toThrow(/Omit the prop entirely/);
|
|
76
|
+
});
|
|
77
|
+
it("reserves the default group name", () => {
|
|
78
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "default", routes: ["/a"] }])).toThrow(/reserved group name/);
|
|
79
|
+
});
|
|
80
|
+
it.each([["has space"], ["under_score"], ["dots.here"], [""]])("rejects group name %p, which has to be a construct id", (name) => {
|
|
81
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name, routes: ["/a"] }])).toThrow(/must match/);
|
|
82
|
+
});
|
|
83
|
+
it("rejects two groups with the same name", () => {
|
|
84
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([
|
|
85
|
+
{ name: "api", routes: ["/a"] },
|
|
86
|
+
{ name: "api", routes: ["/b"] },
|
|
87
|
+
])).toThrow(/both named "api"/);
|
|
88
|
+
});
|
|
89
|
+
it("rejects a group that owns no routes", () => {
|
|
90
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "api", routes: [] }])).toThrow(/owns no routes/);
|
|
91
|
+
});
|
|
92
|
+
it("rejects the same pattern in two groups", () => {
|
|
93
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([
|
|
94
|
+
{ name: "a", routes: ["/api/**"] },
|
|
95
|
+
{ name: "b", routes: ["/api/**"] },
|
|
96
|
+
])).toThrow(/appears in both group "a" and group "b"/);
|
|
97
|
+
});
|
|
98
|
+
it("allows overlapping-but-different patterns, which resolve longest-first", () => {
|
|
99
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([
|
|
100
|
+
{ name: "a", routes: ["/api/**"] },
|
|
101
|
+
{ name: "b", routes: ["/api/reports/**"] },
|
|
102
|
+
])).not.toThrow();
|
|
103
|
+
});
|
|
104
|
+
it("requires a leading slash", () => {
|
|
105
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: ["api/**"] }])).toThrow(/must start with "\/"/);
|
|
106
|
+
});
|
|
107
|
+
it.each([["/dashboard/[id]"], ["/blog/[...slug]"], ["/shop/[[...slug]]"]])("rejects the dynamic segment in %p, which CloudFront cannot express", (route) => {
|
|
108
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: [route] }])).toThrow(/contains a dynamic segment/);
|
|
109
|
+
});
|
|
110
|
+
it("rejects a route group segment, which never appears in a URL", () => {
|
|
111
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: ["/(marketing)/about"] }])).toThrow(/route group segment/);
|
|
112
|
+
});
|
|
113
|
+
it.each([["/api/*"], ["/api/**/x"], ["/api/repo?ts"], ["/*"]])("rejects the wildcard placement in %p", (route) => {
|
|
114
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: [route] }])).toThrow(/wildcard somewhere other than a trailing/);
|
|
115
|
+
});
|
|
116
|
+
it("rejects a pattern that would own everything", () => {
|
|
117
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: ["/**"] }])).toThrow(/would own every route/);
|
|
118
|
+
});
|
|
119
|
+
it("rejects the root, which no CloudFront path pattern can match alone", () => {
|
|
120
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: ["/"] }])).toThrow(/cannot be routed/);
|
|
121
|
+
});
|
|
122
|
+
it("accepts /index, which is a real App Router route", () => {
|
|
123
|
+
// `app/index/page.tsx` is served at `/index`, apart from `/`. Only the
|
|
124
|
+
// assignment knows which router `/index` came from; it rejects the Pages
|
|
125
|
+
// Router home page, which is the same file as `/`.
|
|
126
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: ["/index"] }])).not.toThrow();
|
|
127
|
+
});
|
|
128
|
+
it.each(["/_next", "/_next/**", "/_next/data/**"])("rejects %s, which Next.js reserves", (route) => {
|
|
129
|
+
// A data route follows its page into the page's group; a `_next/*`
|
|
130
|
+
// behavior would compete with the static-asset and image behaviors.
|
|
131
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: [route] }])).toThrow(/under "\/_next"/);
|
|
132
|
+
});
|
|
133
|
+
it("rejects an empty path segment", () => {
|
|
134
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: ["/api//x"] }])).toThrow(/empty path segment/);
|
|
135
|
+
});
|
|
136
|
+
it.each([
|
|
137
|
+
["/über", '"ü"'],
|
|
138
|
+
["/a b", '" "'],
|
|
139
|
+
["/shop/a,b/**", '","'],
|
|
140
|
+
["/100%25", '"%"'],
|
|
141
|
+
])("rejects %p, which holds a character no CloudFront path pattern can", (route, char) => {
|
|
142
|
+
// `pathPatternsFor` copies the route verbatim into a behavior path
|
|
143
|
+
// pattern, so without this it failed at deploy naming neither the group
|
|
144
|
+
// nor the route.
|
|
145
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([{ name: "a", routes: [route] }])).toThrow(`contains ${char}, which a CloudFront behavior path pattern`);
|
|
146
|
+
});
|
|
147
|
+
it("accepts every literal in CloudFront's path pattern alphabet", () => {
|
|
148
|
+
expect(() => (0, function_groups_1.validateFunctionGroups)([
|
|
149
|
+
{
|
|
150
|
+
name: "a",
|
|
151
|
+
routes: [`/AZaz09_-.$~"'@:+&/**`],
|
|
152
|
+
},
|
|
153
|
+
])).not.toThrow();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe("assignRoutesToGroups", () => {
|
|
157
|
+
it("puts unassigned routes in the default group, which always exists", () => {
|
|
158
|
+
const assigned = assign([{ name: "api", routes: ["/api/**"] }], routes("/", "/pricing", "/api/health"));
|
|
159
|
+
expect(assigned).toEqual({
|
|
160
|
+
[function_groups_1.DEFAULT_FUNCTION_GROUP]: ["/", "/pricing"],
|
|
161
|
+
api: ["/api/health"],
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
it("matches an exact pattern only exactly", () => {
|
|
165
|
+
const assigned = assign([{ name: "p", routes: ["/pricing"] }], routes("/pricing", "/pricing/enterprise"));
|
|
166
|
+
expect(assigned.p).toEqual(["/pricing"]);
|
|
167
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/pricing/enterprise"]);
|
|
168
|
+
});
|
|
169
|
+
it("matches a subtree against the dynamic routes under it", () => {
|
|
170
|
+
const assigned = assign([{ name: "blog", routes: ["/blog/**"] }], routes("/blog/[slug]", "/blog/[slug]/comments", "/blogroll"));
|
|
171
|
+
expect(assigned.blog).toEqual(["/blog/[slug]", "/blog/[slug]/comments"]);
|
|
172
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/blogroll"]);
|
|
173
|
+
});
|
|
174
|
+
it("does not let a subtree claim its own root, because the behavior would not", () => {
|
|
175
|
+
// `/api/reports/**` deploys as CloudFront `api/reports/*`, which does not
|
|
176
|
+
// match `/api/reports`. Claiming it here would package the route into a
|
|
177
|
+
// function the edge never routes it to.
|
|
178
|
+
expect(() => assign([{ name: "r", routes: ["/api/reports/**"] }], routes("/api/reports"))).toThrow(/matches no route in this build/);
|
|
179
|
+
});
|
|
180
|
+
it("gives the longest matching pattern the route", () => {
|
|
181
|
+
const assigned = assign([
|
|
182
|
+
{ name: "api", routes: ["/api/**"] },
|
|
183
|
+
{ name: "reports", routes: ["/api/reports/**"] },
|
|
184
|
+
], routes("/api/health", "/api/reports/[id]"));
|
|
185
|
+
expect(assigned.api).toEqual(["/api/health"]);
|
|
186
|
+
expect(assigned.reports).toEqual(["/api/reports/[id]"]);
|
|
187
|
+
});
|
|
188
|
+
it("ranks by segment count before string length", () => {
|
|
189
|
+
// "/a/b" is deeper than "/alongname" even though it is shorter.
|
|
190
|
+
const assigned = assign([
|
|
191
|
+
{ name: "deep", routes: ["/a/b/**"] },
|
|
192
|
+
{ name: "long", routes: ["/a/**"] },
|
|
193
|
+
], routes("/a/b/c", "/a/x"));
|
|
194
|
+
expect(assigned.deep).toEqual(["/a/b/c"]);
|
|
195
|
+
expect(assigned.long).toEqual(["/a/x"]);
|
|
196
|
+
});
|
|
197
|
+
it("throws on a pattern that matches nothing, because the typo is invisible", () => {
|
|
198
|
+
expect(() => assign([{ name: "api", routes: ["/api/**", "/apy/**"] }], routes("/api/x"))).toThrow(/pattern "\/apy\/\*\*" matches no route/);
|
|
199
|
+
});
|
|
200
|
+
it("accepts a pattern every match of which a narrower pattern also claims", () => {
|
|
201
|
+
// `/api/**` never wins a route here, because every API route this build has
|
|
202
|
+
// is under `/api/reports/`. Recording only the *winning* pattern made it look
|
|
203
|
+
// like a typo and threw - rejecting the exact layout the duplicate-pattern
|
|
204
|
+
// error documents as supported. The group is legitimately empty: it is the
|
|
205
|
+
// consumer's choice to keep it for the routes it will own later.
|
|
206
|
+
const assigned = assign([
|
|
207
|
+
{ name: "api", routes: ["/api/**"] },
|
|
208
|
+
{ name: "reports", routes: ["/api/reports/**"] },
|
|
209
|
+
], routes("/api/reports/[id]", "/api/reports/summary"));
|
|
210
|
+
expect(assigned.api).toEqual([]);
|
|
211
|
+
expect(assigned.reports).toEqual([
|
|
212
|
+
"/api/reports/[id]",
|
|
213
|
+
"/api/reports/summary",
|
|
214
|
+
]);
|
|
215
|
+
});
|
|
216
|
+
it("gives a shared entrypoint to its most specific match, not its last one", () => {
|
|
217
|
+
// Two templates, one file, two groups whose patterns both match - one
|
|
218
|
+
// narrowly, one broadly. Ownership used to be last-write-wins over `entries`,
|
|
219
|
+
// so the same build grouped differently depending on manifest key order.
|
|
220
|
+
const entries = [
|
|
221
|
+
// Matched only by the broad pattern.
|
|
222
|
+
{ template: "/api/health", entrypointId: "shared" },
|
|
223
|
+
// Matched by both; the narrow one wins.
|
|
224
|
+
{ template: "/api/reports/summary", entrypointId: "shared" },
|
|
225
|
+
];
|
|
226
|
+
const groups = [
|
|
227
|
+
{ name: "api", routes: ["/api/**"] },
|
|
228
|
+
{ name: "reports", routes: ["/api/reports/**"] },
|
|
229
|
+
];
|
|
230
|
+
// `/api/reports/**` is the most specific claim any of the entrypoint's
|
|
231
|
+
// templates has, so it takes the whole entrypoint — and then the edge still
|
|
232
|
+
// sends `/api/health` to the api group, which lacks the file. That used to
|
|
233
|
+
// deploy and 500; it is the coverage check's to reject, identically in both
|
|
234
|
+
// orders.
|
|
235
|
+
const message = /"\/api\/health" to group "api" \(its pattern "\/api\/\*\*"\)/;
|
|
236
|
+
expect(() => assign(groups, entries)).toThrow(message);
|
|
237
|
+
expect(() => assign(groups, [...entries].reverse())).toThrow(message);
|
|
238
|
+
expect(() => assign(groups, entries)).toThrow(/Add "\/api\/health" to group "reports"'s routes/);
|
|
239
|
+
// Which is the fix: the exact pattern beats the api subtree at the edge.
|
|
240
|
+
const fixed = assign([
|
|
241
|
+
groups[0],
|
|
242
|
+
{ name: "reports", routes: ["/api/reports/**", "/api/health"] },
|
|
243
|
+
], entries);
|
|
244
|
+
expect(fixed.reports).toEqual(["/api/health", "/api/reports/summary"]);
|
|
245
|
+
expect(fixed.api).toEqual([]);
|
|
246
|
+
});
|
|
247
|
+
it("prefixes basePath before matching, since manifest templates carry it", () => {
|
|
248
|
+
const assigned = assign([{ name: "api", routes: ["/api/**"] }], routes("/prod/api/health", "/prod/pricing"), "/prod");
|
|
249
|
+
expect(assigned.api).toEqual(["/prod/api/health"]);
|
|
250
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/prod/pricing"]);
|
|
251
|
+
});
|
|
252
|
+
it("keeps two templates sharing one entrypoint in the same group", () => {
|
|
253
|
+
// A Pages Router page and its `/_next/data/<buildId>/…json` sibling are one
|
|
254
|
+
// file; splitting them would stage it twice and misroute one of them.
|
|
255
|
+
const assigned = assign([{ name: "blog", routes: ["/blog/**"] }], [
|
|
256
|
+
{
|
|
257
|
+
template: "/blog/[slug]",
|
|
258
|
+
entrypointId: "pages/blog/[slug]",
|
|
259
|
+
type: "page",
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
template: "/_next/data/abc123/blog/[slug].json",
|
|
263
|
+
entrypointId: "pages/blog/[slug]",
|
|
264
|
+
type: "page",
|
|
265
|
+
},
|
|
266
|
+
{ template: "/", entrypointId: "pages/index", type: "page" },
|
|
267
|
+
]);
|
|
268
|
+
expect(assigned.blog).toEqual([
|
|
269
|
+
"/_next/data/abc123/blog/[slug].json",
|
|
270
|
+
"/blog/[slug]",
|
|
271
|
+
]);
|
|
272
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/"]);
|
|
273
|
+
});
|
|
274
|
+
it("returns every group even when a group ends up with only the default's leftovers", () => {
|
|
275
|
+
const assigned = assign([{ name: "api", routes: ["/api/**"] }], routes("/api/health"));
|
|
276
|
+
expect(Object.keys(assigned).sort()).toEqual(["api", "default"]);
|
|
277
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual([]);
|
|
278
|
+
});
|
|
279
|
+
it("sorts each group's templates so the manifest is byte-stable", () => {
|
|
280
|
+
const assigned = assign([{ name: "api", routes: ["/api/**"] }], routes("/api/z", "/api/a", "/z", "/a"));
|
|
281
|
+
expect(assigned.api).toEqual(["/api/a", "/api/z"]);
|
|
282
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/a", "/z"]);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
describe("the behaviors the assignment returns", () => {
|
|
286
|
+
it("orders overlapping group patterns most specific first", () => {
|
|
287
|
+
// CloudFront stops at the first matching behavior, so `api/*` ahead of
|
|
288
|
+
// `api/reports/*` would send every report request to the wrong function.
|
|
289
|
+
expect(patternsOf([
|
|
290
|
+
{ name: "api", routes: ["/api/**"] },
|
|
291
|
+
{ name: "reports", routes: ["/api/reports/**"] },
|
|
292
|
+
], routes("/api/[x]", "/api/reports/[id]"))).toEqual(["api/reports/*", "api/*"]);
|
|
293
|
+
});
|
|
294
|
+
it("ranks by segment count before string length", () => {
|
|
295
|
+
expect(patternsOf([
|
|
296
|
+
{ name: "a", routes: ["/a/b/**"] },
|
|
297
|
+
{ name: "b", routes: ["/averyverylongsegment/**"] },
|
|
298
|
+
], routes("/a/b/[x]", "/averyverylongsegment/[x]"))).toEqual(["a/b/*", "averyverylongsegment/*"]);
|
|
299
|
+
});
|
|
300
|
+
it("puts an exact pattern ahead of a wildcard of the same depth", () => {
|
|
301
|
+
// `a/*` and `a/b` are the same length and segment count; `a/*` first
|
|
302
|
+
// swallows `a/b`, sending group b's only route to group a's function.
|
|
303
|
+
expect(patternsOf([
|
|
304
|
+
{ name: "a", routes: ["/a/**"] },
|
|
305
|
+
{ name: "b", routes: ["/a/b"] },
|
|
306
|
+
], routes("/a/b", "/a/[x]"))).toEqual(["a/b", "a/*"]);
|
|
307
|
+
});
|
|
308
|
+
it("adds data-URL behaviors only for the groups that own a Pages Router page", () => {
|
|
309
|
+
// One legacy page must not double every group's behaviors.
|
|
310
|
+
expect(patternsOf([
|
|
311
|
+
{ name: "blog", routes: ["/blog/**"] },
|
|
312
|
+
{ name: "docs", routes: ["/docs/**"] },
|
|
313
|
+
], [
|
|
314
|
+
{
|
|
315
|
+
template: "/blog/[slug]",
|
|
316
|
+
entrypointId: "pages/blog/[slug].js",
|
|
317
|
+
type: "page",
|
|
318
|
+
},
|
|
319
|
+
{ template: "/docs/[page]", entrypointId: "app/docs/[page]/page.js" },
|
|
320
|
+
])).toEqual(["_next/data/abc123/blog/*", "blog/*", "docs/*"]);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
describe("what the edge routes, checked against what was packaged", () => {
|
|
324
|
+
describe("Pages Router data URLs (A)", () => {
|
|
325
|
+
it("keeps a nested page's data URL in its own group", () => {
|
|
326
|
+
// With `_next/data/*/blog/*`, CloudFront sent the docs group's
|
|
327
|
+
// `/_next/data/<id>/docs/blog/intro.json` to the blog function.
|
|
328
|
+
const page = (template, file) => [
|
|
329
|
+
{ template, entrypointId: file, type: "page" },
|
|
330
|
+
{
|
|
331
|
+
template: `/_next/data/${BUILD_ID}${template}.json`,
|
|
332
|
+
entrypointId: file,
|
|
333
|
+
type: "page",
|
|
334
|
+
},
|
|
335
|
+
];
|
|
336
|
+
const assigned = assign([
|
|
337
|
+
{ name: "blog", routes: ["/blog/**"] },
|
|
338
|
+
{ name: "docs", routes: ["/docs/**"] },
|
|
339
|
+
], [
|
|
340
|
+
...page("/blog/[slug]", "pages/blog/[slug].js"),
|
|
341
|
+
...page("/docs/blog/[slug]", "pages/docs/blog/[slug].js"),
|
|
342
|
+
]);
|
|
343
|
+
expect(assigned.docs).toEqual([
|
|
344
|
+
"/_next/data/abc123/docs/blog/[slug].json",
|
|
345
|
+
"/docs/blog/[slug]",
|
|
346
|
+
]);
|
|
347
|
+
});
|
|
348
|
+
it("routes the pages-i18n fixture's page and data URLs together", () => {
|
|
349
|
+
// Splitting refuses i18n, so drop the locale-prefixed copies and keep the
|
|
350
|
+
// shape the fixture has without them: a dynamic SSG page, an SSR page with
|
|
351
|
+
// its data output, two API routes.
|
|
352
|
+
const { entries, options } = fixtureRoutes(pages_i18n_json_1.default);
|
|
353
|
+
const locale = /^\/(?:_next\/data\/[^/]+\/)?(?:en-US|fr|nl-NL)(?:\/|$)/;
|
|
354
|
+
const unlocalized = entries.filter((entry) => !locale.test(entry.template));
|
|
355
|
+
const { templates, behaviors } = (0, function_groups_1.assignRoutesToGroups)([
|
|
356
|
+
{ name: "blog", routes: ["/blog/**"] },
|
|
357
|
+
{ name: "ssr", routes: ["/ssr"] },
|
|
358
|
+
], unlocalized, options);
|
|
359
|
+
expect(templates.blog).toEqual(["/blog/[slug]"]);
|
|
360
|
+
expect(templates.ssr).toEqual([
|
|
361
|
+
`/_next/data/${options.buildId}/ssr.json`,
|
|
362
|
+
"/ssr",
|
|
363
|
+
]);
|
|
364
|
+
expect(behaviors.filter(({ pattern }) => pattern.startsWith("_next/data/"))).toEqual([
|
|
365
|
+
{
|
|
366
|
+
group: "ssr",
|
|
367
|
+
route: "/ssr",
|
|
368
|
+
pattern: `_next/data/${options.buildId}/ssr.json`,
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
group: "blog",
|
|
372
|
+
route: "/blog/**",
|
|
373
|
+
pattern: `_next/data/${options.buildId}/blog/*`,
|
|
374
|
+
},
|
|
375
|
+
]);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
describe("an optional catch-all's parent (B)", () => {
|
|
379
|
+
it("routes the parent URL with the subtree that moved the file", () => {
|
|
380
|
+
const { entries, options } = fixtureRoutes(app_playground_json_1.default);
|
|
381
|
+
const groups = [{ name: "params", routes: ["/params/optional/**"] }];
|
|
382
|
+
const { templates, behaviors } = (0, function_groups_1.assignRoutesToGroups)(groups, entries, options);
|
|
383
|
+
expect(templates.params).toContain("/params/optional/[[...rest]]");
|
|
384
|
+
// `params/optional/*` does not match `/params/optional`, which the same
|
|
385
|
+
// file serves, so it gets an exact behavior of its own.
|
|
386
|
+
expect(behaviors).toEqual([
|
|
387
|
+
{
|
|
388
|
+
group: "params",
|
|
389
|
+
route: "/params/optional",
|
|
390
|
+
pattern: "params/optional",
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
group: "params",
|
|
394
|
+
route: "/params/optional/**",
|
|
395
|
+
pattern: "params/optional/*",
|
|
396
|
+
},
|
|
397
|
+
]);
|
|
398
|
+
});
|
|
399
|
+
it("points the old exact-pattern workaround at the subtree", () => {
|
|
400
|
+
const { entries, options } = fixtureRoutes(app_playground_json_1.default);
|
|
401
|
+
expect(() => (0, function_groups_1.assignRoutesToGroups)([{ name: "params", routes: ["/params/optional"] }], entries, options)).toThrow(/served by the optional catch-all "\/params\/optional\/\[\[\.\.\.rest\]\]", whose subtree pattern "\/params\/optional\/\*\*" routes "\/params\/optional" as well/);
|
|
402
|
+
});
|
|
403
|
+
it("works under a basePath too", () => {
|
|
404
|
+
const assigned = assign([{ name: "shop", routes: ["/shop/**"] }], routes("/base/shop/[[...slug]]", "/base"), "/base");
|
|
405
|
+
expect(assigned.shop).toEqual(["/base/shop/[[...slug]]"]);
|
|
406
|
+
expect((0, function_groups_1.routedPatterns)(["/shop/**"], assigned.shop, "base")).toEqual([
|
|
407
|
+
"/shop/**",
|
|
408
|
+
"/shop",
|
|
409
|
+
]);
|
|
410
|
+
});
|
|
411
|
+
it("routes a Pages Router optional catch-all's parent data URL", () => {
|
|
412
|
+
// `/_next/data/<id>/shop.json` belongs to the same file, and the exact
|
|
413
|
+
// `/shop` pattern `routedPatterns` adds carries it.
|
|
414
|
+
const assigned = assign([{ name: "shop", routes: ["/shop/**"] }], [
|
|
415
|
+
{
|
|
416
|
+
template: "/shop/[[...slug]]",
|
|
417
|
+
entrypointId: "pages/shop/[[...slug]].js",
|
|
418
|
+
type: "page",
|
|
419
|
+
},
|
|
420
|
+
]);
|
|
421
|
+
expect(assigned.shop).toEqual(["/shop/[[...slug]]"]);
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
describe("one file behind several templates (C)", () => {
|
|
425
|
+
// `app/[locale]/page.tsx` with root params: `/en` and `/de` are synthesized
|
|
426
|
+
// from one output, alongside its own `/[locale]` template.
|
|
427
|
+
const rootParams = [
|
|
428
|
+
"/[locale]",
|
|
429
|
+
"/[locale].rsc",
|
|
430
|
+
"/en",
|
|
431
|
+
"/en.rsc",
|
|
432
|
+
"/de",
|
|
433
|
+
"/de.rsc",
|
|
434
|
+
].map((template) => ({
|
|
435
|
+
template,
|
|
436
|
+
entrypointId: "app/[locale]/page.js",
|
|
437
|
+
type: "app-page",
|
|
438
|
+
}));
|
|
439
|
+
it("rejects a pattern that moves the file for one of its URLs", () => {
|
|
440
|
+
// Only `en` got a behavior, so `/de` reached the default function, which
|
|
441
|
+
// no longer had the file.
|
|
442
|
+
expect(() => assign([{ name: "intl", routes: ["/en"] }], rootParams)).toThrow(/"app\/\[locale\]\/page\.js" is packaged into group "intl", but CloudFront would send "\/\[locale\]" to the "default" group, "\/de" to the "default" group/);
|
|
443
|
+
// And says the file cannot be grouped at all: `/[locale]` would need `/**`.
|
|
444
|
+
expect(() => assign([{ name: "intl", routes: ["/en", "/de"] }], rootParams)).toThrow(/"\/\[locale\]" cannot be routed to any group/);
|
|
445
|
+
});
|
|
446
|
+
it("suggests the pattern that covers a static template it left behind", () => {
|
|
447
|
+
const shared = [
|
|
448
|
+
{ template: "/about", entrypointId: "shared.js" },
|
|
449
|
+
{ template: "/team", entrypointId: "shared.js" },
|
|
450
|
+
];
|
|
451
|
+
expect(() => assign([{ name: "m", routes: ["/about"] }], shared)).toThrow(/Add "\/team" to group "m"'s routes/);
|
|
452
|
+
expect(assign([{ name: "m", routes: ["/about", "/team"] }], shared).m).toEqual(["/about", "/team"]);
|
|
453
|
+
});
|
|
454
|
+
it("checks the trailingSlash form, which exact patterns route", () => {
|
|
455
|
+
const assigned = assign([{ name: "p", routes: ["/pricing"] }], routes("/pricing"), "", { trailingSlash: true });
|
|
456
|
+
expect(assigned.p).toEqual(["/pricing"]);
|
|
457
|
+
});
|
|
458
|
+
it("puts an exact trailingSlash form ahead of a subtree it sits at the base of", () => {
|
|
459
|
+
// `a/b/` and `a/b/*` have the same literal depth; were the subtree first
|
|
460
|
+
// it would take `/a/b/` from group x.
|
|
461
|
+
const assigned = assign([
|
|
462
|
+
{ name: "x", routes: ["/a/b"] },
|
|
463
|
+
{ name: "y", routes: ["/a/b/**"] },
|
|
464
|
+
], routes("/", "/a/b", "/a/b/[id]"), "", { trailingSlash: true });
|
|
465
|
+
expect(assigned.x).toEqual(["/a/b"]);
|
|
466
|
+
expect(assigned.y).toEqual(["/a/b/[id]"]);
|
|
467
|
+
});
|
|
468
|
+
it("gives a group without Pages Router routes no data URL behaviors", () => {
|
|
469
|
+
// An App Router `/index` next to a Pages Router home page: a data behavior
|
|
470
|
+
// for the group, `_next/data/<id>/index.json`, would be the home page's
|
|
471
|
+
// data URL. The group owns no page, so it gets none.
|
|
472
|
+
expect(assign([{ name: "idx", routes: ["/index"] }], [
|
|
473
|
+
{ template: "/", entrypointId: "pages/index.js", type: "page" },
|
|
474
|
+
{
|
|
475
|
+
template: "/index",
|
|
476
|
+
entrypointId: "app/index/page.js",
|
|
477
|
+
type: "app-page",
|
|
478
|
+
},
|
|
479
|
+
]).idx).toEqual(["/index"]);
|
|
480
|
+
});
|
|
481
|
+
it("rejects a group pattern claiming a data URL of a file left in default", () => {
|
|
482
|
+
// The same collision in a group that does own a page.
|
|
483
|
+
expect(() => assign([{ name: "idx", routes: ["/index", "/legacy"] }], [
|
|
484
|
+
{ template: "/", entrypointId: "pages/index.js", type: "page" },
|
|
485
|
+
{
|
|
486
|
+
template: "/index",
|
|
487
|
+
entrypointId: "app/index/page.js",
|
|
488
|
+
type: "app-page",
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
template: "/legacy",
|
|
492
|
+
entrypointId: "pages/legacy.js",
|
|
493
|
+
type: "page",
|
|
494
|
+
},
|
|
495
|
+
])).toThrow(/"pages\/index\.js" is packaged into the "default" group, but CloudFront would send "\/_next\/data\/abc123\/index\.json" to group "idx"/);
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
describe("interception routes (D)", () => {
|
|
499
|
+
const photoApp = () => [
|
|
500
|
+
{ template: "/feed", entrypointId: "app/feed/page.js", type: "app-page" },
|
|
501
|
+
{
|
|
502
|
+
template: "/feed/(..)photo/[id]",
|
|
503
|
+
entrypointId: "app/feed/(..)photo/[id]/page.js",
|
|
504
|
+
type: "app-page",
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
template: "/feed/(..)photo/[id].rsc",
|
|
508
|
+
entrypointId: "app/feed/(..)photo/[id]/page.js",
|
|
509
|
+
type: "app-page",
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
template: "/photo/[id]",
|
|
513
|
+
entrypointId: "app/photo/[id]/page.js",
|
|
514
|
+
type: "app-page",
|
|
515
|
+
},
|
|
516
|
+
];
|
|
517
|
+
it("packages an intercepting file with the URL it intercepts", () => {
|
|
518
|
+
// The soft navigation requests `/photo/1`, which CloudFront sends to the
|
|
519
|
+
// default function; Next.js rewrites it there to the intercepting file.
|
|
520
|
+
const assigned = assign([{ name: "feed", routes: ["/feed/**"] }], [
|
|
521
|
+
...photoApp(),
|
|
522
|
+
{ template: "/feed/[post]", entrypointId: "app/feed/[post]/page.js" },
|
|
523
|
+
]);
|
|
524
|
+
expect(assigned.feed).toEqual(["/feed/[post]"]);
|
|
525
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toContain("/feed/(..)photo/[id]");
|
|
526
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toContain("/feed/(..)photo/[id].rsc");
|
|
527
|
+
});
|
|
528
|
+
it("follows the intercepted route into its group", () => {
|
|
529
|
+
const assigned = assign([{ name: "photos", routes: ["/photo/**"] }], photoApp());
|
|
530
|
+
expect(assigned.photos).toEqual([
|
|
531
|
+
"/feed/(..)photo/[id]",
|
|
532
|
+
"/feed/(..)photo/[id].rsc",
|
|
533
|
+
"/photo/[id]",
|
|
534
|
+
]);
|
|
535
|
+
});
|
|
536
|
+
it("throws when the intercepted URL space is split between groups", () => {
|
|
537
|
+
expect(() => assign([{ name: "one", routes: ["/photo/1"] }], [
|
|
538
|
+
...photoApp(),
|
|
539
|
+
{ template: "/photo/1", entrypointId: "app/photo/1/page.js" },
|
|
540
|
+
])).toThrow(/interception route "\/feed\/\(\.\.\)photo\/\[id\]".*group "one"'s pattern "\/photo\/1" claims part of it/s);
|
|
541
|
+
});
|
|
542
|
+
it.each([
|
|
543
|
+
["/feed/(..)photo/[id]", "/photo/[id]"],
|
|
544
|
+
["/feed/(.)photo/[id]", "/feed/photo/[id]"],
|
|
545
|
+
["/(.)photo/[id]", "/photo/[id]"],
|
|
546
|
+
["/a/b/(..)(..)photo", "/photo"],
|
|
547
|
+
["/a/b/(...)photo", "/photo"],
|
|
548
|
+
["/photo/[id]", undefined],
|
|
549
|
+
])("resolves %p to the route it intercepts, %p", (path, expected) => {
|
|
550
|
+
expect((0, function_groups_1.interceptedRoute)(path)).toBe(expected);
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
describe("next.config rewrites (D)", () => {
|
|
554
|
+
it("rejects a rewrite whose source and destination land in different groups", () => {
|
|
555
|
+
// app-playground rewrites `/e2e/rewrite/:path(.*)` to `/e2e/rewrite/echo`.
|
|
556
|
+
// Grouping only the destination leaves the source on the default
|
|
557
|
+
// function, which then rewrites to a file it does not have.
|
|
558
|
+
const { entries, options } = fixtureRoutes(app_playground_json_1.default);
|
|
559
|
+
expect(() => (0, function_groups_1.assignRoutesToGroups)([{ name: "echo", routes: ["/e2e/rewrite/echo"] }], entries, options)).toThrow(/rewrite from "\/e2e\/rewrite\/:path\(\.\*\)" to "\/e2e\/rewrite\/echo\?.*" crosses groups: CloudFront sends "\/e2e\/rewrite\/\[path\]" to the "default" group, and Next\.js then serves it with ".*echo\/page\.js", which is packaged into group "echo"/);
|
|
560
|
+
// Both ends in one group is fine.
|
|
561
|
+
expect((0, function_groups_1.assignRoutesToGroups)([{ name: "e2e", routes: ["/e2e/rewrite/**"] }], entries, options).templates.e2e).toContain("/e2e/rewrite/echo");
|
|
562
|
+
});
|
|
563
|
+
it("resolves a destination through Next.js's dynamic route rules", () => {
|
|
564
|
+
const routing = {
|
|
565
|
+
beforeFiles: [{ source: "/old", destination: "/blog/hello" }],
|
|
566
|
+
dynamicRoutes: [
|
|
567
|
+
{
|
|
568
|
+
sourceRegex: "^/blog/([^/]+?)(?:/)?$",
|
|
569
|
+
destination: "/blog/[slug]",
|
|
570
|
+
},
|
|
571
|
+
],
|
|
572
|
+
};
|
|
573
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/blog/[slug]"), "", {
|
|
574
|
+
routing,
|
|
575
|
+
})).toThrow(/CloudFront sends "\/old" to the "default" group/);
|
|
576
|
+
});
|
|
577
|
+
it("skips an afterFiles source a route already serves, and parameterized destinations", () => {
|
|
578
|
+
const routing = {
|
|
579
|
+
// Never applied: `/pricing` is a route, and afterFiles yields to it.
|
|
580
|
+
afterFiles: [{ source: "/pricing", destination: "/blog/x" }],
|
|
581
|
+
// Not resolvable at synth.
|
|
582
|
+
beforeFiles: [{ source: "/b/:slug", destination: "/blog/:slug" }],
|
|
583
|
+
};
|
|
584
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/blog/x", "/pricing"), "", { routing })).not.toThrow();
|
|
585
|
+
});
|
|
586
|
+
it("checks the path an optional parameter leaves", () => {
|
|
587
|
+
const routing = {
|
|
588
|
+
beforeFiles: [{ source: "/docs/:path*", destination: "/docs-app" }],
|
|
589
|
+
};
|
|
590
|
+
expect(() => assign([{ name: "docs", routes: ["/docs/**", "/docs-app"] }], routes("/docs-app", "/docs/[page]"), "", { routing })).toThrow(/CloudFront sends "\/docs" to the "default" group/);
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
describe("a dynamic route's URL space (E)", () => {
|
|
594
|
+
it("rejects a subtree capturing URLs a default-group catch-all serves", () => {
|
|
595
|
+
// `/blog/[slug]` only matches one segment, so `/blog/a/b` reaches the
|
|
596
|
+
// blog function via `blog/*` and resolves there to `/[...slug]`, which
|
|
597
|
+
// the blog zip lacks. The template text itself never matched `blog/*`.
|
|
598
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/", "/[...slug]", "/blog/[slug]"))).toThrow(/"\/\[\.\.\.slug\]" is packaged into the "default" group, but CloudFront would send "\/blog\/_\/_" to group "blog" \(its pattern "\/blog\/\*\*"\).*dynamic route "\/\[\.\.\.slug\]"/s);
|
|
599
|
+
});
|
|
600
|
+
it("checks under a basePath too", () => {
|
|
601
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/base", "/base/[...slug]", "/base/blog/[slug]"), "/base")).toThrow(/CloudFront would send "\/base\/blog\/_\/_" to group "blog"/);
|
|
602
|
+
});
|
|
603
|
+
it("accepts the capture when the group's own routes shadow every URL of it", () => {
|
|
604
|
+
// A more specific route in the capturing group wins inside Next.js, so
|
|
605
|
+
// with `/blog/[...rest]` there nothing under `/blog/` resolves to the
|
|
606
|
+
// root catch-all.
|
|
607
|
+
const assigned = assign([{ name: "blog", routes: ["/blog/**"] }], routes("/", "/[...slug]", "/blog/[slug]", "/blog/[...rest]"));
|
|
608
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/", "/[...slug]"]);
|
|
609
|
+
expect(assigned.blog).toEqual(["/blog/[...rest]", "/blog/[slug]"]);
|
|
610
|
+
});
|
|
611
|
+
it("accepts a single-segment root param, which never reaches under a subtree", () => {
|
|
612
|
+
const assigned = assign([{ name: "blog", routes: ["/blog/**"] }], routes("/", "/[slug]", "/blog/[slug]"));
|
|
613
|
+
expect(assigned[function_groups_1.DEFAULT_FUNCTION_GROUP]).toEqual(["/", "/[slug]"]);
|
|
614
|
+
});
|
|
615
|
+
it("rejects the trailingSlash form of a subtree's base that a root param serves", () => {
|
|
616
|
+
// `/blog/` matches `blog/*`, and with no `/blog` page Next.js serves it
|
|
617
|
+
// with `/[slug]`.
|
|
618
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/", "/[slug]", "/blog/[slug]"), "", { trailingSlash: true })).toThrow(/CloudFront would send "\/blog\/" to group "blog"/);
|
|
619
|
+
});
|
|
620
|
+
it("lets a static first segment in the group outrank a param in a later one", () => {
|
|
621
|
+
// `/blog/settings` reaches the blog function; `/blog/[slug]` beats
|
|
622
|
+
// `/[team]/settings` there, static first segment before dynamic.
|
|
623
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/", "/[team]/settings", "/blog/[slug]"))).not.toThrow();
|
|
624
|
+
// Without it, `/[team]/settings` is what Next.js resolves it to.
|
|
625
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], routes("/", "/[team]/settings", "/blog/x"))).toThrow(/"\/blog\/settings" to group "blog"/);
|
|
626
|
+
});
|
|
627
|
+
it("checks a root optional catch-all against subtree and exact patterns", () => {
|
|
628
|
+
expect(() => assign([{ name: "docs", routes: ["/docs/**"] }], routes("/[[...slug]]", "/docs/[page]"))).toThrow(/"\/docs\/_\/_" to group "docs"/);
|
|
629
|
+
// An exact pattern owns a static route, which Next.js prefers.
|
|
630
|
+
expect(assign([{ name: "about", routes: ["/about"] }], routes("/[[...slug]]", "/about")).about).toEqual(["/about"]);
|
|
631
|
+
});
|
|
632
|
+
it("checks a grouped catch-all against a narrower group's subtree", () => {
|
|
633
|
+
// `/api/reports/1/2` reaches the reports function, which only has
|
|
634
|
+
// `/api/reports/[id]`; Next.js resolves it to `/api/[...rest]`.
|
|
635
|
+
expect(() => assign([
|
|
636
|
+
{ name: "api", routes: ["/api/**"] },
|
|
637
|
+
{ name: "reports", routes: ["/api/reports/**"] },
|
|
638
|
+
], routes("/api/[...rest]", "/api/reports/[id]"))).toThrow(/"\/api\/\[\.\.\.rest\]" is packaged into group "api", but CloudFront would send "\/api\/reports\/_\/_" to group "reports"/);
|
|
639
|
+
});
|
|
640
|
+
it("checks a Pages Router catch-all's data URLs", () => {
|
|
641
|
+
const page = (template, file) => [
|
|
642
|
+
{ template, entrypointId: file, type: "page" },
|
|
643
|
+
{
|
|
644
|
+
template: `/_next/data/${BUILD_ID}${template}.json`,
|
|
645
|
+
entrypointId: file,
|
|
646
|
+
type: "page",
|
|
647
|
+
},
|
|
648
|
+
];
|
|
649
|
+
expect(() => assign([{ name: "blog", routes: ["/blog/**"] }], [
|
|
650
|
+
...page("/[...slug]", "pages/[...slug].js"),
|
|
651
|
+
...page("/blog/[slug]", "pages/blog/[slug].js"),
|
|
652
|
+
])).toThrow(/"\/_next\/data\/abc123\/blog\/_\/_\.json" to group "blog"/);
|
|
653
|
+
});
|
|
654
|
+
});
|
|
655
|
+
describe("/index (G)", () => {
|
|
656
|
+
it("groups an App Router /index, a route of its own", () => {
|
|
657
|
+
const assigned = assign([{ name: "idx", routes: ["/index"] }], [
|
|
658
|
+
{ template: "/", entrypointId: "app/page.js", type: "app-page" },
|
|
659
|
+
{
|
|
660
|
+
template: "/index.rsc",
|
|
661
|
+
entrypointId: "app/page.js",
|
|
662
|
+
type: "app-page",
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
template: "/index",
|
|
666
|
+
entrypointId: "app/index/page.js",
|
|
667
|
+
type: "app-page",
|
|
668
|
+
},
|
|
669
|
+
]);
|
|
670
|
+
expect(assigned.idx).toEqual(["/index"]);
|
|
671
|
+
});
|
|
672
|
+
it("rejects the Pages Router home page, which is also /", () => {
|
|
673
|
+
expect(() => assign([{ name: "idx", routes: ["/index"] }], ["/", "/index", `/_next/data/${BUILD_ID}/index.json`].map((template) => ({
|
|
674
|
+
template,
|
|
675
|
+
entrypointId: "pages/index.js",
|
|
676
|
+
type: "page",
|
|
677
|
+
})))).toThrow(/"\/" cannot be routed to any group.*"\/index": one file/s);
|
|
678
|
+
});
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
describe("routedPatterns", () => {
|
|
682
|
+
it("adds nothing for a group without an optional catch-all at a subtree's base", () => {
|
|
683
|
+
expect((0, function_groups_1.routedPatterns)(["/blog/**", "/pricing"], ["/blog/[slug]", "/blog/x/[[...rest]]", "/pricing"], "")).toEqual(["/blog/**", "/pricing"]);
|
|
684
|
+
});
|
|
685
|
+
it("does not repeat a parent the group already declares", () => {
|
|
686
|
+
expect((0, function_groups_1.routedPatterns)(["/shop/**", "/shop"], ["/shop/[[...slug]]"], "")).toEqual(["/shop/**", "/shop"]);
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
describe("pathPatternsFor", () => {
|
|
690
|
+
it("drops the leading slash, because the distribution adds basePath itself", () => {
|
|
691
|
+
expect((0, function_groups_1.pathPatternsFor)("/pricing", { hasDataRoutes: false })).toEqual([
|
|
692
|
+
"pricing",
|
|
693
|
+
]);
|
|
694
|
+
});
|
|
695
|
+
it("turns a subtree into a single trailing wildcard", () => {
|
|
696
|
+
expect((0, function_groups_1.pathPatternsFor)("/api/reports/**", { hasDataRoutes: false })).toEqual(["api/reports/*"]);
|
|
697
|
+
});
|
|
698
|
+
it("adds the `_next/data` URL space for Pages Router groups, on the literal build ID", () => {
|
|
699
|
+
// A `*` for the build ID also matches `/`, so `_next/data/*/blog/*` claimed
|
|
700
|
+
// `/_next/data/<id>/docs/blog/x.json`, a page of another group.
|
|
701
|
+
const options = { hasDataRoutes: true, buildId: BUILD_ID };
|
|
702
|
+
expect((0, function_groups_1.pathPatternsFor)("/blog/**", options)).toEqual([
|
|
703
|
+
"blog/*",
|
|
704
|
+
"_next/data/abc123/blog/*",
|
|
705
|
+
]);
|
|
706
|
+
expect((0, function_groups_1.pathPatternsFor)("/pricing", options)).toEqual([
|
|
707
|
+
"pricing",
|
|
708
|
+
"_next/data/abc123/pricing.json",
|
|
709
|
+
]);
|
|
710
|
+
});
|
|
711
|
+
it("refuses to route data URLs without the build ID", () => {
|
|
712
|
+
expect(() => (0, function_groups_1.pathPatternsFor)("/blog/**", { hasDataRoutes: true })).toThrow(/needs its build ID/);
|
|
713
|
+
});
|
|
714
|
+
it("refuses a build ID a path pattern cannot hold", () => {
|
|
715
|
+
// `generateBuildId` can return anything.
|
|
716
|
+
expect(() => (0, function_groups_1.pathPatternsFor)("/blog/**", { hasDataRoutes: true, buildId: "v1/2 3" })).toThrow(/The build ID "v1\/2 3" contains "\/", " "/);
|
|
717
|
+
});
|
|
718
|
+
it("adds the trailing-slash form for a trailingSlash app", async () => {
|
|
719
|
+
// With `trailingSlash: true` the canonical URL is `/pricing/`, and that is
|
|
720
|
+
// what every link in the app points at. A behavior on `pricing` alone does
|
|
721
|
+
// not match it, so the request fell through to the default function - which
|
|
722
|
+
// does not have the route packaged.
|
|
723
|
+
expect((0, function_groups_1.pathPatternsFor)("/pricing", { hasDataRoutes: false })).toEqual([
|
|
724
|
+
"pricing",
|
|
725
|
+
]);
|
|
726
|
+
expect((0, function_groups_1.pathPatternsFor)("/pricing", {
|
|
727
|
+
hasDataRoutes: false,
|
|
728
|
+
trailingSlash: true,
|
|
729
|
+
})).toEqual(["pricing", "pricing/"]);
|
|
730
|
+
});
|
|
731
|
+
it("leaves a subtree pattern alone, which already matches both forms", () => {
|
|
732
|
+
expect((0, function_groups_1.pathPatternsFor)("/api/reports/**", {
|
|
733
|
+
hasDataRoutes: false,
|
|
734
|
+
trailingSlash: true,
|
|
735
|
+
})).toEqual(["api/reports/*"]);
|
|
736
|
+
});
|
|
737
|
+
});
|
|
738
|
+
describe("parseFunctionGroupsEnv", () => {
|
|
739
|
+
it("returns undefined when unset", () => {
|
|
740
|
+
expect((0, function_groups_1.parseFunctionGroupsEnv)(undefined)).toBeUndefined();
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb24tZ3JvdXBzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWRhcHRlci9mdW5jdGlvbi1ncm91cHMudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHNEQUFzRDtBQUN0RCwrRUFBbUY7QUFDbkYsbUZBR3lEO0FBQ3pELDZGQUErRDtBQUMvRCxxRkFBdUQ7QUFDdkQsbURBQTZFO0FBQzdFLHVEQVkyQjtBQUUzQixnRUFBZ0U7QUFDaEUsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLFNBQW1CLEVBQWdCLEVBQUUsQ0FDdEQsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBRXRFLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUUxQjs7O0dBR0c7QUFDSCxTQUFTLFdBQVcsQ0FBQyxPQUFxQixFQUFFLFFBQWdCO0lBQzFELE1BQU0sVUFBVSxHQUFHLEdBQUcsUUFBUSxlQUFlLFFBQVEsR0FBRyxDQUFDO0lBQ3pELE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FDekUsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUNYLFFBQVEsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO1FBQ3RCLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7UUFDMUIsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUNoQyxDQUFDO0lBQ0YsTUFBTSxLQUFLLEdBQUcsQ0FBQyxRQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLFdBQVcsRUFBRSxJQUFBLGdDQUFrQixF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Q0FBZSxFQUFDLFVBQVUsRUFBRTtZQUMxQixhQUFhLEVBQUUsS0FBSztZQUNwQixhQUFhLEVBQUUsSUFBSTtTQUNwQixDQUFDLENBQ0gsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNyQyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxrRUFBa0UsRUFBRSxHQUFHLEVBQUU7UUFDMUUsTUFBTSxDQUNKLElBQUEsaUNBQWUsRUFBQyxpQkFBaUIsRUFBRTtZQUNqQyxhQUFhLEVBQUUsS0FBSztZQUNwQixhQUFhLEVBQUUsSUFBSTtTQUNwQixDQUFDLENBQ0gsQ0FBQyxPQUFPLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO0lBQy9CLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsd0JBQXdCLEVBQUUsR0FBRyxFQUFFO0lBQ3RDLEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxHQUFHLEVBQUU7UUFDdEMsTUFBTSxDQUFDLElBQUEsd0NBQXNCLEVBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUM1RCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5pbXBvcnQgeyBnZXROYW1lZFJvdXRlUmVnZXggfSBmcm9tIFwibmV4dC9kaXN0L3NoYXJlZC9saWIvcm91dGVyL3V0aWxzL3JvdXRlLXJlZ2V4XCI7XG5pbXBvcnQge1xuICBnZXRTb3J0ZWRSb3V0ZU9iamVjdHMsXG4gIGdldFNvcnRlZFJvdXRlcyxcbn0gZnJvbSBcIm5leHQvZGlzdC9zaGFyZWQvbGliL3JvdXRlci91dGlscy9zb3J0ZWQtcm91dGVzXCI7XG5pbXBvcnQgYXBwUGxheWdyb3VuZCBmcm9tIFwiLi9fX2ZpeHR1cmVzX18vYXBwLXBsYXlncm91bmQuanNvblwiO1xuaW1wb3J0IHBhZ2VzSTE4biBmcm9tIFwiLi9fX2ZpeHR1cmVzX18vcGFnZXMtaTE4bi5qc29uXCI7XG5pbXBvcnQgeyBCdWlsZENvbXBsZXRlQ29udGV4dCwgYnVpbGRBZGFwdGVyTWFuaWZlc3QgfSBmcm9tIFwiLi9idWlsZC1vdXRwdXRzXCI7XG5pbXBvcnQge1xuICBBc3NpZ25Sb3V0ZXNPcHRpb25zLFxuICBERUZBVUxUX0ZVTkNUSU9OX0dST1VQLFxuICBGdW5jdGlvbkdyb3VwU3BlYyxcbiAgUm91dGVFbnRyeSxcbiAgUm91dGluZ1J1bGVzLFxuICBhc3NpZ25Sb3V0ZXNUb0dyb3VwcyxcbiAgaW50ZXJjZXB0ZWRSb3V0ZSxcbiAgcGFyc2VGdW5jdGlvbkdyb3Vwc0VudixcbiAgcGF0aFBhdHRlcm5zRm9yLFxuICByb3V0ZWRQYXR0ZXJucyxcbiAgdmFsaWRhdGVGdW5jdGlvbkdyb3Vwcyxcbn0gZnJvbSBcIi4vZnVuY3Rpb24tZ3JvdXBzXCI7XG5cbi8qKiBPbmUgZW50cnlwb2ludCBwZXIgdGVtcGxhdGUgdW5sZXNzIGEgdGVzdCBzYXlzIG90aGVyd2lzZS4gKi9cbmNvbnN0IHJvdXRlcyA9ICguLi50ZW1wbGF0ZXM6IHN0cmluZ1tdKTogUm91dGVFbnRyeVtdID0+XG4gIHRlbXBsYXRlcy5tYXAoKHRlbXBsYXRlKSA9PiAoeyB0ZW1wbGF0ZSwgZW50cnlwb2ludElkOiB0ZW1wbGF0ZSB9KSk7XG5cbmNvbnN0IEJVSUxEX0lEID0gXCJhYmMxMjNcIjtcblxuLyoqXG4gKiBgY3R4LnJvdXRpbmcuZHluYW1pY1JvdXRlc2AgYXMgYG5leHQgYnVpbGRgIGRlcml2ZXMgaXQgZnJvbSBgZW50cmllc2A6IE5leHQnc1xuICogb3duIHJvdXRlIHNvcnQgYW5kIHJlZ2V4ZXMsIGRhdGEgVVJMcyBpbmNsdWRlZC5cbiAqL1xuZnVuY3Rpb24gbmV4dFJvdXRpbmcoZW50cmllczogUm91dGVFbnRyeVtdLCBiYXNlUGF0aDogc3RyaW5nKTogUm91dGluZ1J1bGVzIHtcbiAgY29uc3QgZGF0YVByZWZpeCA9IGAke2Jhc2VQYXRofS9fbmV4dC9kYXRhLyR7QlVJTERfSUR9L2A7XG4gIGNvbnN0IGR5bmFtaWMgPSBbLi4ubmV3IFNldChlbnRyaWVzLm1hcCgoZW50cnkpID0+IGVudHJ5LnRlbXBsYXRlKSldLmZpbHRlcihcbiAgICAodGVtcGxhdGUpID0+XG4gICAgICB0ZW1wbGF0ZS5pbmNsdWRlcyhcIltcIikgJiZcbiAgICAgICF0ZW1wbGF0ZS5lbmRzV2l0aChcIi5yc2NcIikgJiZcbiAgICAgICEvXFwoXFwuezEsM31cXCkvLnRlc3QodGVtcGxhdGUpLFxuICApO1xuICBjb25zdCByb3V0ZSA9ICh0ZW1wbGF0ZTogc3RyaW5nKSA9PiAoe1xuICAgIHNvdXJjZVJlZ2V4OiBnZXROYW1lZFJvdXRlUmVnZXgodGVtcGxhdGUsIHtcbiAgICAgIHByZWZpeFJvdXRlS2V5czogdHJ1ZSxcbiAgICAgIGluY2x1ZGVTdWZmaXg6IHRydWUsXG4gICAgfSkubmFtZWRSZWdleCxcbiAgICBkZXN0aW5hdGlvbjogdGVtcGxhdGUsXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIGR5bmFtaWNSb3V0ZXM6IFtcbiAgICAgIC8vIFNvcnRlZCBieSB0aGUgcGFnZSB0aGV5IG5hbWU6IE5leHQncyBzb3J0IHJlYWRzIGBbc2x1Z10uanNvbmAgYXMgc3RhdGljLlxuICAgICAgLi4uZ2V0U29ydGVkUm91dGVPYmplY3RzKFxuICAgICAgICBkeW5hbWljLmZpbHRlcigodGVtcGxhdGUpID0+IHRlbXBsYXRlLnN0YXJ0c1dpdGgoZGF0YVByZWZpeCkpLFxuICAgICAgICAodGVtcGxhdGUpID0+IGAvJHt0ZW1wbGF0ZS5zbGljZShkYXRhUHJlZml4Lmxlbmd0aCwgLVwiLmpzb25cIi5sZW5ndGgpfWAsXG4gICAgICApLm1hcChyb3V0ZSksXG4gICAgICAuLi5nZXRTb3J0ZWRSb3V0ZXMoXG4gICAgICAgIGR5bmFtaWMuZmlsdGVyKCh0ZW1wbGF0ZSkgPT4gIXRlbXBsYXRlLnN0YXJ0c1dpdGgoZGF0YVByZWZpeCkpLFxuICAgICAgKS5tYXAocm91dGUpLFxuICAgIF0sXG4gIH07XG59XG5cbmNvbnN0IGFzc2lnbm1lbnQgPSAoXG4gIGdyb3VwczogRnVuY3Rpb25Hcm91cFNwZWNbXSxcbiAgZW50cmllczogUm91dGVFbnRyeVtdLFxuICBiYXNlUGF0aCA9IFwiXCIsXG4gIG9wdGlvbnM6IFBhcnRpYWw8QXNzaWduUm91dGVzT3B0aW9ucz4gPSB7fSxcbikgPT5cbiAgYXNzaWduUm91dGVzVG9Hcm91cHMoZ3JvdXBzLCBlbnRyaWVzLCB7XG4gICAgYmFzZVBhdGgsXG4gICAgYnVpbGRJZDogQlVJTERfSUQsXG4gICAgLi4ub3B0aW9ucyxcbiAgICByb3V0aW5nOiB7IC4uLm5leHRSb3V0aW5nKGVudHJpZXMsIGJhc2VQYXRoKSwgLi4ub3B0aW9ucy5yb3V0aW5nIH0sXG4gIH0pO1xuXG5jb25zdCBhc3NpZ24gPSAoLi4uYXJnczogUGFyYW1ldGVyczx0eXBlb2YgYXNzaWdubWVudD4pID0+XG4gIGFzc2lnbm1lbnQoLi4uYXJncykudGVtcGxhdGVzO1xuXG4vKiogVGhlIHBhdGggcGF0dGVybnMgb2YgdGhlIGJlaGF2aW9ycyB0aGUgYXNzaWdubWVudCByZXR1cm5zLCBpbiBvcmRlci4gKi9cbmNvbnN0IHBhdHRlcm5zT2YgPSAoLi4uYXJnczogUGFyYW1ldGVyczx0eXBlb2YgYXNzaWdubWVudD4pID0+XG4gIGFzc2lnbm1lbnQoLi4uYXJncykuYmVoYXZpb3JzLm1hcCgoeyBwYXR0ZXJuIH0pID0+IHBhdHRlcm4pO1xuXG4vKipcbiAqIEEgY2FwdHVyZWQgYG9uQnVpbGRDb21wbGV0ZWAgZml4dHVyZSdzIHJvdXRlcywgZXhhY3RseSBhcyBgYnVpbGRBZGFwdGVyTWFuaWZlc3RgXG4gKiBoYW5kcyB0aGVtIHRvIHRoZSBhc3NpZ25tZW50LCBwbHVzIHRoZSByZXN0IG9mIHdoYXQgaXQgcGFzc2VzLlxuICovXG5mdW5jdGlvbiBmaXh0dXJlUm91dGVzKGZpeHR1cmU6IHVua25vd24pIHtcbiAgY29uc3QgY3R4ID0gc3RydWN0dXJlZENsb25lKGZpeHR1cmUpIGFzIEJ1aWxkQ29tcGxldGVDb250ZXh0O1xuICBjb25zdCB3YXJuID0gamVzdC5zcHlPbihjb25zb2xlLCBcIndhcm5cIikubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHt9KTtcbiAgY29uc3QgeyBtYW5pZmVzdCB9ID0gYnVpbGRBZGFwdGVyTWFuaWZlc3QoY3R4LCB7IGJ1aWxkQ3dkOiBjdHgucHJvamVjdERpciB9KTtcbiAgd2Fybi5tb2NrUmVzdG9yZSgpO1xuICBjb25zdCBlbnRyaWVzOiBSb3V0ZUVudHJ5W10gPSBPYmplY3QuZW50cmllcyhtYW5pZmVzdC5lbnRyeXBvaW50cykubWFwKFxuICAgIChbdGVtcGxhdGUsIGVudHJ5cG9pbnRdKSA9PiAoe1xuICAgICAgdGVtcGxhdGUsXG4gICAgICBlbnRyeXBvaW50SWQ6IGVudHJ5cG9pbnQuZmlsZVBhdGgsXG4gICAgICB0eXBlOiBlbnRyeXBvaW50LnR5cGUsXG4gICAgfSksXG4gICk7XG4gIHJldHVybiB7XG4gICAgZW50cmllcyxcbiAgICBvcHRpb25zOiB7XG4gICAgICBiYXNlUGF0aDogY3R4LmNvbmZpZy5iYXNlUGF0aCB8fCBcIlwiLFxuICAgICAgYnVpbGRJZDogY3R4LmJ1aWxkSWQsXG4gICAgICB0cmFpbGluZ1NsYXNoOiBjdHguY29uZmlnLnRyYWlsaW5nU2xhc2ggPT09IHRydWUsXG4gICAgICByb3V0aW5nOiBjdHgucm91dGluZyxcbiAgICB9IGFzIEFzc2lnblJvdXRlc09wdGlvbnMsXG4gIH07XG59XG5cbmRlc2NyaWJlKFwidmFsaWRhdGVGdW5jdGlvbkdyb3Vwc1wiLCAoKSA9PiB7XG4gIGl0KFwicmVqZWN0cyBhbiBlbXB0eSBhcnJheSByYXRoZXIgdGhhbiB0cmVhdGluZyBpdCBhcyBubyBzcGxpdHRpbmdcIiwgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFtdKSkudG9UaHJvdygvT21pdCB0aGUgcHJvcCBlbnRpcmVseS8pO1xuICB9KTtcblxuICBpdChcInJlc2VydmVzIHRoZSBkZWZhdWx0IGdyb3VwIG5hbWVcIiwgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgdmFsaWRhdGVGdW5jdGlvbkdyb3VwcyhbeyBuYW1lOiBcImRlZmF1bHRcIiwgcm91dGVzOiBbXCIvYVwiXSB9XSksXG4gICAgKS50b1Rocm93KC9yZXNlcnZlZCBncm91cCBuYW1lLyk7XG4gIH0pO1xuXG4gIGl0LmVhY2goW1tcImhhcyBzcGFjZVwiXSwgW1widW5kZXJfc2NvcmVcIl0sIFtcImRvdHMuaGVyZVwiXSwgW1wiXCJdXSkoXG4gICAgXCJyZWplY3RzIGdyb3VwIG5hbWUgJXAsIHdoaWNoIGhhcyB0byBiZSBhIGNvbnN0cnVjdCBpZFwiLFxuICAgIChuYW1lKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT4gdmFsaWRhdGVGdW5jdGlvbkdyb3VwcyhbeyBuYW1lLCByb3V0ZXM6IFtcIi9hXCJdIH1dKSkudG9UaHJvdyhcbiAgICAgICAgL211c3QgbWF0Y2gvLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIGl0KFwicmVqZWN0cyB0d28gZ3JvdXBzIHdpdGggdGhlIHNhbWUgbmFtZVwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+XG4gICAgICB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFtcbiAgICAgICAgeyBuYW1lOiBcImFwaVwiLCByb3V0ZXM6IFtcIi9hXCJdIH0sXG4gICAgICAgIHsgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXCIvYlwiXSB9LFxuICAgICAgXSksXG4gICAgKS50b1Rocm93KC9ib3RoIG5hbWVkIFwiYXBpXCIvKTtcbiAgfSk7XG5cbiAgaXQoXCJyZWplY3RzIGEgZ3JvdXAgdGhhdCBvd25zIG5vIHJvdXRlc1wiLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHZhbGlkYXRlRnVuY3Rpb25Hcm91cHMoW3sgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXSB9XSkpLnRvVGhyb3coXG4gICAgICAvb3ducyBubyByb3V0ZXMvLFxuICAgICk7XG4gIH0pO1xuXG4gIGl0KFwicmVqZWN0cyB0aGUgc2FtZSBwYXR0ZXJuIGluIHR3byBncm91cHNcIiwgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgdmFsaWRhdGVGdW5jdGlvbkdyb3VwcyhbXG4gICAgICAgIHsgbmFtZTogXCJhXCIsIHJvdXRlczogW1wiL2FwaS8qKlwiXSB9LFxuICAgICAgICB7IG5hbWU6IFwiYlwiLCByb3V0ZXM6IFtcIi9hcGkvKipcIl0gfSxcbiAgICAgIF0pLFxuICAgICkudG9UaHJvdygvYXBwZWFycyBpbiBib3RoIGdyb3VwIFwiYVwiIGFuZCBncm91cCBcImJcIi8pO1xuICB9KTtcblxuICBpdChcImFsbG93cyBvdmVybGFwcGluZy1idXQtZGlmZmVyZW50IHBhdHRlcm5zLCB3aGljaCByZXNvbHZlIGxvbmdlc3QtZmlyc3RcIiwgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgdmFsaWRhdGVGdW5jdGlvbkdyb3VwcyhbXG4gICAgICAgIHsgbmFtZTogXCJhXCIsIHJvdXRlczogW1wiL2FwaS8qKlwiXSB9LFxuICAgICAgICB7IG5hbWU6IFwiYlwiLCByb3V0ZXM6IFtcIi9hcGkvcmVwb3J0cy8qKlwiXSB9LFxuICAgICAgXSksXG4gICAgKS5ub3QudG9UaHJvdygpO1xuICB9KTtcblxuICBpdChcInJlcXVpcmVzIGEgbGVhZGluZyBzbGFzaFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+XG4gICAgICB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFt7IG5hbWU6IFwiYVwiLCByb3V0ZXM6IFtcImFwaS8qKlwiXSB9XSksXG4gICAgKS50b1Rocm93KC9tdXN0IHN0YXJ0IHdpdGggXCJcXC9cIi8pO1xuICB9KTtcblxuICBpdC5lYWNoKFtbXCIvZGFzaGJvYXJkL1tpZF1cIl0sIFtcIi9ibG9nL1suLi5zbHVnXVwiXSwgW1wiL3Nob3AvW1suLi5zbHVnXV1cIl1dKShcbiAgICBcInJlamVjdHMgdGhlIGR5bmFtaWMgc2VnbWVudCBpbiAlcCwgd2hpY2ggQ2xvdWRGcm9udCBjYW5ub3QgZXhwcmVzc1wiLFxuICAgIChyb3V0ZSkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIHZhbGlkYXRlRnVuY3Rpb25Hcm91cHMoW3sgbmFtZTogXCJhXCIsIHJvdXRlczogW3JvdXRlXSB9XSksXG4gICAgICApLnRvVGhyb3coL2NvbnRhaW5zIGEgZHluYW1pYyBzZWdtZW50Lyk7XG4gICAgfSxcbiAgKTtcblxuICBpdChcInJlamVjdHMgYSByb3V0ZSBncm91cCBzZWdtZW50LCB3aGljaCBuZXZlciBhcHBlYXJzIGluIGEgVVJMXCIsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT5cbiAgICAgIHZhbGlkYXRlRnVuY3Rpb25Hcm91cHMoW3sgbmFtZTogXCJhXCIsIHJvdXRlczogW1wiLyhtYXJrZXRpbmcpL2Fib3V0XCJdIH1dKSxcbiAgICApLnRvVGhyb3coL3JvdXRlIGdyb3VwIHNlZ21lbnQvKTtcbiAgfSk7XG5cbiAgaXQuZWFjaChbW1wiL2FwaS8qXCJdLCBbXCIvYXBpLyoqL3hcIl0sIFtcIi9hcGkvcmVwbz90c1wiXSwgW1wiLypcIl1dKShcbiAgICBcInJlamVjdHMgdGhlIHdpbGRjYXJkIHBsYWNlbWVudCBpbiAlcFwiLFxuICAgIChyb3V0ZSkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIHZhbGlkYXRlRnVuY3Rpb25Hcm91cHMoW3sgbmFtZTogXCJhXCIsIHJvdXRlczogW3JvdXRlXSB9XSksXG4gICAgICApLnRvVGhyb3coL3dpbGRjYXJkIHNvbWV3aGVyZSBvdGhlciB0aGFuIGEgdHJhaWxpbmcvKTtcbiAgICB9LFxuICApO1xuXG4gIGl0KFwicmVqZWN0cyBhIHBhdHRlcm4gdGhhdCB3b3VsZCBvd24gZXZlcnl0aGluZ1wiLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+XG4gICAgICB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFt7IG5hbWU6IFwiYVwiLCByb3V0ZXM6IFtcIi8qKlwiXSB9XSksXG4gICAgKS50b1Rocm93KC93b3VsZCBvd24gZXZlcnkgcm91dGUvKTtcbiAgfSk7XG5cbiAgaXQoXCJyZWplY3RzIHRoZSByb290LCB3aGljaCBubyBDbG91ZEZyb250IHBhdGggcGF0dGVybiBjYW4gbWF0Y2ggYWxvbmVcIiwgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgdmFsaWRhdGVGdW5jdGlvbkdyb3VwcyhbeyBuYW1lOiBcImFcIiwgcm91dGVzOiBbXCIvXCJdIH1dKSxcbiAgICApLnRvVGhyb3coL2Nhbm5vdCBiZSByb3V0ZWQvKTtcbiAgfSk7XG5cbiAgaXQoXCJhY2NlcHRzIC9pbmRleCwgd2hpY2ggaXMgYSByZWFsIEFwcCBSb3V0ZXIgcm91dGVcIiwgKCkgPT4ge1xuICAgIC8vIGBhcHAvaW5kZXgvcGFnZS50c3hgIGlzIHNlcnZlZCBhdCBgL2luZGV4YCwgYXBhcnQgZnJvbSBgL2AuIE9ubHkgdGhlXG4gICAgLy8gYXNzaWdubWVudCBrbm93cyB3aGljaCByb3V0ZXIgYC9pbmRleGAgY2FtZSBmcm9tOyBpdCByZWplY3RzIHRoZSBQYWdlc1xuICAgIC8vIFJvdXRlciBob21lIHBhZ2UsIHdoaWNoIGlzIHRoZSBzYW1lIGZpbGUgYXMgYC9gLlxuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgdmFsaWRhdGVGdW5jdGlvbkdyb3VwcyhbeyBuYW1lOiBcImFcIiwgcm91dGVzOiBbXCIvaW5kZXhcIl0gfV0pLFxuICAgICkubm90LnRvVGhyb3coKTtcbiAgfSk7XG5cbiAgaXQuZWFjaChbXCIvX25leHRcIiwgXCIvX25leHQvKipcIiwgXCIvX25leHQvZGF0YS8qKlwiXSkoXG4gICAgXCJyZWplY3RzICVzLCB3aGljaCBOZXh0LmpzIHJlc2VydmVzXCIsXG4gICAgKHJvdXRlKSA9PiB7XG4gICAgICAvLyBBIGRhdGEgcm91dGUgZm9sbG93cyBpdHMgcGFnZSBpbnRvIHRoZSBwYWdlJ3MgZ3JvdXA7IGEgYF9uZXh0LypgXG4gICAgICAvLyBiZWhhdmlvciB3b3VsZCBjb21wZXRlIHdpdGggdGhlIHN0YXRpYy1hc3NldCBhbmQgaW1hZ2UgYmVoYXZpb3JzLlxuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIHZhbGlkYXRlRnVuY3Rpb25Hcm91cHMoW3sgbmFtZTogXCJhXCIsIHJvdXRlczogW3JvdXRlXSB9XSksXG4gICAgICApLnRvVGhyb3coL3VuZGVyIFwiXFwvX25leHRcIi8pO1xuICAgIH0sXG4gICk7XG5cbiAgaXQoXCJyZWplY3RzIGFuIGVtcHR5IHBhdGggc2VnbWVudFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+XG4gICAgICB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFt7IG5hbWU6IFwiYVwiLCByb3V0ZXM6IFtcIi9hcGkvL3hcIl0gfV0pLFxuICAgICkudG9UaHJvdygvZW1wdHkgcGF0aCBzZWdtZW50Lyk7XG4gIH0pO1xuXG4gIGl0LmVhY2goW1xuICAgIFtcIi/DvGJlclwiLCAnXCLDvFwiJ10sXG4gICAgW1wiL2EgYlwiLCAnXCIgXCInXSxcbiAgICBbXCIvc2hvcC9hLGIvKipcIiwgJ1wiLFwiJ10sXG4gICAgW1wiLzEwMCUyNVwiLCAnXCIlXCInXSxcbiAgXSkoXG4gICAgXCJyZWplY3RzICVwLCB3aGljaCBob2xkcyBhIGNoYXJhY3RlciBubyBDbG91ZEZyb250IHBhdGggcGF0dGVybiBjYW5cIixcbiAgICAocm91dGUsIGNoYXIpID0+IHtcbiAgICAgIC8vIGBwYXRoUGF0dGVybnNGb3JgIGNvcGllcyB0aGUgcm91dGUgdmVyYmF0aW0gaW50byBhIGJlaGF2aW9yIHBhdGhcbiAgICAgIC8vIHBhdHRlcm4sIHNvIHdpdGhvdXQgdGhpcyBpdCBmYWlsZWQgYXQgZGVwbG95IG5hbWluZyBuZWl0aGVyIHRoZSBncm91cFxuICAgICAgLy8gbm9yIHRoZSByb3V0ZS5cbiAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICB2YWxpZGF0ZUZ1bmN0aW9uR3JvdXBzKFt7IG5hbWU6IFwiYVwiLCByb3V0ZXM6IFtyb3V0ZV0gfV0pLFxuICAgICAgKS50b1Rocm93KGBjb250YWlucyAke2NoYXJ9LCB3aGljaCBhIENsb3VkRnJvbnQgYmVoYXZpb3IgcGF0aCBwYXR0ZXJuYCk7XG4gICAgfSxcbiAgKTtcblxuICBpdChcImFjY2VwdHMgZXZlcnkgbGl0ZXJhbCBpbiBDbG91ZEZyb250J3MgcGF0aCBwYXR0ZXJuIGFscGhhYmV0XCIsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT5cbiAgICAgIHZhbGlkYXRlRnVuY3Rpb25Hcm91cHMoW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJhXCIsXG4gICAgICAgICAgcm91dGVzOiBbYC9BWmF6MDlfLS4kflwiJ0A6KyYvKipgXSxcbiAgICAgICAgfSxcbiAgICAgIF0pLFxuICAgICkubm90LnRvVGhyb3coKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJhc3NpZ25Sb3V0ZXNUb0dyb3Vwc1wiLCAoKSA9PiB7XG4gIGl0KFwicHV0cyB1bmFzc2lnbmVkIHJvdXRlcyBpbiB0aGUgZGVmYXVsdCBncm91cCwgd2hpY2ggYWx3YXlzIGV4aXN0c1wiLCAoKSA9PiB7XG4gICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICBbeyBuYW1lOiBcImFwaVwiLCByb3V0ZXM6IFtcIi9hcGkvKipcIl0gfV0sXG4gICAgICByb3V0ZXMoXCIvXCIsIFwiL3ByaWNpbmdcIiwgXCIvYXBpL2hlYWx0aFwiKSxcbiAgICApO1xuICAgIGV4cGVjdChhc3NpZ25lZCkudG9FcXVhbCh7XG4gICAgICBbREVGQVVMVF9GVU5DVElPTl9HUk9VUF06IFtcIi9cIiwgXCIvcHJpY2luZ1wiXSxcbiAgICAgIGFwaTogW1wiL2FwaS9oZWFsdGhcIl0sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KFwibWF0Y2hlcyBhbiBleGFjdCBwYXR0ZXJuIG9ubHkgZXhhY3RseVwiLCAoKSA9PiB7XG4gICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICBbeyBuYW1lOiBcInBcIiwgcm91dGVzOiBbXCIvcHJpY2luZ1wiXSB9XSxcbiAgICAgIHJvdXRlcyhcIi9wcmljaW5nXCIsIFwiL3ByaWNpbmcvZW50ZXJwcmlzZVwiKSxcbiAgICApO1xuICAgIGV4cGVjdChhc3NpZ25lZC5wKS50b0VxdWFsKFtcIi9wcmljaW5nXCJdKTtcbiAgICBleHBlY3QoYXNzaWduZWRbREVGQVVMVF9GVU5DVElPTl9HUk9VUF0pLnRvRXF1YWwoW1wiL3ByaWNpbmcvZW50ZXJwcmlzZVwiXSk7XG4gIH0pO1xuXG4gIGl0KFwibWF0Y2hlcyBhIHN1YnRyZWUgYWdhaW5zdCB0aGUgZHluYW1pYyByb3V0ZXMgdW5kZXIgaXRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGFzc2lnbmVkID0gYXNzaWduKFxuICAgICAgW3sgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfV0sXG4gICAgICByb3V0ZXMoXCIvYmxvZy9bc2x1Z11cIiwgXCIvYmxvZy9bc2x1Z10vY29tbWVudHNcIiwgXCIvYmxvZ3JvbGxcIiksXG4gICAgKTtcbiAgICBleHBlY3QoYXNzaWduZWQuYmxvZykudG9FcXVhbChbXCIvYmxvZy9bc2x1Z11cIiwgXCIvYmxvZy9bc2x1Z10vY29tbWVudHNcIl0pO1xuICAgIGV4cGVjdChhc3NpZ25lZFtERUZBVUxUX0ZVTkNUSU9OX0dST1VQXSkudG9FcXVhbChbXCIvYmxvZ3JvbGxcIl0pO1xuICB9KTtcblxuICBpdChcImRvZXMgbm90IGxldCBhIHN1YnRyZWUgY2xhaW0gaXRzIG93biByb290LCBiZWNhdXNlIHRoZSBiZWhhdmlvciB3b3VsZCBub3RcIiwgKCkgPT4ge1xuICAgIC8vIGAvYXBpL3JlcG9ydHMvKipgIGRlcGxveXMgYXMgQ2xvdWRGcm9udCBgYXBpL3JlcG9ydHMvKmAsIHdoaWNoIGRvZXMgbm90XG4gICAgLy8gbWF0Y2ggYC9hcGkvcmVwb3J0c2AuIENsYWltaW5nIGl0IGhlcmUgd291bGQgcGFja2FnZSB0aGUgcm91dGUgaW50byBhXG4gICAgLy8gZnVuY3Rpb24gdGhlIGVkZ2UgbmV2ZXIgcm91dGVzIGl0IHRvLlxuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgYXNzaWduKFxuICAgICAgICBbeyBuYW1lOiBcInJcIiwgcm91dGVzOiBbXCIvYXBpL3JlcG9ydHMvKipcIl0gfV0sXG4gICAgICAgIHJvdXRlcyhcIi9hcGkvcmVwb3J0c1wiKSxcbiAgICAgICksXG4gICAgKS50b1Rocm93KC9tYXRjaGVzIG5vIHJvdXRlIGluIHRoaXMgYnVpbGQvKTtcbiAgfSk7XG5cbiAgaXQoXCJnaXZlcyB0aGUgbG9uZ2VzdCBtYXRjaGluZyBwYXR0ZXJuIHRoZSByb3V0ZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICBbXG4gICAgICAgIHsgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXCIvYXBpLyoqXCJdIH0sXG4gICAgICAgIHsgbmFtZTogXCJyZXBvcnRzXCIsIHJvdXRlczogW1wiL2FwaS9yZXBvcnRzLyoqXCJdIH0sXG4gICAgICBdLFxuICAgICAgcm91dGVzKFwiL2FwaS9oZWFsdGhcIiwgXCIvYXBpL3JlcG9ydHMvW2lkXVwiKSxcbiAgICApO1xuICAgIGV4cGVjdChhc3NpZ25lZC5hcGkpLnRvRXF1YWwoW1wiL2FwaS9oZWFsdGhcIl0pO1xuICAgIGV4cGVjdChhc3NpZ25lZC5yZXBvcnRzKS50b0VxdWFsKFtcIi9hcGkvcmVwb3J0cy9baWRdXCJdKTtcbiAgfSk7XG5cbiAgaXQoXCJyYW5rcyBieSBzZWdtZW50IGNvdW50IGJlZm9yZSBzdHJpbmcgbGVuZ3RoXCIsICgpID0+IHtcbiAgICAvLyBcIi9hL2JcIiBpcyBkZWVwZXIgdGhhbiBcIi9hbG9uZ25hbWVcIiBldmVuIHRob3VnaCBpdCBpcyBzaG9ydGVyLlxuICAgIGNvbnN0IGFzc2lnbmVkID0gYXNzaWduKFxuICAgICAgW1xuICAgICAgICB7IG5hbWU6IFwiZGVlcFwiLCByb3V0ZXM6IFtcIi9hL2IvKipcIl0gfSxcbiAgICAgICAgeyBuYW1lOiBcImxvbmdcIiwgcm91dGVzOiBbXCIvYS8qKlwiXSB9LFxuICAgICAgXSxcbiAgICAgIHJvdXRlcyhcIi9hL2IvY1wiLCBcIi9hL3hcIiksXG4gICAgKTtcbiAgICBleHBlY3QoYXNzaWduZWQuZGVlcCkudG9FcXVhbChbXCIvYS9iL2NcIl0pO1xuICAgIGV4cGVjdChhc3NpZ25lZC5sb25nKS50b0VxdWFsKFtcIi9hL3hcIl0pO1xuICB9KTtcblxuICBpdChcInRocm93cyBvbiBhIHBhdHRlcm4gdGhhdCBtYXRjaGVzIG5vdGhpbmcsIGJlY2F1c2UgdGhlIHR5cG8gaXMgaW52aXNpYmxlXCIsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT5cbiAgICAgIGFzc2lnbihcbiAgICAgICAgW3sgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXCIvYXBpLyoqXCIsIFwiL2FweS8qKlwiXSB9XSxcbiAgICAgICAgcm91dGVzKFwiL2FwaS94XCIpLFxuICAgICAgKSxcbiAgICApLnRvVGhyb3coL3BhdHRlcm4gXCJcXC9hcHlcXC9cXCpcXCpcIiBtYXRjaGVzIG5vIHJvdXRlLyk7XG4gIH0pO1xuXG4gIGl0KFwiYWNjZXB0cyBhIHBhdHRlcm4gZXZlcnkgbWF0Y2ggb2Ygd2hpY2ggYSBuYXJyb3dlciBwYXR0ZXJuIGFsc28gY2xhaW1zXCIsICgpID0+IHtcbiAgICAvLyBgL2FwaS8qKmAgbmV2ZXIgd2lucyBhIHJvdXRlIGhlcmUsIGJlY2F1c2UgZXZlcnkgQVBJIHJvdXRlIHRoaXMgYnVpbGQgaGFzXG4gICAgLy8gaXMgdW5kZXIgYC9hcGkvcmVwb3J0cy9gLiBSZWNvcmRpbmcgb25seSB0aGUgKndpbm5pbmcqIHBhdHRlcm4gbWFkZSBpdCBsb29rXG4gICAgLy8gbGlrZSBhIHR5cG8gYW5kIHRocmV3IC0gcmVqZWN0aW5nIHRoZSBleGFjdCBsYXlvdXQgdGhlIGR1cGxpY2F0ZS1wYXR0ZXJuXG4gICAgLy8gZXJyb3IgZG9jdW1lbnRzIGFzIHN1cHBvcnRlZC4gVGhlIGdyb3VwIGlzIGxlZ2l0aW1hdGVseSBlbXB0eTogaXQgaXMgdGhlXG4gICAgLy8gY29uc3VtZXIncyBjaG9pY2UgdG8ga2VlcCBpdCBmb3IgdGhlIHJvdXRlcyBpdCB3aWxsIG93biBsYXRlci5cbiAgICBjb25zdCBhc3NpZ25lZCA9IGFzc2lnbihcbiAgICAgIFtcbiAgICAgICAgeyBuYW1lOiBcImFwaVwiLCByb3V0ZXM6IFtcIi9hcGkvKipcIl0gfSxcbiAgICAgICAgeyBuYW1lOiBcInJlcG9ydHNcIiwgcm91dGVzOiBbXCIvYXBpL3JlcG9ydHMvKipcIl0gfSxcbiAgICAgIF0sXG4gICAgICByb3V0ZXMoXCIvYXBpL3JlcG9ydHMvW2lkXVwiLCBcIi9hcGkvcmVwb3J0cy9zdW1tYXJ5XCIpLFxuICAgICk7XG4gICAgZXhwZWN0KGFzc2lnbmVkLmFwaSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0KGFzc2lnbmVkLnJlcG9ydHMpLnRvRXF1YWwoW1xuICAgICAgXCIvYXBpL3JlcG9ydHMvW2lkXVwiLFxuICAgICAgXCIvYXBpL3JlcG9ydHMvc3VtbWFyeVwiLFxuICAgIF0pO1xuICB9KTtcblxuICBpdChcImdpdmVzIGEgc2hhcmVkIGVudHJ5cG9pbnQgdG8gaXRzIG1vc3Qgc3BlY2lmaWMgbWF0Y2gsIG5vdCBpdHMgbGFzdCBvbmVcIiwgKCkgPT4ge1xuICAgIC8vIFR3byB0ZW1wbGF0ZXMsIG9uZSBmaWxlLCB0d28gZ3JvdXBzIHdob3NlIHBhdHRlcm5zIGJvdGggbWF0Y2ggLSBvbmVcbiAgICAvLyBuYXJyb3dseSwgb25lIGJyb2FkbHkuIE93bmVyc2hpcCB1c2VkIHRvIGJlIGxhc3Qtd3JpdGUtd2lucyBvdmVyIGBlbnRyaWVzYCxcbiAgICAvLyBzbyB0aGUgc2FtZSBidWlsZCBncm91cGVkIGRpZmZlcmVudGx5IGRlcGVuZGluZyBvbiBtYW5pZmVzdCBrZXkgb3JkZXIuXG4gICAgY29uc3QgZW50cmllczogUm91dGVFbnRyeVtdID0gW1xuICAgICAgLy8gTWF0Y2hlZCBvbmx5IGJ5IHRoZSBicm9hZCBwYXR0ZXJuLlxuICAgICAgeyB0ZW1wbGF0ZTogXCIvYXBpL2hlYWx0aFwiLCBlbnRyeXBvaW50SWQ6IFwic2hhcmVkXCIgfSxcbiAgICAgIC8vIE1hdGNoZWQgYnkgYm90aDsgdGhlIG5hcnJvdyBvbmUgd2lucy5cbiAgICAgIHsgdGVtcGxhdGU6IFwiL2FwaS9yZXBvcnRzL3N1bW1hcnlcIiwgZW50cnlwb2ludElkOiBcInNoYXJlZFwiIH0sXG4gICAgXTtcbiAgICBjb25zdCBncm91cHM6IEZ1bmN0aW9uR3JvdXBTcGVjW10gPSBbXG4gICAgICB7IG5hbWU6IFwiYXBpXCIsIHJvdXRlczogW1wiL2FwaS8qKlwiXSB9LFxuICAgICAgeyBuYW1lOiBcInJlcG9ydHNcIiwgcm91dGVzOiBbXCIvYXBpL3JlcG9ydHMvKipcIl0gfSxcbiAgICBdO1xuICAgIC8vIGAvYXBpL3JlcG9ydHMvKipgIGlzIHRoZSBtb3N0IHNwZWNpZmljIGNsYWltIGFueSBvZiB0aGUgZW50cnlwb2ludCdzXG4gICAgLy8gdGVtcGxhdGVzIGhhcywgc28gaXQgdGFrZXMgdGhlIHdob2xlIGVudHJ5cG9pbnQg4oCUIGFuZCB0aGVuIHRoZSBlZGdlIHN0aWxsXG4gICAgLy8gc2VuZHMgYC9hcGkvaGVhbHRoYCB0byB0aGUgYXBpIGdyb3VwLCB3aGljaCBsYWNrcyB0aGUgZmlsZS4gVGhhdCB1c2VkIHRvXG4gICAgLy8gZGVwbG95IGFuZCA1MDA7IGl0IGlzIHRoZSBjb3ZlcmFnZSBjaGVjaydzIHRvIHJlamVjdCwgaWRlbnRpY2FsbHkgaW4gYm90aFxuICAgIC8vIG9yZGVycy5cbiAgICBjb25zdCBtZXNzYWdlID1cbiAgICAgIC9cIlxcL2FwaVxcL2hlYWx0aFwiIHRvIGdyb3VwIFwiYXBpXCIgXFwoaXRzIHBhdHRlcm4gXCJcXC9hcGlcXC9cXCpcXCpcIlxcKS87XG4gICAgZXhwZWN0KCgpID0+IGFzc2lnbihncm91cHMsIGVudHJpZXMpKS50b1Rocm93KG1lc3NhZ2UpO1xuICAgIGV4cGVjdCgoKSA9PiBhc3NpZ24oZ3JvdXBzLCBbLi4uZW50cmllc10ucmV2ZXJzZSgpKSkudG9UaHJvdyhtZXNzYWdlKTtcbiAgICBleHBlY3QoKCkgPT4gYXNzaWduKGdyb3VwcywgZW50cmllcykpLnRvVGhyb3coXG4gICAgICAvQWRkIFwiXFwvYXBpXFwvaGVhbHRoXCIgdG8gZ3JvdXAgXCJyZXBvcnRzXCIncyByb3V0ZXMvLFxuICAgICk7XG4gICAgLy8gV2hpY2ggaXMgdGhlIGZpeDogdGhlIGV4YWN0IHBhdHRlcm4gYmVhdHMgdGhlIGFwaSBzdWJ0cmVlIGF0IHRoZSBlZGdlLlxuICAgIGNvbnN0IGZpeGVkID0gYXNzaWduKFxuICAgICAgW1xuICAgICAgICBncm91cHNbMF0sXG4gICAgICAgIHsgbmFtZTogXCJyZXBvcnRzXCIsIHJvdXRlczogW1wiL2FwaS9yZXBvcnRzLyoqXCIsIFwiL2FwaS9oZWFsdGhcIl0gfSxcbiAgICAgIF0sXG4gICAgICBlbnRyaWVzLFxuICAgICk7XG4gICAgZXhwZWN0KGZpeGVkLnJlcG9ydHMpLnRvRXF1YWwoW1wiL2FwaS9oZWFsdGhcIiwgXCIvYXBpL3JlcG9ydHMvc3VtbWFyeVwiXSk7XG4gICAgZXhwZWN0KGZpeGVkLmFwaSkudG9FcXVhbChbXSk7XG4gIH0pO1xuXG4gIGl0KFwicHJlZml4ZXMgYmFzZVBhdGggYmVmb3JlIG1hdGNoaW5nLCBzaW5jZSBtYW5pZmVzdCB0ZW1wbGF0ZXMgY2FycnkgaXRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGFzc2lnbmVkID0gYXNzaWduKFxuICAgICAgW3sgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXCIvYXBpLyoqXCJdIH1dLFxuICAgICAgcm91dGVzKFwiL3Byb2QvYXBpL2hlYWx0aFwiLCBcIi9wcm9kL3ByaWNpbmdcIiksXG4gICAgICBcIi9wcm9kXCIsXG4gICAgKTtcbiAgICBleHBlY3QoYXNzaWduZWQuYXBpKS50b0VxdWFsKFtcIi9wcm9kL2FwaS9oZWFsdGhcIl0pO1xuICAgIGV4cGVjdChhc3NpZ25lZFtERUZBVUxUX0ZVTkNUSU9OX0dST1VQXSkudG9FcXVhbChbXCIvcHJvZC9wcmljaW5nXCJdKTtcbiAgfSk7XG5cbiAgaXQoXCJrZWVwcyB0d28gdGVtcGxhdGVzIHNoYXJpbmcgb25lIGVudHJ5cG9pbnQgaW4gdGhlIHNhbWUgZ3JvdXBcIiwgKCkgPT4ge1xuICAgIC8vIEEgUGFnZXMgUm91dGVyIHBhZ2UgYW5kIGl0cyBgL19uZXh0L2RhdGEvPGJ1aWxkSWQ+L+KApmpzb25gIHNpYmxpbmcgYXJlIG9uZVxuICAgIC8vIGZpbGU7IHNwbGl0dGluZyB0aGVtIHdvdWxkIHN0YWdlIGl0IHR3aWNlIGFuZCBtaXNyb3V0ZSBvbmUgb2YgdGhlbS5cbiAgICBjb25zdCBhc3NpZ25lZCA9IGFzc2lnbihcbiAgICAgIFt7IG5hbWU6IFwiYmxvZ1wiLCByb3V0ZXM6IFtcIi9ibG9nLyoqXCJdIH1dLFxuICAgICAgW1xuICAgICAgICB7XG4gICAgICAgICAgdGVtcGxhdGU6IFwiL2Jsb2cvW3NsdWddXCIsXG4gICAgICAgICAgZW50cnlwb2ludElkOiBcInBhZ2VzL2Jsb2cvW3NsdWddXCIsXG4gICAgICAgICAgdHlwZTogXCJwYWdlXCIsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZW1wbGF0ZTogXCIvX25leHQvZGF0YS9hYmMxMjMvYmxvZy9bc2x1Z10uanNvblwiLFxuICAgICAgICAgIGVudHJ5cG9pbnRJZDogXCJwYWdlcy9ibG9nL1tzbHVnXVwiLFxuICAgICAgICAgIHR5cGU6IFwicGFnZVwiLFxuICAgICAgICB9LFxuICAgICAgICB7IHRlbXBsYXRlOiBcIi9cIiwgZW50cnlwb2ludElkOiBcInBhZ2VzL2luZGV4XCIsIHR5cGU6IFwicGFnZVwiIH0sXG4gICAgICBdLFxuICAgICk7XG4gICAgZXhwZWN0KGFzc2lnbmVkLmJsb2cpLnRvRXF1YWwoW1xuICAgICAgXCIvX25leHQvZGF0YS9hYmMxMjMvYmxvZy9bc2x1Z10uanNvblwiLFxuICAgICAgXCIvYmxvZy9bc2x1Z11cIixcbiAgICBdKTtcbiAgICBleHBlY3QoYXNzaWduZWRbREVGQVVMVF9GVU5DVElPTl9HUk9VUF0pLnRvRXF1YWwoW1wiL1wiXSk7XG4gIH0pO1xuXG4gIGl0KFwicmV0dXJucyBldmVyeSBncm91cCBldmVuIHdoZW4gYSBncm91cCBlbmRzIHVwIHdpdGggb25seSB0aGUgZGVmYXVsdCdzIGxlZnRvdmVyc1wiLCAoKSA9PiB7XG4gICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICBbeyBuYW1lOiBcImFwaVwiLCByb3V0ZXM6IFtcIi9hcGkvKipcIl0gfV0sXG4gICAgICByb3V0ZXMoXCIvYXBpL2hlYWx0aFwiKSxcbiAgICApO1xuICAgIGV4cGVjdChPYmplY3Qua2V5cyhhc3NpZ25lZCkuc29ydCgpKS50b0VxdWFsKFtcImFwaVwiLCBcImRlZmF1bHRcIl0pO1xuICAgIGV4cGVjdChhc3NpZ25lZFtERUZBVUxUX0ZVTkNUSU9OX0dST1VQXSkudG9FcXVhbChbXSk7XG4gIH0pO1xuXG4gIGl0KFwic29ydHMgZWFjaCBncm91cCdzIHRlbXBsYXRlcyBzbyB0aGUgbWFuaWZlc3QgaXMgYnl0ZS1zdGFibGVcIiwgKCkgPT4ge1xuICAgIGNvbnN0IGFzc2lnbmVkID0gYXNzaWduKFxuICAgICAgW3sgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXCIvYXBpLyoqXCJdIH1dLFxuICAgICAgcm91dGVzKFwiL2FwaS96XCIsIFwiL2FwaS9hXCIsIFwiL3pcIiwgXCIvYVwiKSxcbiAgICApO1xuICAgIGV4cGVjdChhc3NpZ25lZC5hcGkpLnRvRXF1YWwoW1wiL2FwaS9hXCIsIFwiL2FwaS96XCJdKTtcbiAgICBleHBlY3QoYXNzaWduZWRbREVGQVVMVF9GVU5DVElPTl9HUk9VUF0pLnRvRXF1YWwoW1wiL2FcIiwgXCIvelwiXSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwidGhlIGJlaGF2aW9ycyB0aGUgYXNzaWdubWVudCByZXR1cm5zXCIsICgpID0+IHtcbiAgaXQoXCJvcmRlcnMgb3ZlcmxhcHBpbmcgZ3JvdXAgcGF0dGVybnMgbW9zdCBzcGVjaWZpYyBmaXJzdFwiLCAoKSA9PiB7XG4gICAgLy8gQ2xvdWRGcm9udCBzdG9wcyBhdCB0aGUgZmlyc3QgbWF0Y2hpbmcgYmVoYXZpb3IsIHNvIGBhcGkvKmAgYWhlYWQgb2ZcbiAgICAvLyBgYXBpL3JlcG9ydHMvKmAgd291bGQgc2VuZCBldmVyeSByZXBvcnQgcmVxdWVzdCB0byB0aGUgd3JvbmcgZnVuY3Rpb24uXG4gICAgZXhwZWN0KFxuICAgICAgcGF0dGVybnNPZihcbiAgICAgICAgW1xuICAgICAgICAgIHsgbmFtZTogXCJhcGlcIiwgcm91dGVzOiBbXCIvYXBpLyoqXCJdIH0sXG4gICAgICAgICAgeyBuYW1lOiBcInJlcG9ydHNcIiwgcm91dGVzOiBbXCIvYXBpL3JlcG9ydHMvKipcIl0gfSxcbiAgICAgICAgXSxcbiAgICAgICAgcm91dGVzKFwiL2FwaS9beF1cIiwgXCIvYXBpL3JlcG9ydHMvW2lkXVwiKSxcbiAgICAgICksXG4gICAgKS50b0VxdWFsKFtcImFwaS9yZXBvcnRzLypcIiwgXCJhcGkvKlwiXSk7XG4gIH0pO1xuXG4gIGl0KFwicmFua3MgYnkgc2VnbWVudCBjb3VudCBiZWZvcmUgc3RyaW5nIGxlbmd0aFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgcGF0dGVybnNPZihcbiAgICAgICAgW1xuICAgICAgICAgIHsgbmFtZTogXCJhXCIsIHJvdXRlczogW1wiL2EvYi8qKlwiXSB9LFxuICAgICAgICAgIHsgbmFtZTogXCJiXCIsIHJvdXRlczogW1wiL2F2ZXJ5dmVyeWxvbmdzZWdtZW50LyoqXCJdIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHJvdXRlcyhcIi9hL2IvW3hdXCIsIFwiL2F2ZXJ5dmVyeWxvbmdzZWdtZW50L1t4XVwiKSxcbiAgICAgICksXG4gICAgKS50b0VxdWFsKFtcImEvYi8qXCIsIFwiYXZlcnl2ZXJ5bG9uZ3NlZ21lbnQvKlwiXSk7XG4gIH0pO1xuXG4gIGl0KFwicHV0cyBhbiBleGFjdCBwYXR0ZXJuIGFoZWFkIG9mIGEgd2lsZGNhcmQgb2YgdGhlIHNhbWUgZGVwdGhcIiwgKCkgPT4ge1xuICAgIC8vIGBhLypgIGFuZCBgYS9iYCBhcmUgdGhlIHNhbWUgbGVuZ3RoIGFuZCBzZWdtZW50IGNvdW50OyBgYS8qYCBmaXJzdFxuICAgIC8vIHN3YWxsb3dzIGBhL2JgLCBzZW5kaW5nIGdyb3VwIGIncyBvbmx5IHJvdXRlIHRvIGdyb3VwIGEncyBmdW5jdGlvbi5cbiAgICBleHBlY3QoXG4gICAgICBwYXR0ZXJuc09mKFxuICAgICAgICBbXG4gICAgICAgICAgeyBuYW1lOiBcImFcIiwgcm91dGVzOiBbXCIvYS8qKlwiXSB9LFxuICAgICAgICAgIHsgbmFtZTogXCJiXCIsIHJvdXRlczogW1wiL2EvYlwiXSB9LFxuICAgICAgICBdLFxuICAgICAgICByb3V0ZXMoXCIvYS9iXCIsIFwiL2EvW3hdXCIpLFxuICAgICAgKSxcbiAgICApLnRvRXF1YWwoW1wiYS9iXCIsIFwiYS8qXCJdKTtcbiAgfSk7XG5cbiAgaXQoXCJhZGRzIGRhdGEtVVJMIGJlaGF2aW9ycyBvbmx5IGZvciB0aGUgZ3JvdXBzIHRoYXQgb3duIGEgUGFnZXMgUm91dGVyIHBhZ2VcIiwgKCkgPT4ge1xuICAgIC8vIE9uZSBsZWdhY3kgcGFnZSBtdXN0IG5vdCBkb3VibGUgZXZlcnkgZ3JvdXAncyBiZWhhdmlvcnMuXG4gICAgZXhwZWN0KFxuICAgICAgcGF0dGVybnNPZihcbiAgICAgICAgW1xuICAgICAgICAgIHsgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfSxcbiAgICAgICAgICB7IG5hbWU6IFwiZG9jc1wiLCByb3V0ZXM6IFtcIi9kb2NzLyoqXCJdIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0ZW1wbGF0ZTogXCIvYmxvZy9bc2x1Z11cIixcbiAgICAgICAgICAgIGVudHJ5cG9pbnRJZDogXCJwYWdlcy9ibG9nL1tzbHVnXS5qc1wiLFxuICAgICAgICAgICAgdHlwZTogXCJwYWdlXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IHRlbXBsYXRlOiBcIi9kb2NzL1twYWdlXVwiLCBlbnRyeXBvaW50SWQ6IFwiYXBwL2RvY3MvW3BhZ2VdL3BhZ2UuanNcIiB9LFxuICAgICAgICBdLFxuICAgICAgKSxcbiAgICApLnRvRXF1YWwoW1wiX25leHQvZGF0YS9hYmMxMjMvYmxvZy8qXCIsIFwiYmxvZy8qXCIsIFwiZG9jcy8qXCJdKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJ3aGF0IHRoZSBlZGdlIHJvdXRlcywgY2hlY2tlZCBhZ2FpbnN0IHdoYXQgd2FzIHBhY2thZ2VkXCIsICgpID0+IHtcbiAgZGVzY3JpYmUoXCJQYWdlcyBSb3V0ZXIgZGF0YSBVUkxzIChBKVwiLCAoKSA9PiB7XG4gICAgaXQoXCJrZWVwcyBhIG5lc3RlZCBwYWdlJ3MgZGF0YSBVUkwgaW4gaXRzIG93biBncm91cFwiLCAoKSA9PiB7XG4gICAgICAvLyBXaXRoIGBfbmV4dC9kYXRhLyovYmxvZy8qYCwgQ2xvdWRGcm9udCBzZW50IHRoZSBkb2NzIGdyb3VwJ3NcbiAgICAgIC8vIGAvX25leHQvZGF0YS88aWQ+L2RvY3MvYmxvZy9pbnRyby5qc29uYCB0byB0aGUgYmxvZyBmdW5jdGlvbi5cbiAgICAgIGNvbnN0IHBhZ2UgPSAodGVtcGxhdGU6IHN0cmluZywgZmlsZTogc3RyaW5nKTogUm91dGVFbnRyeVtdID0+IFtcbiAgICAgICAgeyB0ZW1wbGF0ZSwgZW50cnlwb2ludElkOiBmaWxlLCB0eXBlOiBcInBhZ2VcIiB9LFxuICAgICAgICB7XG4gICAgICAgICAgdGVtcGxhdGU6IGAvX25leHQvZGF0YS8ke0JVSUxEX0lEfSR7dGVtcGxhdGV9Lmpzb25gLFxuICAgICAgICAgIGVudHJ5cG9pbnRJZDogZmlsZSxcbiAgICAgICAgICB0eXBlOiBcInBhZ2VcIixcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCBhc3NpZ25lZCA9IGFzc2lnbihcbiAgICAgICAgW1xuICAgICAgICAgIHsgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfSxcbiAgICAgICAgICB7IG5hbWU6IFwiZG9jc1wiLCByb3V0ZXM6IFtcIi9kb2NzLyoqXCJdIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFtcbiAgICAgICAgICAuLi5wYWdlKFwiL2Jsb2cvW3NsdWddXCIsIFwicGFnZXMvYmxvZy9bc2x1Z10uanNcIiksXG4gICAgICAgICAgLi4ucGFnZShcIi9kb2NzL2Jsb2cvW3NsdWddXCIsIFwicGFnZXMvZG9jcy9ibG9nL1tzbHVnXS5qc1wiKSxcbiAgICAgICAgXSxcbiAgICAgICk7XG4gICAgICBleHBlY3QoYXNzaWduZWQuZG9jcykudG9FcXVhbChbXG4gICAgICAgIFwiL19uZXh0L2RhdGEvYWJjMTIzL2RvY3MvYmxvZy9bc2x1Z10uanNvblwiLFxuICAgICAgICBcIi9kb2NzL2Jsb2cvW3NsdWddXCIsXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwicm91dGVzIHRoZSBwYWdlcy1pMThuIGZpeHR1cmUncyBwYWdlIGFuZCBkYXRhIFVSTHMgdG9nZXRoZXJcIiwgKCkgPT4ge1xuICAgICAgLy8gU3BsaXR0aW5nIHJlZnVzZXMgaTE4biwgc28gZHJvcCB0aGUgbG9jYWxlLXByZWZpeGVkIGNvcGllcyBhbmQga2VlcCB0aGVcbiAgICAgIC8vIHNoYXBlIHRoZSBmaXh0dXJlIGhhcyB3aXRob3V0IHRoZW06IGEgZHluYW1pYyBTU0cgcGFnZSwgYW4gU1NSIHBhZ2Ugd2l0aFxuICAgICAgLy8gaXRzIGRhdGEgb3V0cHV0LCB0d28gQVBJIHJvdXRlcy5cbiAgICAgIGNvbnN0IHsgZW50cmllcywgb3B0aW9ucyB9ID0gZml4dHVyZVJvdXRlcyhwYWdlc0kxOG4pO1xuICAgICAgY29uc3QgbG9jYWxlID0gL15cXC8oPzpfbmV4dFxcL2RhdGFcXC9bXi9dK1xcLyk/KD86ZW4tVVN8ZnJ8bmwtTkwpKD86XFwvfCQpLztcbiAgICAgIGNvbnN0IHVubG9jYWxpemVkID0gZW50cmllcy5maWx0ZXIoXG4gICAgICAgIChlbnRyeSkgPT4gIWxvY2FsZS50ZXN0KGVudHJ5LnRlbXBsYXRlKSxcbiAgICAgICk7XG4gICAgICBjb25zdCB7IHRlbXBsYXRlcywgYmVoYXZpb3JzIH0gPSBhc3NpZ25Sb3V0ZXNUb0dyb3VwcyhcbiAgICAgICAgW1xuICAgICAgICAgIHsgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfSxcbiAgICAgICAgICB7IG5hbWU6IFwic3NyXCIsIHJvdXRlczogW1wiL3NzclwiXSB9LFxuICAgICAgICBdLFxuICAgICAgICB1bmxvY2FsaXplZCxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgICk7XG4gICAgICBleHBlY3QodGVtcGxhdGVzLmJsb2cpLnRvRXF1YWwoW1wiL2Jsb2cvW3NsdWddXCJdKTtcbiAgICAgIGV4cGVjdCh0ZW1wbGF0ZXMuc3NyKS50b0VxdWFsKFtcbiAgICAgICAgYC9fbmV4dC9kYXRhLyR7b3B0aW9ucy5idWlsZElkfS9zc3IuanNvbmAsXG4gICAgICAgIFwiL3NzclwiLFxuICAgICAgXSk7XG4gICAgICBleHBlY3QoXG4gICAgICAgIGJlaGF2aW9ycy5maWx0ZXIoKHsgcGF0dGVybiB9KSA9PiBwYXR0ZXJuLnN0YXJ0c1dpdGgoXCJfbmV4dC9kYXRhL1wiKSksXG4gICAgICApLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgZ3JvdXA6IFwic3NyXCIsXG4gICAgICAgICAgcm91dGU6IFwiL3NzclwiLFxuICAgICAgICAgIHBhdHRlcm46IGBfbmV4dC9kYXRhLyR7b3B0aW9ucy5idWlsZElkfS9zc3IuanNvbmAsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBncm91cDogXCJibG9nXCIsXG4gICAgICAgICAgcm91dGU6IFwiL2Jsb2cvKipcIixcbiAgICAgICAgICBwYXR0ZXJuOiBgX25leHQvZGF0YS8ke29wdGlvbnMuYnVpbGRJZH0vYmxvZy8qYCxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcImFuIG9wdGlvbmFsIGNhdGNoLWFsbCdzIHBhcmVudCAoQilcIiwgKCkgPT4ge1xuICAgIGl0KFwicm91dGVzIHRoZSBwYXJlbnQgVVJMIHdpdGggdGhlIHN1YnRyZWUgdGhhdCBtb3ZlZCB0aGUgZmlsZVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGVudHJpZXMsIG9wdGlvbnMgfSA9IGZpeHR1cmVSb3V0ZXMoYXBwUGxheWdyb3VuZCk7XG4gICAgICBjb25zdCBncm91cHMgPSBbeyBuYW1lOiBcInBhcmFtc1wiLCByb3V0ZXM6IFtcIi9wYXJhbXMvb3B0aW9uYWwvKipcIl0gfV07XG4gICAgICBjb25zdCB7IHRlbXBsYXRlcywgYmVoYXZpb3JzIH0gPSBhc3NpZ25Sb3V0ZXNUb0dyb3VwcyhcbiAgICAgICAgZ3JvdXBzLFxuICAgICAgICBlbnRyaWVzLFxuICAgICAgICBvcHRpb25zLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdCh0ZW1wbGF0ZXMucGFyYW1zKS50b0NvbnRhaW4oXCIvcGFyYW1zL29wdGlvbmFsL1tbLi4ucmVzdF1dXCIpO1xuICAgICAgLy8gYHBhcmFtcy9vcHRpb25hbC8qYCBkb2VzIG5vdCBtYXRjaCBgL3BhcmFtcy9vcHRpb25hbGAsIHdoaWNoIHRoZSBzYW1lXG4gICAgICAvLyBmaWxlIHNlcnZlcywgc28gaXQgZ2V0cyBhbiBleGFjdCBiZWhhdmlvciBvZiBpdHMgb3duLlxuICAgICAgZXhwZWN0KGJlaGF2aW9ycykudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICBncm91cDogXCJwYXJhbXNcIixcbiAgICAgICAgICByb3V0ZTogXCIvcGFyYW1zL29wdGlvbmFsXCIsXG4gICAgICAgICAgcGF0dGVybjogXCJwYXJhbXMvb3B0aW9uYWxcIixcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGdyb3VwOiBcInBhcmFtc1wiLFxuICAgICAgICAgIHJvdXRlOiBcIi9wYXJhbXMvb3B0aW9uYWwvKipcIixcbiAgICAgICAgICBwYXR0ZXJuOiBcInBhcmFtcy9vcHRpb25hbC8qXCIsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwicG9pbnRzIHRoZSBvbGQgZXhhY3QtcGF0dGVybiB3b3JrYXJvdW5kIGF0IHRoZSBzdWJ0cmVlXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHsgZW50cmllcywgb3B0aW9ucyB9ID0gZml4dHVyZVJvdXRlcyhhcHBQbGF5Z3JvdW5kKTtcbiAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICBhc3NpZ25Sb3V0ZXNUb0dyb3VwcyhcbiAgICAgICAgICBbeyBuYW1lOiBcInBhcmFtc1wiLCByb3V0ZXM6IFtcIi9wYXJhbXMvb3B0aW9uYWxcIl0gfV0sXG4gICAgICAgICAgZW50cmllcyxcbiAgICAgICAgICBvcHRpb25zLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KFxuICAgICAgICAvc2VydmVkIGJ5IHRoZSBvcHRpb25hbCBjYXRjaC1hbGwgXCJcXC9wYXJhbXNcXC9vcHRpb25hbFxcL1xcW1xcW1xcLlxcLlxcLnJlc3RcXF1cXF1cIiwgd2hvc2Ugc3VidHJlZSBwYXR0ZXJuIFwiXFwvcGFyYW1zXFwvb3B0aW9uYWxcXC9cXCpcXCpcIiByb3V0ZXMgXCJcXC9wYXJhbXNcXC9vcHRpb25hbFwiIGFzIHdlbGwvLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KFwid29ya3MgdW5kZXIgYSBiYXNlUGF0aCB0b29cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICAgIFt7IG5hbWU6IFwic2hvcFwiLCByb3V0ZXM6IFtcIi9zaG9wLyoqXCJdIH1dLFxuICAgICAgICByb3V0ZXMoXCIvYmFzZS9zaG9wL1tbLi4uc2x1Z11dXCIsIFwiL2Jhc2VcIiksXG4gICAgICAgIFwiL2Jhc2VcIixcbiAgICAgICk7XG4gICAgICBleHBlY3QoYXNzaWduZWQuc2hvcCkudG9FcXVhbChbXCIvYmFzZS9zaG9wL1tbLi4uc2x1Z11dXCJdKTtcbiAgICAgIGV4cGVjdChyb3V0ZWRQYXR0ZXJucyhbXCIvc2hvcC8qKlwiXSwgYXNzaWduZWQuc2hvcCwgXCJiYXNlXCIpKS50b0VxdWFsKFtcbiAgICAgICAgXCIvc2hvcC8qKlwiLFxuICAgICAgICBcIi9zaG9wXCIsXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwicm91dGVzIGEgUGFnZXMgUm91dGVyIG9wdGlvbmFsIGNhdGNoLWFsbCdzIHBhcmVudCBkYXRhIFVSTFwiLCAoKSA9PiB7XG4gICAgICAvLyBgL19uZXh0L2RhdGEvPGlkPi9zaG9wLmpzb25gIGJlbG9uZ3MgdG8gdGhlIHNhbWUgZmlsZSwgYW5kIHRoZSBleGFjdFxuICAgICAgLy8gYC9zaG9wYCBwYXR0ZXJuIGByb3V0ZWRQYXR0ZXJuc2AgYWRkcyBjYXJyaWVzIGl0LlxuICAgICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICAgIFt7IG5hbWU6IFwic2hvcFwiLCByb3V0ZXM6IFtcIi9zaG9wLyoqXCJdIH1dLFxuICAgICAgICBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGVtcGxhdGU6IFwiL3Nob3AvW1suLi5zbHVnXV1cIixcbiAgICAgICAgICAgIGVudHJ5cG9pbnRJZDogXCJwYWdlcy9zaG9wL1tbLi4uc2x1Z11dLmpzXCIsXG4gICAgICAgICAgICB0eXBlOiBcInBhZ2VcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChhc3NpZ25lZC5zaG9wKS50b0VxdWFsKFtcIi9zaG9wL1tbLi4uc2x1Z11dXCJdKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJvbmUgZmlsZSBiZWhpbmQgc2V2ZXJhbCB0ZW1wbGF0ZXMgKEMpXCIsICgpID0+IHtcbiAgICAvLyBgYXBwL1tsb2NhbGVdL3BhZ2UudHN4YCB3aXRoIHJvb3QgcGFyYW1zOiBgL2VuYCBhbmQgYC9kZWAgYXJlIHN5bnRoZXNpemVkXG4gICAgLy8gZnJvbSBvbmUgb3V0cHV0LCBhbG9uZ3NpZGUgaXRzIG93biBgL1tsb2NhbGVdYCB0ZW1wbGF0ZS5cbiAgICBjb25zdCByb290UGFyYW1zOiBSb3V0ZUVudHJ5W10gPSBbXG4gICAgICBcIi9bbG9jYWxlXVwiLFxuICAgICAgXCIvW2xvY2FsZV0ucnNjXCIsXG4gICAgICBcIi9lblwiLFxuICAgICAgXCIvZW4ucnNjXCIsXG4gICAgICBcIi9kZVwiLFxuICAgICAgXCIvZGUucnNjXCIsXG4gICAgXS5tYXAoKHRlbXBsYXRlKSA9PiAoe1xuICAgICAgdGVtcGxhdGUsXG4gICAgICBlbnRyeXBvaW50SWQ6IFwiYXBwL1tsb2NhbGVdL3BhZ2UuanNcIixcbiAgICAgIHR5cGU6IFwiYXBwLXBhZ2VcIixcbiAgICB9KSk7XG5cbiAgICBpdChcInJlamVjdHMgYSBwYXR0ZXJuIHRoYXQgbW92ZXMgdGhlIGZpbGUgZm9yIG9uZSBvZiBpdHMgVVJMc1wiLCAoKSA9PiB7XG4gICAgICAvLyBPbmx5IGBlbmAgZ290IGEgYmVoYXZpb3IsIHNvIGAvZGVgIHJlYWNoZWQgdGhlIGRlZmF1bHQgZnVuY3Rpb24sIHdoaWNoXG4gICAgICAvLyBubyBsb25nZXIgaGFkIHRoZSBmaWxlLlxuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihbeyBuYW1lOiBcImludGxcIiwgcm91dGVzOiBbXCIvZW5cIl0gfV0sIHJvb3RQYXJhbXMpLFxuICAgICAgKS50b1Rocm93KFxuICAgICAgICAvXCJhcHBcXC9cXFtsb2NhbGVcXF1cXC9wYWdlXFwuanNcIiBpcyBwYWNrYWdlZCBpbnRvIGdyb3VwIFwiaW50bFwiLCBidXQgQ2xvdWRGcm9udCB3b3VsZCBzZW5kIFwiXFwvXFxbbG9jYWxlXFxdXCIgdG8gdGhlIFwiZGVmYXVsdFwiIGdyb3VwLCBcIlxcL2RlXCIgdG8gdGhlIFwiZGVmYXVsdFwiIGdyb3VwLyxcbiAgICAgICk7XG4gICAgICAvLyBBbmQgc2F5cyB0aGUgZmlsZSBjYW5ub3QgYmUgZ3JvdXBlZCBhdCBhbGw6IGAvW2xvY2FsZV1gIHdvdWxkIG5lZWQgYC8qKmAuXG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgYXNzaWduKFt7IG5hbWU6IFwiaW50bFwiLCByb3V0ZXM6IFtcIi9lblwiLCBcIi9kZVwiXSB9XSwgcm9vdFBhcmFtcyksXG4gICAgICApLnRvVGhyb3coL1wiXFwvXFxbbG9jYWxlXFxdXCIgY2Fubm90IGJlIHJvdXRlZCB0byBhbnkgZ3JvdXAvKTtcbiAgICB9KTtcblxuICAgIGl0KFwic3VnZ2VzdHMgdGhlIHBhdHRlcm4gdGhhdCBjb3ZlcnMgYSBzdGF0aWMgdGVtcGxhdGUgaXQgbGVmdCBiZWhpbmRcIiwgKCkgPT4ge1xuICAgICAgY29uc3Qgc2hhcmVkOiBSb3V0ZUVudHJ5W10gPSBbXG4gICAgICAgIHsgdGVtcGxhdGU6IFwiL2Fib3V0XCIsIGVudHJ5cG9pbnRJZDogXCJzaGFyZWQuanNcIiB9LFxuICAgICAgICB7IHRlbXBsYXRlOiBcIi90ZWFtXCIsIGVudHJ5cG9pbnRJZDogXCJzaGFyZWQuanNcIiB9LFxuICAgICAgXTtcbiAgICAgIGV4cGVjdCgoKSA9PiBhc3NpZ24oW3sgbmFtZTogXCJtXCIsIHJvdXRlczogW1wiL2Fib3V0XCJdIH1dLCBzaGFyZWQpKS50b1Rocm93KFxuICAgICAgICAvQWRkIFwiXFwvdGVhbVwiIHRvIGdyb3VwIFwibVwiJ3Mgcm91dGVzLyxcbiAgICAgICk7XG4gICAgICBleHBlY3QoXG4gICAgICAgIGFzc2lnbihbeyBuYW1lOiBcIm1cIiwgcm91dGVzOiBbXCIvYWJvdXRcIiwgXCIvdGVhbVwiXSB9XSwgc2hhcmVkKS5tLFxuICAgICAgKS50b0VxdWFsKFtcIi9hYm91dFwiLCBcIi90ZWFtXCJdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY2hlY2tzIHRoZSB0cmFpbGluZ1NsYXNoIGZvcm0sIHdoaWNoIGV4YWN0IHBhdHRlcm5zIHJvdXRlXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGFzc2lnbmVkID0gYXNzaWduKFxuICAgICAgICBbeyBuYW1lOiBcInBcIiwgcm91dGVzOiBbXCIvcHJpY2luZ1wiXSB9XSxcbiAgICAgICAgcm91dGVzKFwiL3ByaWNpbmdcIiksXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHsgdHJhaWxpbmdTbGFzaDogdHJ1ZSB9LFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChhc3NpZ25lZC5wKS50b0VxdWFsKFtcIi9wcmljaW5nXCJdKTtcbiAgICB9KTtcblxuICAgIGl0KFwicHV0cyBhbiBleGFjdCB0cmFpbGluZ1NsYXNoIGZvcm0gYWhlYWQgb2YgYSBzdWJ0cmVlIGl0IHNpdHMgYXQgdGhlIGJhc2Ugb2ZcIiwgKCkgPT4ge1xuICAgICAgLy8gYGEvYi9gIGFuZCBgYS9iLypgIGhhdmUgdGhlIHNhbWUgbGl0ZXJhbCBkZXB0aDsgd2VyZSB0aGUgc3VidHJlZSBmaXJzdFxuICAgICAgLy8gaXQgd291bGQgdGFrZSBgL2EvYi9gIGZyb20gZ3JvdXAgeC5cbiAgICAgIGNvbnN0IGFzc2lnbmVkID0gYXNzaWduKFxuICAgICAgICBbXG4gICAgICAgICAgeyBuYW1lOiBcInhcIiwgcm91dGVzOiBbXCIvYS9iXCJdIH0sXG4gICAgICAgICAgeyBuYW1lOiBcInlcIiwgcm91dGVzOiBbXCIvYS9iLyoqXCJdIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHJvdXRlcyhcIi9cIiwgXCIvYS9iXCIsIFwiL2EvYi9baWRdXCIpLFxuICAgICAgICBcIlwiLFxuICAgICAgICB7IHRyYWlsaW5nU2xhc2g6IHRydWUgfSxcbiAgICAgICk7XG4gICAgICBleHBlY3QoYXNzaWduZWQueCkudG9FcXVhbChbXCIvYS9iXCJdKTtcbiAgICAgIGV4cGVjdChhc3NpZ25lZC55KS50b0VxdWFsKFtcIi9hL2IvW2lkXVwiXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImdpdmVzIGEgZ3JvdXAgd2l0aG91dCBQYWdlcyBSb3V0ZXIgcm91dGVzIG5vIGRhdGEgVVJMIGJlaGF2aW9yc1wiLCAoKSA9PiB7XG4gICAgICAvLyBBbiBBcHAgUm91dGVyIGAvaW5kZXhgIG5leHQgdG8gYSBQYWdlcyBSb3V0ZXIgaG9tZSBwYWdlOiBhIGRhdGEgYmVoYXZpb3JcbiAgICAgIC8vIGZvciB0aGUgZ3JvdXAsIGBfbmV4dC9kYXRhLzxpZD4vaW5kZXguanNvbmAsIHdvdWxkIGJlIHRoZSBob21lIHBhZ2Unc1xuICAgICAgLy8gZGF0YSBVUkwuIFRoZSBncm91cCBvd25zIG5vIHBhZ2UsIHNvIGl0IGdldHMgbm9uZS5cbiAgICAgIGV4cGVjdChcbiAgICAgICAgYXNzaWduKFxuICAgICAgICAgIFt7IG5hbWU6IFwiaWR4XCIsIHJvdXRlczogW1wiL2luZGV4XCJdIH1dLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIHsgdGVtcGxhdGU6IFwiL1wiLCBlbnRyeXBvaW50SWQ6IFwicGFnZXMvaW5kZXguanNcIiwgdHlwZTogXCJwYWdlXCIgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdGVtcGxhdGU6IFwiL2luZGV4XCIsXG4gICAgICAgICAgICAgIGVudHJ5cG9pbnRJZDogXCJhcHAvaW5kZXgvcGFnZS5qc1wiLFxuICAgICAgICAgICAgICB0eXBlOiBcImFwcC1wYWdlXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICkuaWR4LFxuICAgICAgKS50b0VxdWFsKFtcIi9pbmRleFwiXSk7XG4gICAgfSk7XG5cbiAgICBpdChcInJlamVjdHMgYSBncm91cCBwYXR0ZXJuIGNsYWltaW5nIGEgZGF0YSBVUkwgb2YgYSBmaWxlIGxlZnQgaW4gZGVmYXVsdFwiLCAoKSA9PiB7XG4gICAgICAvLyBUaGUgc2FtZSBjb2xsaXNpb24gaW4gYSBncm91cCB0aGF0IGRvZXMgb3duIGEgcGFnZS5cbiAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICBhc3NpZ24oXG4gICAgICAgICAgW3sgbmFtZTogXCJpZHhcIiwgcm91dGVzOiBbXCIvaW5kZXhcIiwgXCIvbGVnYWN5XCJdIH1dLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIHsgdGVtcGxhdGU6IFwiL1wiLCBlbnRyeXBvaW50SWQ6IFwicGFnZXMvaW5kZXguanNcIiwgdHlwZTogXCJwYWdlXCIgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdGVtcGxhdGU6IFwiL2luZGV4XCIsXG4gICAgICAgICAgICAgIGVudHJ5cG9pbnRJZDogXCJhcHAvaW5kZXgvcGFnZS5qc1wiLFxuICAgICAgICAgICAgICB0eXBlOiBcImFwcC1wYWdlXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB0ZW1wbGF0ZTogXCIvbGVnYWN5XCIsXG4gICAgICAgICAgICAgIGVudHJ5cG9pbnRJZDogXCJwYWdlcy9sZWdhY3kuanNcIixcbiAgICAgICAgICAgICAgdHlwZTogXCJwYWdlXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICksXG4gICAgICApLnRvVGhyb3coXG4gICAgICAgIC9cInBhZ2VzXFwvaW5kZXhcXC5qc1wiIGlzIHBhY2thZ2VkIGludG8gdGhlIFwiZGVmYXVsdFwiIGdyb3VwLCBidXQgQ2xvdWRGcm9udCB3b3VsZCBzZW5kIFwiXFwvX25leHRcXC9kYXRhXFwvYWJjMTIzXFwvaW5kZXhcXC5qc29uXCIgdG8gZ3JvdXAgXCJpZHhcIi8sXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcImludGVyY2VwdGlvbiByb3V0ZXMgKEQpXCIsICgpID0+IHtcbiAgICBjb25zdCBwaG90b0FwcCA9ICgpOiBSb3V0ZUVudHJ5W10gPT4gW1xuICAgICAgeyB0ZW1wbGF0ZTogXCIvZmVlZFwiLCBlbnRyeXBvaW50SWQ6IFwiYXBwL2ZlZWQvcGFnZS5qc1wiLCB0eXBlOiBcImFwcC1wYWdlXCIgfSxcbiAgICAgIHtcbiAgICAgICAgdGVtcGxhdGU6IFwiL2ZlZWQvKC4uKXBob3RvL1tpZF1cIixcbiAgICAgICAgZW50cnlwb2ludElkOiBcImFwcC9mZWVkLyguLilwaG90by9baWRdL3BhZ2UuanNcIixcbiAgICAgICAgdHlwZTogXCJhcHAtcGFnZVwiLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgdGVtcGxhdGU6IFwiL2ZlZWQvKC4uKXBob3RvL1tpZF0ucnNjXCIsXG4gICAgICAgIGVudHJ5cG9pbnRJZDogXCJhcHAvZmVlZC8oLi4pcGhvdG8vW2lkXS9wYWdlLmpzXCIsXG4gICAgICAgIHR5cGU6IFwiYXBwLXBhZ2VcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHRlbXBsYXRlOiBcIi9waG90by9baWRdXCIsXG4gICAgICAgIGVudHJ5cG9pbnRJZDogXCJhcHAvcGhvdG8vW2lkXS9wYWdlLmpzXCIsXG4gICAgICAgIHR5cGU6IFwiYXBwLXBhZ2VcIixcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIGl0KFwicGFja2FnZXMgYW4gaW50ZXJjZXB0aW5nIGZpbGUgd2l0aCB0aGUgVVJMIGl0IGludGVyY2VwdHNcIiwgKCkgPT4ge1xuICAgICAgLy8gVGhlIHNvZnQgbmF2aWdhdGlvbiByZXF1ZXN0cyBgL3Bob3RvLzFgLCB3aGljaCBDbG91ZEZyb250IHNlbmRzIHRvIHRoZVxuICAgICAgLy8gZGVmYXVsdCBmdW5jdGlvbjsgTmV4dC5qcyByZXdyaXRlcyBpdCB0aGVyZSB0byB0aGUgaW50ZXJjZXB0aW5nIGZpbGUuXG4gICAgICBjb25zdCBhc3NpZ25lZCA9IGFzc2lnbihcbiAgICAgICAgW3sgbmFtZTogXCJmZWVkXCIsIHJvdXRlczogW1wiL2ZlZWQvKipcIl0gfV0sXG4gICAgICAgIFtcbiAgICAgICAgICAuLi5waG90b0FwcCgpLFxuICAgICAgICAgIHsgdGVtcGxhdGU6IFwiL2ZlZWQvW3Bvc3RdXCIsIGVudHJ5cG9pbnRJZDogXCJhcHAvZmVlZC9bcG9zdF0vcGFnZS5qc1wiIH0sXG4gICAgICAgIF0sXG4gICAgICApO1xuICAgICAgZXhwZWN0KGFzc2lnbmVkLmZlZWQpLnRvRXF1YWwoW1wiL2ZlZWQvW3Bvc3RdXCJdKTtcbiAgICAgIGV4cGVjdChhc3NpZ25lZFtERUZBVUxUX0ZVTkNUSU9OX0dST1VQXSkudG9Db250YWluKFxuICAgICAgICBcIi9mZWVkLyguLilwaG90by9baWRdXCIsXG4gICAgICApO1xuICAgICAgZXhwZWN0KGFzc2lnbmVkW0RFRkFVTFRfRlVOQ1RJT05fR1JPVVBdKS50b0NvbnRhaW4oXG4gICAgICAgIFwiL2ZlZWQvKC4uKXBob3RvL1tpZF0ucnNjXCIsXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoXCJmb2xsb3dzIHRoZSBpbnRlcmNlcHRlZCByb3V0ZSBpbnRvIGl0cyBncm91cFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBhc3NpZ25lZCA9IGFzc2lnbihcbiAgICAgICAgW3sgbmFtZTogXCJwaG90b3NcIiwgcm91dGVzOiBbXCIvcGhvdG8vKipcIl0gfV0sXG4gICAgICAgIHBob3RvQXBwKCksXG4gICAgICApO1xuICAgICAgZXhwZWN0KGFzc2lnbmVkLnBob3RvcykudG9FcXVhbChbXG4gICAgICAgIFwiL2ZlZWQvKC4uKXBob3RvL1tpZF1cIixcbiAgICAgICAgXCIvZmVlZC8oLi4pcGhvdG8vW2lkXS5yc2NcIixcbiAgICAgICAgXCIvcGhvdG8vW2lkXVwiLFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcInRocm93cyB3aGVuIHRoZSBpbnRlcmNlcHRlZCBVUkwgc3BhY2UgaXMgc3BsaXQgYmV0d2VlbiBncm91cHNcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihcbiAgICAgICAgICBbeyBuYW1lOiBcIm9uZVwiLCByb3V0ZXM6IFtcIi9waG90by8xXCJdIH1dLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIC4uLnBob3RvQXBwKCksXG4gICAgICAgICAgICB7IHRlbXBsYXRlOiBcIi9waG90by8xXCIsIGVudHJ5cG9pbnRJZDogXCJhcHAvcGhvdG8vMS9wYWdlLmpzXCIgfSxcbiAgICAgICAgICBdLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KFxuICAgICAgICAvaW50ZXJjZXB0aW9uIHJvdXRlIFwiXFwvZmVlZFxcL1xcKFxcLlxcLlxcKXBob3RvXFwvXFxbaWRcXF1cIi4qZ3JvdXAgXCJvbmVcIidzIHBhdHRlcm4gXCJcXC9waG90b1xcLzFcIiBjbGFpbXMgcGFydCBvZiBpdC9zLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW1wiL2ZlZWQvKC4uKXBob3RvL1tpZF1cIiwgXCIvcGhvdG8vW2lkXVwiXSxcbiAgICAgIFtcIi9mZWVkLyguKXBob3RvL1tpZF1cIiwgXCIvZmVlZC9waG90by9baWRdXCJdLFxuICAgICAgW1wiLyguKXBob3RvL1tpZF1cIiwgXCIvcGhvdG8vW2lkXVwiXSxcbiAgICAgIFtcIi9hL2IvKC4uKSguLilwaG90b1wiLCBcIi9waG90b1wiXSxcbiAgICAgIFtcIi9hL2IvKC4uLilwaG90b1wiLCBcIi9waG90b1wiXSxcbiAgICAgIFtcIi9waG90by9baWRdXCIsIHVuZGVmaW5lZF0sXG4gICAgXSkoXCJyZXNvbHZlcyAlcCB0byB0aGUgcm91dGUgaXQgaW50ZXJjZXB0cywgJXBcIiwgKHBhdGgsIGV4cGVjdGVkKSA9PiB7XG4gICAgICBleHBlY3QoaW50ZXJjZXB0ZWRSb3V0ZShwYXRoKSkudG9CZShleHBlY3RlZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwibmV4dC5jb25maWcgcmV3cml0ZXMgKEQpXCIsICgpID0+IHtcbiAgICBpdChcInJlamVjdHMgYSByZXdyaXRlIHdob3NlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24gbGFuZCBpbiBkaWZmZXJlbnQgZ3JvdXBzXCIsICgpID0+IHtcbiAgICAgIC8vIGFwcC1wbGF5Z3JvdW5kIHJld3JpdGVzIGAvZTJlL3Jld3JpdGUvOnBhdGgoLiopYCB0byBgL2UyZS9yZXdyaXRlL2VjaG9gLlxuICAgICAgLy8gR3JvdXBpbmcgb25seSB0aGUgZGVzdGluYXRpb24gbGVhdmVzIHRoZSBzb3VyY2Ugb24gdGhlIGRlZmF1bHRcbiAgICAgIC8vIGZ1bmN0aW9uLCB3aGljaCB0aGVuIHJld3JpdGVzIHRvIGEgZmlsZSBpdCBkb2VzIG5vdCBoYXZlLlxuICAgICAgY29uc3QgeyBlbnRyaWVzLCBvcHRpb25zIH0gPSBmaXh0dXJlUm91dGVzKGFwcFBsYXlncm91bmQpO1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnblJvdXRlc1RvR3JvdXBzKFxuICAgICAgICAgIFt7IG5hbWU6IFwiZWNob1wiLCByb3V0ZXM6IFtcIi9lMmUvcmV3cml0ZS9lY2hvXCJdIH1dLFxuICAgICAgICAgIGVudHJpZXMsXG4gICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgKSxcbiAgICAgICkudG9UaHJvdyhcbiAgICAgICAgL3Jld3JpdGUgZnJvbSBcIlxcL2UyZVxcL3Jld3JpdGVcXC86cGF0aFxcKFxcLlxcKlxcKVwiIHRvIFwiXFwvZTJlXFwvcmV3cml0ZVxcL2VjaG9cXD8uKlwiIGNyb3NzZXMgZ3JvdXBzOiBDbG91ZEZyb250IHNlbmRzIFwiXFwvZTJlXFwvcmV3cml0ZVxcL1xcW3BhdGhcXF1cIiB0byB0aGUgXCJkZWZhdWx0XCIgZ3JvdXAsIGFuZCBOZXh0XFwuanMgdGhlbiBzZXJ2ZXMgaXQgd2l0aCBcIi4qZWNob1xcL3BhZ2VcXC5qc1wiLCB3aGljaCBpcyBwYWNrYWdlZCBpbnRvIGdyb3VwIFwiZWNob1wiLyxcbiAgICAgICk7XG4gICAgICAvLyBCb3RoIGVuZHMgaW4gb25lIGdyb3VwIGlzIGZpbmUuXG4gICAgICBleHBlY3QoXG4gICAgICAgIGFzc2lnblJvdXRlc1RvR3JvdXBzKFxuICAgICAgICAgIFt7IG5hbWU6IFwiZTJlXCIsIHJvdXRlczogW1wiL2UyZS9yZXdyaXRlLyoqXCJdIH1dLFxuICAgICAgICAgIGVudHJpZXMsXG4gICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgKS50ZW1wbGF0ZXMuZTJlLFxuICAgICAgKS50b0NvbnRhaW4oXCIvZTJlL3Jld3JpdGUvZWNob1wiKTtcbiAgICB9KTtcblxuICAgIGl0KFwicmVzb2x2ZXMgYSBkZXN0aW5hdGlvbiB0aHJvdWdoIE5leHQuanMncyBkeW5hbWljIHJvdXRlIHJ1bGVzXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHJvdXRpbmcgPSB7XG4gICAgICAgIGJlZm9yZUZpbGVzOiBbeyBzb3VyY2U6IFwiL29sZFwiLCBkZXN0aW5hdGlvbjogXCIvYmxvZy9oZWxsb1wiIH1dLFxuICAgICAgICBkeW5hbWljUm91dGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgc291cmNlUmVnZXg6IFwiXi9ibG9nLyhbXi9dKz8pKD86Lyk/JFwiLFxuICAgICAgICAgICAgZGVzdGluYXRpb246IFwiL2Jsb2cvW3NsdWddXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgYXNzaWduKFxuICAgICAgICAgIFt7IG5hbWU6IFwiYmxvZ1wiLCByb3V0ZXM6IFtcIi9ibG9nLyoqXCJdIH1dLFxuICAgICAgICAgIHJvdXRlcyhcIi9ibG9nL1tzbHVnXVwiKSxcbiAgICAgICAgICBcIlwiLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJvdXRpbmcsXG4gICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICAgICkudG9UaHJvdygvQ2xvdWRGcm9udCBzZW5kcyBcIlxcL29sZFwiIHRvIHRoZSBcImRlZmF1bHRcIiBncm91cC8pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJza2lwcyBhbiBhZnRlckZpbGVzIHNvdXJjZSBhIHJvdXRlIGFscmVhZHkgc2VydmVzLCBhbmQgcGFyYW1ldGVyaXplZCBkZXN0aW5hdGlvbnNcIiwgKCkgPT4ge1xuICAgICAgY29uc3Qgcm91dGluZyA9IHtcbiAgICAgICAgLy8gTmV2ZXIgYXBwbGllZDogYC9wcmljaW5nYCBpcyBhIHJvdXRlLCBhbmQgYWZ0ZXJGaWxlcyB5aWVsZHMgdG8gaXQuXG4gICAgICAgIGFmdGVyRmlsZXM6IFt7IHNvdXJjZTogXCIvcHJpY2luZ1wiLCBkZXN0aW5hdGlvbjogXCIvYmxvZy94XCIgfV0sXG4gICAgICAgIC8vIE5vdCByZXNvbHZhYmxlIGF0IHN5bnRoLlxuICAgICAgICBiZWZvcmVGaWxlczogW3sgc291cmNlOiBcIi9iLzpzbHVnXCIsIGRlc3RpbmF0aW9uOiBcIi9ibG9nLzpzbHVnXCIgfV0sXG4gICAgICB9O1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihcbiAgICAgICAgICBbeyBuYW1lOiBcImJsb2dcIiwgcm91dGVzOiBbXCIvYmxvZy8qKlwiXSB9XSxcbiAgICAgICAgICByb3V0ZXMoXCIvYmxvZy94XCIsIFwiL3ByaWNpbmdcIiksXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgICB7IHJvdXRpbmcgfSxcbiAgICAgICAgKSxcbiAgICAgICkubm90LnRvVGhyb3coKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY2hlY2tzIHRoZSBwYXRoIGFuIG9wdGlvbmFsIHBhcmFtZXRlciBsZWF2ZXNcIiwgKCkgPT4ge1xuICAgICAgY29uc3Qgcm91dGluZyA9IHtcbiAgICAgICAgYmVmb3JlRmlsZXM6IFt7IHNvdXJjZTogXCIvZG9jcy86cGF0aCpcIiwgZGVzdGluYXRpb246IFwiL2RvY3MtYXBwXCIgfV0sXG4gICAgICB9O1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihcbiAgICAgICAgICBbeyBuYW1lOiBcImRvY3NcIiwgcm91dGVzOiBbXCIvZG9jcy8qKlwiLCBcIi9kb2NzLWFwcFwiXSB9XSxcbiAgICAgICAgICByb3V0ZXMoXCIvZG9jcy1hcHBcIiwgXCIvZG9jcy9bcGFnZV1cIiksXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgICB7IHJvdXRpbmcgfSxcbiAgICAgICAgKSxcbiAgICAgICkudG9UaHJvdygvQ2xvdWRGcm9udCBzZW5kcyBcIlxcL2RvY3NcIiB0byB0aGUgXCJkZWZhdWx0XCIgZ3JvdXAvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJhIGR5bmFtaWMgcm91dGUncyBVUkwgc3BhY2UgKEUpXCIsICgpID0+IHtcbiAgICBpdChcInJlamVjdHMgYSBzdWJ0cmVlIGNhcHR1cmluZyBVUkxzIGEgZGVmYXVsdC1ncm91cCBjYXRjaC1hbGwgc2VydmVzXCIsICgpID0+IHtcbiAgICAgIC8vIGAvYmxvZy9bc2x1Z11gIG9ubHkgbWF0Y2hlcyBvbmUgc2VnbWVudCwgc28gYC9ibG9nL2EvYmAgcmVhY2hlcyB0aGVcbiAgICAgIC8vIGJsb2cgZnVuY3Rpb24gdmlhIGBibG9nLypgIGFuZCByZXNvbHZlcyB0aGVyZSB0byBgL1suLi5zbHVnXWAsIHdoaWNoXG4gICAgICAvLyB0aGUgYmxvZyB6aXAgbGFja3MuIFRoZSB0ZW1wbGF0ZSB0ZXh0IGl0c2VsZiBuZXZlciBtYXRjaGVkIGBibG9nLypgLlxuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihcbiAgICAgICAgICBbeyBuYW1lOiBcImJsb2dcIiwgcm91dGVzOiBbXCIvYmxvZy8qKlwiXSB9XSxcbiAgICAgICAgICByb3V0ZXMoXCIvXCIsIFwiL1suLi5zbHVnXVwiLCBcIi9ibG9nL1tzbHVnXVwiKSxcbiAgICAgICAgKSxcbiAgICAgICkudG9UaHJvdyhcbiAgICAgICAgL1wiXFwvXFxbXFwuXFwuXFwuc2x1Z1xcXVwiIGlzIHBhY2thZ2VkIGludG8gdGhlIFwiZGVmYXVsdFwiIGdyb3VwLCBidXQgQ2xvdWRGcm9udCB3b3VsZCBzZW5kIFwiXFwvYmxvZ1xcL19cXC9fXCIgdG8gZ3JvdXAgXCJibG9nXCIgXFwoaXRzIHBhdHRlcm4gXCJcXC9ibG9nXFwvXFwqXFwqXCJcXCkuKmR5bmFtaWMgcm91dGUgXCJcXC9cXFtcXC5cXC5cXC5zbHVnXFxdXCIvcyxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdChcImNoZWNrcyB1bmRlciBhIGJhc2VQYXRoIHRvb1wiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgYXNzaWduKFxuICAgICAgICAgIFt7IG5hbWU6IFwiYmxvZ1wiLCByb3V0ZXM6IFtcIi9ibG9nLyoqXCJdIH1dLFxuICAgICAgICAgIHJvdXRlcyhcIi9iYXNlXCIsIFwiL2Jhc2UvWy4uLnNsdWddXCIsIFwiL2Jhc2UvYmxvZy9bc2x1Z11cIiksXG4gICAgICAgICAgXCIvYmFzZVwiLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KC9DbG91ZEZyb250IHdvdWxkIHNlbmQgXCJcXC9iYXNlXFwvYmxvZ1xcL19cXC9fXCIgdG8gZ3JvdXAgXCJibG9nXCIvKTtcbiAgICB9KTtcblxuICAgIGl0KFwiYWNjZXB0cyB0aGUgY2FwdHVyZSB3aGVuIHRoZSBncm91cCdzIG93biByb3V0ZXMgc2hhZG93IGV2ZXJ5IFVSTCBvZiBpdFwiLCAoKSA9PiB7XG4gICAgICAvLyBBIG1vcmUgc3BlY2lmaWMgcm91dGUgaW4gdGhlIGNhcHR1cmluZyBncm91cCB3aW5zIGluc2lkZSBOZXh0LmpzLCBzb1xuICAgICAgLy8gd2l0aCBgL2Jsb2cvWy4uLnJlc3RdYCB0aGVyZSBub3RoaW5nIHVuZGVyIGAvYmxvZy9gIHJlc29sdmVzIHRvIHRoZVxuICAgICAgLy8gcm9vdCBjYXRjaC1hbGwuXG4gICAgICBjb25zdCBhc3NpZ25lZCA9IGFzc2lnbihcbiAgICAgICAgW3sgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfV0sXG4gICAgICAgIHJvdXRlcyhcIi9cIiwgXCIvWy4uLnNsdWddXCIsIFwiL2Jsb2cvW3NsdWddXCIsIFwiL2Jsb2cvWy4uLnJlc3RdXCIpLFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChhc3NpZ25lZFtERUZBVUxUX0ZVTkNUSU9OX0dST1VQXSkudG9FcXVhbChbXCIvXCIsIFwiL1suLi5zbHVnXVwiXSk7XG4gICAgICBleHBlY3QoYXNzaWduZWQuYmxvZykudG9FcXVhbChbXCIvYmxvZy9bLi4ucmVzdF1cIiwgXCIvYmxvZy9bc2x1Z11cIl0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJhY2NlcHRzIGEgc2luZ2xlLXNlZ21lbnQgcm9vdCBwYXJhbSwgd2hpY2ggbmV2ZXIgcmVhY2hlcyB1bmRlciBhIHN1YnRyZWVcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICAgIFt7IG5hbWU6IFwiYmxvZ1wiLCByb3V0ZXM6IFtcIi9ibG9nLyoqXCJdIH1dLFxuICAgICAgICByb3V0ZXMoXCIvXCIsIFwiL1tzbHVnXVwiLCBcIi9ibG9nL1tzbHVnXVwiKSxcbiAgICAgICk7XG4gICAgICBleHBlY3QoYXNzaWduZWRbREVGQVVMVF9GVU5DVElPTl9HUk9VUF0pLnRvRXF1YWwoW1wiL1wiLCBcIi9bc2x1Z11cIl0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJyZWplY3RzIHRoZSB0cmFpbGluZ1NsYXNoIGZvcm0gb2YgYSBzdWJ0cmVlJ3MgYmFzZSB0aGF0IGEgcm9vdCBwYXJhbSBzZXJ2ZXNcIiwgKCkgPT4ge1xuICAgICAgLy8gYC9ibG9nL2AgbWF0Y2hlcyBgYmxvZy8qYCwgYW5kIHdpdGggbm8gYC9ibG9nYCBwYWdlIE5leHQuanMgc2VydmVzIGl0XG4gICAgICAvLyB3aXRoIGAvW3NsdWddYC5cbiAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICBhc3NpZ24oXG4gICAgICAgICAgW3sgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfV0sXG4gICAgICAgICAgcm91dGVzKFwiL1wiLCBcIi9bc2x1Z11cIiwgXCIvYmxvZy9bc2x1Z11cIiksXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgICB7IHRyYWlsaW5nU2xhc2g6IHRydWUgfSxcbiAgICAgICAgKSxcbiAgICAgICkudG9UaHJvdygvQ2xvdWRGcm9udCB3b3VsZCBzZW5kIFwiXFwvYmxvZ1xcL1wiIHRvIGdyb3VwIFwiYmxvZ1wiLyk7XG4gICAgfSk7XG5cbiAgICBpdChcImxldHMgYSBzdGF0aWMgZmlyc3Qgc2VnbWVudCBpbiB0aGUgZ3JvdXAgb3V0cmFuayBhIHBhcmFtIGluIGEgbGF0ZXIgb25lXCIsICgpID0+IHtcbiAgICAgIC8vIGAvYmxvZy9zZXR0aW5nc2AgcmVhY2hlcyB0aGUgYmxvZyBmdW5jdGlvbjsgYC9ibG9nL1tzbHVnXWAgYmVhdHNcbiAgICAgIC8vIGAvW3RlYW1dL3NldHRpbmdzYCB0aGVyZSwgc3RhdGljIGZpcnN0IHNlZ21lbnQgYmVmb3JlIGR5bmFtaWMuXG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgYXNzaWduKFxuICAgICAgICAgIFt7IG5hbWU6IFwiYmxvZ1wiLCByb3V0ZXM6IFtcIi9ibG9nLyoqXCJdIH1dLFxuICAgICAgICAgIHJvdXRlcyhcIi9cIiwgXCIvW3RlYW1dL3NldHRpbmdzXCIsIFwiL2Jsb2cvW3NsdWddXCIpLFxuICAgICAgICApLFxuICAgICAgKS5ub3QudG9UaHJvdygpO1xuICAgICAgLy8gV2l0aG91dCBpdCwgYC9bdGVhbV0vc2V0dGluZ3NgIGlzIHdoYXQgTmV4dC5qcyByZXNvbHZlcyBpdCB0by5cbiAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICBhc3NpZ24oXG4gICAgICAgICAgW3sgbmFtZTogXCJibG9nXCIsIHJvdXRlczogW1wiL2Jsb2cvKipcIl0gfV0sXG4gICAgICAgICAgcm91dGVzKFwiL1wiLCBcIi9bdGVhbV0vc2V0dGluZ3NcIiwgXCIvYmxvZy94XCIpLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KC9cIlxcL2Jsb2dcXC9zZXR0aW5nc1wiIHRvIGdyb3VwIFwiYmxvZ1wiLyk7XG4gICAgfSk7XG5cbiAgICBpdChcImNoZWNrcyBhIHJvb3Qgb3B0aW9uYWwgY2F0Y2gtYWxsIGFnYWluc3Qgc3VidHJlZSBhbmQgZXhhY3QgcGF0dGVybnNcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihcbiAgICAgICAgICBbeyBuYW1lOiBcImRvY3NcIiwgcm91dGVzOiBbXCIvZG9jcy8qKlwiXSB9XSxcbiAgICAgICAgICByb3V0ZXMoXCIvW1suLi5zbHVnXV1cIiwgXCIvZG9jcy9bcGFnZV1cIiksXG4gICAgICAgICksXG4gICAgICApLnRvVGhyb3coL1wiXFwvZG9jc1xcL19cXC9fXCIgdG8gZ3JvdXAgXCJkb2NzXCIvKTtcbiAgICAgIC8vIEFuIGV4YWN0IHBhdHRlcm4gb3ducyBhIHN0YXRpYyByb3V0ZSwgd2hpY2ggTmV4dC5qcyBwcmVmZXJzLlxuICAgICAgZXhwZWN0KFxuICAgICAgICBhc3NpZ24oXG4gICAgICAgICAgW3sgbmFtZTogXCJhYm91dFwiLCByb3V0ZXM6IFtcIi9hYm91dFwiXSB9XSxcbiAgICAgICAgICByb3V0ZXMoXCIvW1suLi5zbHVnXV1cIiwgXCIvYWJvdXRcIiksXG4gICAgICAgICkuYWJvdXQsXG4gICAgICApLnRvRXF1YWwoW1wiL2Fib3V0XCJdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY2hlY2tzIGEgZ3JvdXBlZCBjYXRjaC1hbGwgYWdhaW5zdCBhIG5hcnJvd2VyIGdyb3VwJ3Mgc3VidHJlZVwiLCAoKSA9PiB7XG4gICAgICAvLyBgL2FwaS9yZXBvcnRzLzEvMmAgcmVhY2hlcyB0aGUgcmVwb3J0cyBmdW5jdGlvbiwgd2hpY2ggb25seSBoYXNcbiAgICAgIC8vIGAvYXBpL3JlcG9ydHMvW2lkXWA7IE5leHQuanMgcmVzb2x2ZXMgaXQgdG8gYC9hcGkvWy4uLnJlc3RdYC5cbiAgICAgIGV4cGVjdCgoKSA9PlxuICAgICAgICBhc3NpZ24oXG4gICAgICAgICAgW1xuICAgICAgICAgICAgeyBuYW1lOiBcImFwaVwiLCByb3V0ZXM6IFtcIi9hcGkvKipcIl0gfSxcbiAgICAgICAgICAgIHsgbmFtZTogXCJyZXBvcnRzXCIsIHJvdXRlczogW1wiL2FwaS9yZXBvcnRzLyoqXCJdIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICByb3V0ZXMoXCIvYXBpL1suLi5yZXN0XVwiLCBcIi9hcGkvcmVwb3J0cy9baWRdXCIpLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KFxuICAgICAgICAvXCJcXC9hcGlcXC9cXFtcXC5cXC5cXC5yZXN0XFxdXCIgaXMgcGFja2FnZWQgaW50byBncm91cCBcImFwaVwiLCBidXQgQ2xvdWRGcm9udCB3b3VsZCBzZW5kIFwiXFwvYXBpXFwvcmVwb3J0c1xcL19cXC9fXCIgdG8gZ3JvdXAgXCJyZXBvcnRzXCIvLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KFwiY2hlY2tzIGEgUGFnZXMgUm91dGVyIGNhdGNoLWFsbCdzIGRhdGEgVVJMc1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwYWdlID0gKHRlbXBsYXRlOiBzdHJpbmcsIGZpbGU6IHN0cmluZyk6IFJvdXRlRW50cnlbXSA9PiBbXG4gICAgICAgIHsgdGVtcGxhdGUsIGVudHJ5cG9pbnRJZDogZmlsZSwgdHlwZTogXCJwYWdlXCIgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRlbXBsYXRlOiBgL19uZXh0L2RhdGEvJHtCVUlMRF9JRH0ke3RlbXBsYXRlfS5qc29uYCxcbiAgICAgICAgICBlbnRyeXBvaW50SWQ6IGZpbGUsXG4gICAgICAgICAgdHlwZTogXCJwYWdlXCIsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGFzc2lnbihcbiAgICAgICAgICBbeyBuYW1lOiBcImJsb2dcIiwgcm91dGVzOiBbXCIvYmxvZy8qKlwiXSB9XSxcbiAgICAgICAgICBbXG4gICAgICAgICAgICAuLi5wYWdlKFwiL1suLi5zbHVnXVwiLCBcInBhZ2VzL1suLi5zbHVnXS5qc1wiKSxcbiAgICAgICAgICAgIC4uLnBhZ2UoXCIvYmxvZy9bc2x1Z11cIiwgXCJwYWdlcy9ibG9nL1tzbHVnXS5qc1wiKSxcbiAgICAgICAgICBdLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KC9cIlxcL19uZXh0XFwvZGF0YVxcL2FiYzEyM1xcL2Jsb2dcXC9fXFwvX1xcLmpzb25cIiB0byBncm91cCBcImJsb2dcIi8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIi9pbmRleCAoRylcIiwgKCkgPT4ge1xuICAgIGl0KFwiZ3JvdXBzIGFuIEFwcCBSb3V0ZXIgL2luZGV4LCBhIHJvdXRlIG9mIGl0cyBvd25cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgYXNzaWduZWQgPSBhc3NpZ24oXG4gICAgICAgIFt7IG5hbWU6IFwiaWR4XCIsIHJvdXRlczogW1wiL2luZGV4XCJdIH1dLFxuICAgICAgICBbXG4gICAgICAgICAgeyB0ZW1wbGF0ZTogXCIvXCIsIGVudHJ5cG9pbnRJZDogXCJhcHAvcGFnZS5qc1wiLCB0eXBlOiBcImFwcC1wYWdlXCIgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0ZW1wbGF0ZTogXCIvaW5kZXgucnNjXCIsXG4gICAgICAgICAgICBlbnRyeXBvaW50SWQ6IFwiYXBwL3BhZ2UuanNcIixcbiAgICAgICAgICAgIHR5cGU6IFwiYXBwLXBhZ2VcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHRlbXBsYXRlOiBcIi9pbmRleFwiLFxuICAgICAgICAgICAgZW50cnlwb2ludElkOiBcImFwcC9pbmRleC9wYWdlLmpzXCIsXG4gICAgICAgICAgICB0eXBlOiBcImFwcC1wYWdlXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICk7XG4gICAgICBleHBlY3QoYXNzaWduZWQuaWR4KS50b0VxdWFsKFtcIi9pbmRleFwiXSk7XG4gICAgfSk7XG5cbiAgICBpdChcInJlamVjdHMgdGhlIFBhZ2VzIFJvdXRlciBob21lIHBhZ2UsIHdoaWNoIGlzIGFsc28gL1wiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT5cbiAgICAgICAgYXNzaWduKFxuICAgICAgICAgIFt7IG5hbWU6IFwiaWR4XCIsIHJvdXRlczogW1wiL2luZGV4XCJdIH1dLFxuICAgICAgICAgIFtcIi9cIiwgXCIvaW5kZXhcIiwgYC9fbmV4dC9kYXRhLyR7QlVJTERfSUR9L2luZGV4Lmpzb25gXS5tYXAoXG4gICAgICAgICAgICAodGVtcGxhdGUpID0+ICh7XG4gICAgICAgICAgICAgIHRlbXBsYXRlLFxuICAgICAgICAgICAgICBlbnRyeXBvaW50SWQ6IFwicGFnZXMvaW5kZXguanNcIixcbiAgICAgICAgICAgICAgdHlwZTogXCJwYWdlXCIsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApLFxuICAgICAgICApLFxuICAgICAgKS50b1Rocm93KC9cIlxcL1wiIGNhbm5vdCBiZSByb3V0ZWQgdG8gYW55IGdyb3VwLipcIlxcL2luZGV4XCI6IG9uZSBmaWxlL3MpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcInJvdXRlZFBhdHRlcm5zXCIsICgpID0+IHtcbiAgaXQoXCJhZGRzIG5vdGhpbmcgZm9yIGEgZ3JvdXAgd2l0aG91dCBhbiBvcHRpb25hbCBjYXRjaC1hbGwgYXQgYSBzdWJ0cmVlJ3MgYmFzZVwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgcm91dGVkUGF0dGVybnMoXG4gICAgICAgIFtcIi9ibG9nLyoqXCIsIFwiL3ByaWNpbmdcIl0sXG4gICAgICAgIFtcIi9ibG9nL1tzbHVnXVwiLCBcIi9ibG9nL3gvW1suLi5yZXN0XV1cIiwgXCIvcHJpY2luZ1wiXSxcbiAgICAgICAgXCJcIixcbiAgICAgICksXG4gICAgKS50b0VxdWFsKFtcIi9ibG9nLyoqXCIsIFwiL3ByaWNpbmdcIl0pO1xuICB9KTtcblxuICBpdChcImRvZXMgbm90IHJlcGVhdCBhIHBhcmVudCB0aGUgZ3JvdXAgYWxyZWFkeSBkZWNsYXJlc1wiLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgcm91dGVkUGF0dGVybnMoW1wiL3Nob3AvKipcIiwgXCIvc2hvcFwiXSwgW1wiL3Nob3AvW1suLi5zbHVnXV1cIl0sIFwiXCIpLFxuICAgICkudG9FcXVhbChbXCIvc2hvcC8qKlwiLCBcIi9zaG9wXCJdKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJwYXRoUGF0dGVybnNGb3JcIiwgKCkgPT4ge1xuICBpdChcImRyb3BzIHRoZSBsZWFkaW5nIHNsYXNoLCBiZWNhdXNlIHRoZSBkaXN0cmlidXRpb24gYWRkcyBiYXNlUGF0aCBpdHNlbGZcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChwYXRoUGF0dGVybnNGb3IoXCIvcHJpY2luZ1wiLCB7IGhhc0RhdGFSb3V0ZXM6IGZhbHNlIH0pKS50b0VxdWFsKFtcbiAgICAgIFwicHJpY2luZ1wiLFxuICAgIF0pO1xuICB9KTtcblxuICBpdChcInR1cm5zIGEgc3VidHJlZSBpbnRvIGEgc2luZ2xlIHRyYWlsaW5nIHdpbGRjYXJkXCIsICgpID0+IHtcbiAgICBleHBlY3QoXG4gICAgICBwYXRoUGF0dGVybnNGb3IoXCIvYXBpL3JlcG9ydHMvKipcIiwgeyBoYXNEYXRhUm91dGVzOiBmYWxzZSB9KSxcbiAgICApLnRvRXF1YWwoW1wiYXBpL3JlcG9ydHMvKlwiXSk7XG4gIH0pO1xuXG4gIGl0KFwiYWRkcyB0aGUgYF9uZXh0L2RhdGFgIFVSTCBzcGFjZSBmb3IgUGFnZXMgUm91dGVyIGdyb3Vwcywgb24gdGhlIGxpdGVyYWwgYnVpbGQgSURcIiwgKCkgPT4ge1xuICAgIC8vIEEgYCpgIGZvciB0aGUgYnVpbGQgSUQgYWxzbyBtYXRjaGVzIGAvYCwgc28gYF9uZXh0L2RhdGEvKi9ibG9nLypgIGNsYWltZWRcbiAgICAvLyBgL19uZXh0L2RhdGEvPGlkPi9kb2NzL2Jsb2cveC5qc29uYCwgYSBwYWdlIG9mIGFub3RoZXIgZ3JvdXAuXG4gICAgY29uc3Qgb3B0aW9ucyA9IHsgaGFzRGF0YVJvdXRlczogdHJ1ZSwgYnVpbGRJZDogQlVJTERfSUQgfTtcbiAgICBleHBlY3QocGF0aFBhdHRlcm5zRm9yKFwiL2Jsb2cvKipcIiwgb3B0aW9ucykpLnRvRXF1YWwoW1xuICAgICAgXCJibG9nLypcIixcbiAgICAgIFwiX25leHQvZGF0YS9hYmMxMjMvYmxvZy8qXCIsXG4gICAgXSk7XG4gICAgZXhwZWN0KHBhdGhQYXR0ZXJuc0ZvcihcIi9wcmljaW5nXCIsIG9wdGlvbnMpKS50b0VxdWFsKFtcbiAgICAgIFwicHJpY2luZ1wiLFxuICAgICAgXCJfbmV4dC9kYXRhL2FiYzEyMy9wcmljaW5nLmpzb25cIixcbiAgICBdKTtcbiAgfSk7XG5cbiAgaXQoXCJyZWZ1c2VzIHRvIHJvdXRlIGRhdGEgVVJMcyB3aXRob3V0IHRoZSBidWlsZCBJRFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHBhdGhQYXR0ZXJuc0ZvcihcIi9ibG9nLyoqXCIsIHsgaGFzRGF0YVJvdXRlczogdHJ1ZSB9KSkudG9UaHJvdyhcbiAgICAgIC9uZWVkcyBpdHMgYnVpbGQgSUQvLFxuICAgICk7XG4gIH0pO1xuXG4gIGl0KFwicmVmdXNlcyBhIGJ1aWxkIElEIGEgcGF0aCBwYXR0ZXJuIGNhbm5vdCBob2xkXCIsICgpID0+IHtcbiAgICAvLyBgZ2VuZXJhdGVCdWlsZElkYCBjYW4gcmV0dXJuIGFueXRoaW5nLlxuICAgIGV4cGVjdCgoKSA9PlxuICAgICAgcGF0aFBhdHRlcm5zRm9yKFwiL2Jsb2cvKipcIiwgeyBoYXNEYXRhUm91dGVzOiB0cnVlLCBidWlsZElkOiBcInYxLzIgM1wiIH0pLFxuICAgICkudG9UaHJvdygvVGhlIGJ1aWxkIElEIFwidjFcXC8yIDNcIiBjb250YWlucyBcIlxcL1wiLCBcIiBcIi8pO1xuICB9KTtcblxuICBpdChcImFkZHMgdGhlIHRyYWlsaW5nLXNsYXNoIGZvcm0gZm9yIGEgdHJhaWxpbmdTbGFzaCBhcHBcIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIFdpdGggYHRyYWlsaW5nU2xhc2g6IHRydWVgIHRoZSBjYW5vbmljYWwgVVJMIGlzIGAvcHJpY2luZy9gLCBhbmQgdGhhdCBpc1xuICAgIC8vIHdoYXQgZXZlcnkgbGluayBpbiB0aGUgYXBwIHBvaW50cyBhdC4gQSBiZWhhdmlvciBvbiBgcHJpY2luZ2AgYWxvbmUgZG9lc1xuICAgIC8vIG5vdCBtYXRjaCBpdCwgc28gdGhlIHJlcXVlc3QgZmVsbCB0aHJvdWdoIHRvIHRoZSBkZWZhdWx0IGZ1bmN0aW9uIC0gd2hpY2hcbiAgICAvLyBkb2VzIG5vdCBoYXZlIHRoZSByb3V0ZSBwYWNrYWdlZC5cbiAgICBleHBlY3QocGF0aFBhdHRlcm5zRm9yKFwiL3ByaWNpbmdcIiwgeyBoYXNEYXRhUm91dGVzOiBmYWxzZSB9KSkudG9FcXVhbChbXG4gICAgICBcInByaWNpbmdcIixcbiAgICBdKTtcbiAgICBleHBlY3QoXG4gICAgICBwYXRoUGF0dGVybnNGb3IoXCIvcHJpY2luZ1wiLCB7XG4gICAgICAgIGhhc0RhdGFSb3V0ZXM6IGZhbHNlLFxuICAgICAgICB0cmFpbGluZ1NsYXNoOiB0cnVlLFxuICAgICAgfSksXG4gICAgKS50b0VxdWFsKFtcInByaWNpbmdcIiwgXCJwcmljaW5nL1wiXSk7XG4gIH0pO1xuXG4gIGl0KFwibGVhdmVzIGEgc3VidHJlZSBwYXR0ZXJuIGFsb25lLCB3aGljaCBhbHJlYWR5IG1hdGNoZXMgYm90aCBmb3Jtc1wiLCAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgcGF0aFBhdHRlcm5zRm9yKFwiL2FwaS9yZXBvcnRzLyoqXCIsIHtcbiAgICAgICAgaGFzRGF0YVJvdXRlczogZmFsc2UsXG4gICAgICAgIHRyYWlsaW5nU2xhc2g6IHRydWUsXG4gICAgICB9KSxcbiAgICApLnRvRXF1YWwoW1wiYXBpL3JlcG9ydHMvKlwiXSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwicGFyc2VGdW5jdGlvbkdyb3Vwc0VudlwiLCAoKSA9PiB7XG4gIGl0KFwicmV0dXJucyB1bmRlZmluZWQgd2hlbiB1bnNldFwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHBhcnNlRnVuY3Rpb25Hcm91cHNFbnYodW5kZWZpbmVkKSkudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcbn0pO1xuIl19
|