cdk-nextjs 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2467 -2714
- package/.jsii.tabl.json +1 -1
- package/API.md +1725 -1909
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +687 -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 +1548 -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 +852 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +861 -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 +13 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
- 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/post-deploy.lambda.js +3 -2
- 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 +19 -3
- package/lib/lambdas/post-deploy/prune-s3.js +54 -15
- package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
- 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 +107 -18
- package/lib/nextjs-api.js +349 -39
- package/lib/nextjs-api.test.js +582 -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 +23 -3
- package/lib/nextjs-post-deploy.js +14 -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 +23 -4
- package/lib/nextjs-static-assets.js +29 -6
- package/lib/nextjs-static-assets.test.js +20 -1
- package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
- package/lib/root-constructs/nextjs-base-construct.js +144 -34
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -70
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -69
- package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
- package/lib/root-constructs/nextjs-regional-containers.js +17 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -25
- 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 +1213 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1678 -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 +41595 -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 +55 -0
- package/lib/runtime/next-modules.js +124 -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 +41588 -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 +123 -11
- package/lib/utils/base-path.js +276 -39
- package/lib/utils/base-path.test.js +275 -50
- 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
package/lib/utils/base-path.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_API_GATEWAY_PREFIX = void 0;
|
|
3
4
|
exports.normalizeBasePath = normalizeBasePath;
|
|
5
|
+
exports.hasPathPrefix = hasPathPrefix;
|
|
6
|
+
exports.basePathPrefix = basePathPrefix;
|
|
7
|
+
exports.wholeAppInvalidationPaths = wholeAppInvalidationPaths;
|
|
4
8
|
exports.joinPath = joinPath;
|
|
5
|
-
exports.
|
|
9
|
+
exports.prefixWithBasePath = prefixWithBasePath;
|
|
10
|
+
exports.relativeAssetPrefix = relativeAssetPrefix;
|
|
11
|
+
exports.isAssetPrefixUnserved = isAssetPrefixUnserved;
|
|
12
|
+
exports.assetPrefixPath = assetPrefixPath;
|
|
6
13
|
exports.resolveBasePath = resolveBasePath;
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Pure `basePath` and URL path helpers. Nothing here imports `aws-cdk-lib` or
|
|
16
|
+
* touches the filesystem, so the adapter and runtime bundles can import it as
|
|
17
|
+
* well as the constructs.
|
|
18
|
+
*/
|
|
9
19
|
const constants_1 = require("../constants");
|
|
10
20
|
/**
|
|
11
21
|
* Reduces a `basePath` to a bare path segment so values that address the same
|
|
@@ -15,6 +25,39 @@ const constants_1 = require("../constants");
|
|
|
15
25
|
function normalizeBasePath(basePath) {
|
|
16
26
|
return (basePath || "").replace(/^\/+/, "").replace(/\/+$/, "");
|
|
17
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether `path` is `prefix` or under it on a segment boundary, so `/docsearch`
|
|
30
|
+
* is not under `/docs`. An empty `prefix` matches nothing. Both sides must be in
|
|
31
|
+
* the same form (both with or both without the leading `/`).
|
|
32
|
+
*/
|
|
33
|
+
function hasPathPrefix(path, prefix) {
|
|
34
|
+
return !!prefix && (path === prefix || path.startsWith(`${prefix}/`));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A `basePath` as Next.js spells it and URLs start with it: one leading slash,
|
|
38
|
+
* no trailing one ("/base"), `""` for none. Accepts any spelling
|
|
39
|
+
* {@link normalizeBasePath} does.
|
|
40
|
+
*/
|
|
41
|
+
function basePathPrefix(basePath) {
|
|
42
|
+
const bare = normalizeBasePath(basePath);
|
|
43
|
+
return bare ? `/${bare}` : "";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Invalidation paths covering every URI of the app: what a deploy invalidates,
|
|
47
|
+
* and what the cache handler's oversized batches, retries after a quota error,
|
|
48
|
+
* and tags whose routes could not all be named fall back to.
|
|
49
|
+
*
|
|
50
|
+
* `/*` is the whole app only without a `basePath`. `/base/*` matches neither the
|
|
51
|
+
* app's root, `/base`, nor its RSC payload, `/base?_rsc=…` - the same root the
|
|
52
|
+
* `revalidatePath("/")` that overflowed may have named - so those are spelled
|
|
53
|
+
* out. `/base*` would cover them for one wildcard, but also every sibling
|
|
54
|
+
* prefix (`/base2`, `/basement`), which may be another app on the same
|
|
55
|
+
* distribution.
|
|
56
|
+
*/
|
|
57
|
+
function wholeAppInvalidationPaths(basePath) {
|
|
58
|
+
const prefix = basePathPrefix(basePath);
|
|
59
|
+
return prefix ? [prefix, `${prefix}?*`, `${prefix}/*`] : ["/*"];
|
|
60
|
+
}
|
|
18
61
|
/**
|
|
19
62
|
* Joins path parts with a single "/", normalizing each (so no leading or
|
|
20
63
|
* trailing slash survives, including on the result) and dropping the empty
|
|
@@ -24,36 +67,181 @@ function joinPath(...parts) {
|
|
|
24
67
|
return parts.map(normalizeBasePath).filter(Boolean).join("/");
|
|
25
68
|
}
|
|
26
69
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
70
|
+
* Prefixes an absolute app path (a health check path, say) with `basePath`,
|
|
71
|
+
* always returning a leading slash. An empty or unset `basePath` only
|
|
72
|
+
* normalizes that leading slash. Anything after the first segment is passed
|
|
73
|
+
* through as given, trailing slash included, since a `trailingSlash` app
|
|
74
|
+
* answers "/api/health" and "/api/health/" differently.
|
|
75
|
+
*
|
|
76
|
+
* Use this for paths handed to something that talks to the app directly — an ALB
|
|
77
|
+
* target group health check, the container's own health probe — since the app
|
|
78
|
+
* only answers under its own `basePath`.
|
|
79
|
+
*
|
|
80
|
+
* Prefixes unconditionally, so `path` has to arrive as the app routes it,
|
|
81
|
+
* without `basePath`: for an app based at "/base", "/base/api/health" becomes
|
|
82
|
+
* "/base/base/api/health". Deliberately not special-cased — an app can route
|
|
83
|
+
* "/base/base/..." legitimately, and accepting both spellings would give the
|
|
84
|
+
* path two meanings. See `docs/breaking-changes.md` (0.6.0), which tells users
|
|
85
|
+
* who prefixed `healthCheckPath` by hand to drop the prefix.
|
|
86
|
+
*/
|
|
87
|
+
function prefixWithBasePath(basePath, path) {
|
|
88
|
+
const normalized = normalizeBasePath(basePath);
|
|
89
|
+
const absolute = path.startsWith("/") ? path : `/${path}`;
|
|
90
|
+
return normalized ? `/${normalized}${absolute}` : absolute;
|
|
91
|
+
}
|
|
92
|
+
/** Whether an `assetPrefix` names an origin rather than a path on this one. */
|
|
93
|
+
function isAbsoluteAssetPrefix(assetPrefix) {
|
|
94
|
+
return /^([a-z][a-z0-9+.-]*:)?\/\//i.test(assetPrefix);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The app's own `assetPrefix` as a path with a leading and no trailing slash
|
|
98
|
+
* ("/cdn"), or `""` when the app sets none.
|
|
99
|
+
*
|
|
100
|
+
* Returns `""` for an absolute `assetPrefix` ("https://cdn.example.com", or the
|
|
101
|
+
* protocol-relative "//cdn.example.com") too: that names an origin cdk-nextjs
|
|
102
|
+
* does not control, and it is the supported way to serve assets from elsewhere,
|
|
103
|
+
* so nothing about it is worth warning about. Use {@link assetPrefixPath} for
|
|
104
|
+
* what the *distribution* has to answer on, which includes the path an absolute
|
|
105
|
+
* prefix carries.
|
|
106
|
+
*
|
|
107
|
+
* Next.js applies `assetPrefix` on top of, not under, `basePath`, so the result
|
|
108
|
+
* is the whole prefix of a `_next/static` URL and must not be joined with
|
|
109
|
+
* `basePath`.
|
|
110
|
+
*/
|
|
111
|
+
function relativeAssetPrefix(assetPrefix) {
|
|
112
|
+
return isAbsoluteAssetPrefix(assetPrefix) ? "" : basePathPrefix(assetPrefix);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether a path-style `assetPrefix` would go unanswered on this `NextjsType`,
|
|
116
|
+
* i.e. whether every bundle would 404.
|
|
117
|
+
*
|
|
118
|
+
* `assetPrefix` moves every bundle URL to `<assetPrefix>/_next/static/...` while
|
|
119
|
+
* the objects keep their `<basePath>/_next/static/...` S3 keys. The Global
|
|
120
|
+
* `NextjsType`s answer that with a cache behavior of their own
|
|
121
|
+
* (`NextjsDistribution`); the regional ones have nothing that maps the prefix
|
|
122
|
+
* back — API Gateway's `_next/static` resource and the container's own files are
|
|
123
|
+
* both under the unprefixed path.
|
|
124
|
+
*
|
|
125
|
+
* A prefix equal to the app's own `basePath` is **not** unserved, because that is
|
|
126
|
+
* the value Next.js resolves `assetPrefix` to when `basePath` is set and
|
|
127
|
+
* `assetPrefix` is not: `.next/required-server-files.json` comes back as
|
|
128
|
+
* `{"assetPrefix":"/prod","basePath":"/prod"}` for an app that only ever set
|
|
129
|
+
* `basePath`. Without that exemption the warning fired on every regional
|
|
130
|
+
* deployment that sets a `basePath` at all — including `examples/regional-functions`
|
|
131
|
+
* — telling users their bundles would 404 at the one path that does serve them.
|
|
132
|
+
* `NextjsDistribution.resolveAssetPrefix` drops the prefix for the same reason.
|
|
31
133
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* `NextjsType`s that derive `basePath` from the app would quietly not derive
|
|
36
|
-
* it and 404 every static asset.
|
|
134
|
+
* Both sides go through `normalizeBasePath` because they arrive in different
|
|
135
|
+
* shapes: `nextConfigAssetPrefix` carries a leading slash (`"/prod"`),
|
|
136
|
+
* `nextConfigBasePath` does not (`"prod"`).
|
|
37
137
|
*/
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
138
|
+
function isAssetPrefixUnserved(nextjsType, nextConfigAssetPrefix, nextConfigBasePath) {
|
|
139
|
+
if (!nextConfigAssetPrefix)
|
|
140
|
+
return false;
|
|
141
|
+
if (nextjsType === constants_1.NextjsType.GLOBAL_FUNCTIONS ||
|
|
142
|
+
nextjsType === constants_1.NextjsType.GLOBAL_CONTAINERS) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return (normalizeBasePath(nextConfigAssetPrefix) !==
|
|
146
|
+
normalizeBasePath(nextConfigBasePath));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The *path* every bundle URL carries, whichever form `assetPrefix` takes: "/cdn"
|
|
150
|
+
* for `assetPrefix: "/cdn"` and for `assetPrefix:
|
|
151
|
+
* "https://cdn.example.com/cdn"` alike, `""` when there is none (an absolute
|
|
152
|
+
* prefix with no path, or no prefix at all).
|
|
153
|
+
*
|
|
154
|
+
* An absolute prefix's path counts because `next build` compiles a `beforeFiles`
|
|
155
|
+
* rewrite of its own for it — `/cdn/_next/:path+ → /_next/:path+` — so `next
|
|
156
|
+
* start` serves every bundle under that path as well as under `/_next`. A CDN
|
|
157
|
+
* fronting this deployment at that path therefore has to be answered, and the
|
|
158
|
+
* distribution's `assetPrefix` behavior is what answers it. Measured against
|
|
159
|
+
* `test/e2e/app-dir/asset-prefix-absolute`; see `docs/harness-coverage.md`.
|
|
160
|
+
* Shared with `NextjsDistribution`, whose `assetPrefix` prop a user can also
|
|
161
|
+
* set by hand.
|
|
162
|
+
*/
|
|
163
|
+
function assetPrefixPath(assetPrefix) {
|
|
164
|
+
if (!assetPrefix)
|
|
44
165
|
return "";
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
166
|
+
let path = assetPrefix;
|
|
167
|
+
if (isAbsoluteAssetPrefix(assetPrefix)) {
|
|
168
|
+
try {
|
|
169
|
+
// `//cdn.example.com/cdn` is protocol-relative, which `URL` only parses
|
|
170
|
+
// with a base — any base, since only the path is read off it.
|
|
171
|
+
path = new URL(assetPrefix, "https://asset-prefix.invalid").pathname;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return "";
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return basePathPrefix(path);
|
|
178
|
+
}
|
|
179
|
+
/** `RestApi`'s own defaults: the `prod` stage, no custom domain. */
|
|
180
|
+
exports.DEFAULT_API_GATEWAY_PREFIX = {
|
|
181
|
+
strippedPrefix: "prod",
|
|
182
|
+
customDomain: false,
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* The resource path an app's `basePath` needs on `REGIONAL_FUNCTIONS` when the
|
|
186
|
+
* `basePath` prop is unset: the app's `basePath` with the prefix API Gateway
|
|
187
|
+
* strips taken off the front, or the whole of it when it does not start with
|
|
188
|
+
* that prefix.
|
|
189
|
+
*
|
|
190
|
+
* An app at the `prod` stage emits `/prod/...` and API Gateway strips `/prod`
|
|
191
|
+
* before matching, so `basePath: "/prod"` needs resources at the root and
|
|
192
|
+
* `basePath: "/prod/base"` needs them under `base`. An app whose `basePath` API
|
|
193
|
+
* Gateway does not strip — a custom domain mapped at the root, serving
|
|
194
|
+
* `basePath: "/docs"` — needs them under `docs`. Leaving that one at the root is
|
|
195
|
+
* what used to happen: `_next/static` and `public/` fell through to the
|
|
196
|
+
* `{proxy+}` catch-all, and every bundle 404'd with nothing said at synth.
|
|
197
|
+
*/
|
|
198
|
+
function deriveApiGatewayBasePath(config, { strippedPrefix, customDomain }) {
|
|
199
|
+
if (!config || strippedPrefix === undefined) {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
const stripped = normalizeBasePath(strippedPrefix);
|
|
203
|
+
if (hasPathPrefix(config, stripped)) {
|
|
204
|
+
return config.slice(stripped.length + 1) || undefined;
|
|
205
|
+
}
|
|
206
|
+
warnUnstrippedBasePath(config, { strippedPrefix, customDomain });
|
|
207
|
+
return config;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Warn that an app mounted under its whole `basePath` is served somewhere its
|
|
211
|
+
* own links don't reach, when API Gateway strips a prefix that `basePath` lacks.
|
|
212
|
+
* Both ways of arriving there warn: the prop left unset (derived to the whole
|
|
213
|
+
* `basePath`) and the prop set to the same value.
|
|
214
|
+
*/
|
|
215
|
+
function warnUnstrippedBasePath(config, { strippedPrefix, customDomain }) {
|
|
216
|
+
const stripped = normalizeBasePath(strippedPrefix);
|
|
217
|
+
if (strippedPrefix === undefined || !stripped) {
|
|
218
|
+
// A token, or a custom domain mapped at the root: nothing is stripped that
|
|
219
|
+
// the app's links could miss.
|
|
220
|
+
return;
|
|
48
221
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
222
|
+
if (customDomain) {
|
|
223
|
+
// The same miss through a custom domain's base path mapping: served at
|
|
224
|
+
// `/<mapping>/<basePath>`, linking to `/<basePath>/...`, which no mapping
|
|
225
|
+
// covers.
|
|
226
|
+
console.warn(`${constants_1.LOG_PREFIX} your Next.js app's \`basePath\` is ${quote(config)}, which does not start with the custom domain's base path mapping "/${stripped}". ` +
|
|
227
|
+
"Its links and bundle URLs will be requested without the mapping, which the custom domain answers with 403. " +
|
|
228
|
+
`Set \`basePath: "/${joinPath(stripped, config)}"\` in your next.config, or map the domain at the root.`);
|
|
52
229
|
}
|
|
53
|
-
|
|
54
|
-
|
|
230
|
+
else {
|
|
231
|
+
// Resources under the app's basePath serve it at `/<stage>/<basePath>`, but
|
|
232
|
+
// the app's own links are `/<basePath>/...`, which misses the stage. A
|
|
233
|
+
// warning, not an error: a domain attached after synth (`addDomainName`)
|
|
234
|
+
// makes it right, and synth cannot see that.
|
|
235
|
+
console.warn(`${constants_1.LOG_PREFIX} your Next.js app's \`basePath\` is ${quote(config)}, which does not start with the API Gateway stage "/${stripped}". ` +
|
|
236
|
+
"Its links and bundle URLs will be requested without the stage, which the execute-api endpoint answers with 403. " +
|
|
237
|
+
`Set \`basePath: "/${joinPath(stripped, config)}"\` in your next.config, or serve the app from a custom domain mapped at the root.`);
|
|
55
238
|
}
|
|
56
239
|
}
|
|
240
|
+
/** Whether API Gateway strips the front of `basePath` before matching resources. */
|
|
241
|
+
function startsWithStrippedPrefix(basePath, { strippedPrefix }) {
|
|
242
|
+
const stripped = normalizeBasePath(strippedPrefix);
|
|
243
|
+
return !!basePath && hasPathPrefix(basePath, stripped);
|
|
244
|
+
}
|
|
57
245
|
function quote(basePath) {
|
|
58
246
|
return basePath ? `"/${basePath}"` : "unset";
|
|
59
247
|
}
|
|
@@ -69,15 +257,43 @@ function quote(basePath) {
|
|
|
69
257
|
* land under), the config is the prefix the app emits its own links and asset
|
|
70
258
|
* hrefs under — so how strictly they have to line up, and whether one can stand
|
|
71
259
|
* in for the other, depends on how the `NextjsType` routes static requests.
|
|
260
|
+
*
|
|
261
|
+
* `apiGateway` is only read for `REGIONAL_FUNCTIONS`, and only when the prop is
|
|
262
|
+
* unset: see `deriveApiGatewayBasePath`.
|
|
72
263
|
*/
|
|
73
|
-
function resolveBasePath(nextjsType, propBasePath, nextConfigBasePath) {
|
|
264
|
+
function resolveBasePath(nextjsType, propBasePath, nextConfigBasePath, apiGateway = exports.DEFAULT_API_GATEWAY_PREFIX) {
|
|
74
265
|
const prop = normalizeBasePath(propBasePath);
|
|
75
266
|
const config = normalizeBasePath(nextConfigBasePath);
|
|
267
|
+
const mismatch = `${constants_1.LOG_PREFIX} basePath mismatch for NextjsType.${nextjsType}: the \`basePath\` prop is ${quote(prop)} ` +
|
|
268
|
+
`but your Next.js app's config sets \`basePath\` to ${quote(config)}. `;
|
|
76
269
|
if (prop === config) {
|
|
270
|
+
if (nextjsType === constants_1.NextjsType.REGIONAL_FUNCTIONS &&
|
|
271
|
+
startsWithStrippedPrefix(prop, apiGateway)) {
|
|
272
|
+
// Agreeing is not enough here: API Gateway strips the stage (or base path
|
|
273
|
+
// mapping) before matching, so resources under the prop's "prod" are only
|
|
274
|
+
// reached at `/prod/prod/...`, and every link the app emits 403s.
|
|
275
|
+
const problem = `API Gateway strips "/${normalizeBasePath(apiGateway.strippedPrefix)}" before matching resources, so a prop that repeats it nests every resource under a path no request reaches. ` +
|
|
276
|
+
"Leave the prop unset: it is derived from your app's `basePath` with that prefix taken off.";
|
|
277
|
+
if (apiGateway.customDomain) {
|
|
278
|
+
throw new Error(mismatch + problem);
|
|
279
|
+
}
|
|
280
|
+
// On the execute-api endpoint that is certain, but an explicit prop wins:
|
|
281
|
+
// a domain attached with `addDomainName()`, invisible here, can map the
|
|
282
|
+
// stage at its root, and then `/prod/...` does reach resources under
|
|
283
|
+
// "prod".
|
|
284
|
+
console.warn(mismatch +
|
|
285
|
+
problem +
|
|
286
|
+
" (Ignore this if a domain attached with `addDomainName()` serves the app without stripping that prefix.)");
|
|
287
|
+
return prop;
|
|
288
|
+
}
|
|
289
|
+
if (nextjsType === constants_1.NextjsType.REGIONAL_FUNCTIONS && prop) {
|
|
290
|
+
// Agreeing the other way round has the unset case's problem: resources
|
|
291
|
+
// under "docs" are reached at `/prod/docs/...`, the app links to
|
|
292
|
+
// `/docs/...`.
|
|
293
|
+
warnUnstrippedBasePath(config, apiGateway);
|
|
294
|
+
}
|
|
77
295
|
return prop || undefined;
|
|
78
296
|
}
|
|
79
|
-
const mismatch = `${constants_1.LOG_PREFIX} basePath mismatch for NextjsType.${nextjsType}: the \`basePath\` prop is ${quote(prop)} ` +
|
|
80
|
-
`but your Next.js app's config sets \`basePath\` to ${quote(config)}. `;
|
|
81
297
|
switch (nextjsType) {
|
|
82
298
|
case constants_1.NextjsType.GLOBAL_FUNCTIONS:
|
|
83
299
|
case constants_1.NextjsType.GLOBAL_CONTAINERS:
|
|
@@ -93,26 +309,47 @@ function resolveBasePath(nextjsType, propBasePath, nextConfigBasePath) {
|
|
|
93
309
|
"CloudFront serves static assets straight from S3 using the request path as the object key, so a mismatch means every `_next/static` and `public/` request 404s. " +
|
|
94
310
|
"Either set both to the same value, or drop the prop — left unset, it follows your app's `basePath`.");
|
|
95
311
|
case constants_1.NextjsType.REGIONAL_FUNCTIONS:
|
|
96
|
-
// Deliberately not derived: API Gateway mounts resources below the stage
|
|
97
|
-
// and strips it before invoking the app, so an app whose basePath is the
|
|
98
|
-
// stage name (or a custom domain base path mapping that gets stripped the
|
|
99
|
-
// same way) is correct precisely because the prop stays unset.
|
|
100
312
|
if (!prop) {
|
|
101
|
-
|
|
313
|
+
// A prop that is set but names no path ("/") is an explicit root
|
|
314
|
+
// mount, not "unset": it is how an app says the prefix is stripped by
|
|
315
|
+
// something synth can't see — a domain attached later with
|
|
316
|
+
// `addDomainName({ basePath })`, say — so deriving here would nest the
|
|
317
|
+
// resources under a path the stripped requests never reach.
|
|
318
|
+
if (propBasePath !== undefined) {
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
return deriveApiGatewayBasePath(config, apiGateway);
|
|
102
322
|
}
|
|
103
323
|
// The prop only has to be the tail of what the app emits, not all of it,
|
|
104
324
|
// because the stripped prefix is part of the app's `basePath` but never
|
|
105
325
|
// part of the resource path: an app at the `prod` stage nested under
|
|
106
|
-
// "/base" sets `basePath: "/prod/base"` and the prop to "/base".
|
|
107
|
-
//
|
|
108
|
-
|
|
326
|
+
// "/base" sets `basePath: "/prod/base"` and the prop to "/base". Exactly
|
|
327
|
+
// the stripped prefix and then the prop, not any tail: with a prop of
|
|
328
|
+
// "/base" an app at "/foo/base" is served at `/prod/base/...` and links
|
|
329
|
+
// to `/foo/base/...`, which 403s. Only a token stage, which synth can't
|
|
330
|
+
// read, falls back to a tail on a path boundary.
|
|
331
|
+
if (apiGateway.strippedPrefix === undefined
|
|
332
|
+
? config.endsWith(`/${prop}`)
|
|
333
|
+
: config === joinPath(apiGateway.strippedPrefix, prop)) {
|
|
334
|
+
return prop;
|
|
335
|
+
}
|
|
336
|
+
// Any tail on a path boundary is also what a domain attached with
|
|
337
|
+
// `addDomainName({ basePath: "v1" })` needs for an app at "/v1/base":
|
|
338
|
+
// synth only sees the stage, so it can't tell that setup from a mistake.
|
|
339
|
+
// An explicit prop wins, so that warns; a custom domain configured in
|
|
340
|
+
// `restApiProps.domainName` is visible, so there it still throws below.
|
|
341
|
+
if (!apiGateway.customDomain && config.endsWith(`/${prop}`)) {
|
|
342
|
+
const leading = config.slice(0, -prop.length - 1);
|
|
343
|
+
console.warn(`${constants_1.LOG_PREFIX} the \`basePath\` prop is ${quote(prop)} and your Next.js app's \`basePath\` is ${quote(config)}, ` +
|
|
344
|
+
`so the app is served at "/${joinPath(normalizeBasePath(apiGateway.strippedPrefix), prop)}" on the execute-api endpoint and links to "/${config}". ` +
|
|
345
|
+
`That only works through a custom domain whose base path mapping strips "/${leading}" (\`addDomainName({ basePath: "${leading}" })\`); otherwise every request 403s.`);
|
|
109
346
|
return prop;
|
|
110
347
|
}
|
|
111
348
|
// Anything else never works: the prop moves every resource, including the
|
|
112
349
|
// `ANY` catch-all, under a path the app never links to.
|
|
113
350
|
throw new Error(mismatch +
|
|
114
351
|
"The `basePath` prop nests every API Gateway resource under that path, including the catch-all, so the app has to emit its links under the same prefix or every request 404s. " +
|
|
115
|
-
'Either set your app\'s `basePath` to
|
|
352
|
+
'Either set your app\'s `basePath` to the prop, or to the prop prefixed by the stage or base path mapping API Gateway strips (e.g. `basePath: "/prod/base"` with a prop of "/base"), or leave the prop unset — unset is what you want when the app\'s `basePath` is the API Gateway stage name, since the stage isn\'t part of the resource path.');
|
|
116
353
|
case constants_1.NextjsType.REGIONAL_CONTAINERS:
|
|
117
354
|
// The ALB forwards every path to the container, which serves its own
|
|
118
355
|
// static assets, so here `basePath` only namespaces the S3 bucket and has
|
|
@@ -120,4 +357,4 @@ function resolveBasePath(nextjsType, propBasePath, nextConfigBasePath) {
|
|
|
120
357
|
return prop || undefined;
|
|
121
358
|
}
|
|
122
359
|
}
|
|
123
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1wYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2Jhc2UtcGF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLDhDQUVDO0FBT0QsNEJBRUM7QUFjRCx3REF1QkM7QUFtQkQsMENBNERDO0FBeElELHFDQUFtRDtBQUNuRCx5Q0FBaUM7QUFDakMsNENBQXNEO0FBRXREOzs7O0dBSUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxRQUFpQjtJQUNqRCxPQUFPLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNsRSxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLFFBQVEsQ0FBQyxHQUFHLEtBQTZCO0lBQ3ZELE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDaEUsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQUMsV0FBbUI7SUFDeEQsTUFBTSxtQkFBbUIsR0FBRyxJQUFBLGdCQUFJLEVBQUMsV0FBVyxFQUFFLDRCQUE0QixDQUFDLENBQUM7SUFDNUUsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFjLEVBQUUsRUFBRTtRQUNsQyxPQUFPLENBQUMsSUFBSSxDQUNWLEdBQUcsc0JBQVUsSUFBSSxNQUFNLG9EQUFvRDtZQUN6RSxxRUFBcUU7WUFDckUsdURBQXVELENBQzFELENBQUM7UUFDRixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUMsQ0FBQztJQUNGLElBQUksQ0FBQyxJQUFBLG9CQUFVLEVBQUMsbUJBQW1CLENBQUMsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sUUFBUSxDQUNiLDZDQUE2QyxtQkFBbUIsRUFBRSxDQUNuRSxDQUFDO0lBQ0osQ0FBQztJQUNELElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUEsc0JBQVksRUFBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQzFFLE9BQU8saUJBQWlCLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxRQUFRLENBQ2IsZ0NBQWdDLG1CQUFtQixLQUFLLEtBQUssRUFBRSxDQUNoRSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLEtBQUssQ0FBQyxRQUFnQjtJQUM3QixPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxTQUFnQixlQUFlLENBQzdCLFVBQXNCLEVBQ3RCLFlBQXFCLEVBQ3JCLGtCQUEyQjtJQUUzQixNQUFNLElBQUksR0FBRyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUM3QyxNQUFNLE1BQU0sR0FBRyxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JELElBQUksSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQ3BCLE9BQU8sSUFBSSxJQUFJLFNBQVMsQ0FBQztJQUMzQixDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQ1osR0FBRyxzQkFBVSxxQ0FBcUMsVUFBVSw4QkFBOEIsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHO1FBQ3hHLHNEQUFzRCxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztJQUUxRSxRQUFRLFVBQVUsRUFBRSxDQUFDO1FBQ25CLEtBQUssc0JBQVUsQ0FBQyxnQkFBZ0IsQ0FBQztRQUNqQyxLQUFLLHNCQUFVLENBQUMsaUJBQWlCO1lBQy9CLDRFQUE0RTtZQUM1RSxxRUFBcUU7WUFDckUseUVBQXlFO1lBQ3pFLHdFQUF3RTtZQUN4RSxtRUFBbUU7WUFDbkUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNWLE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLFFBQVE7Z0JBQ04sa0tBQWtLO2dCQUNsSyxxR0FBcUcsQ0FDeEcsQ0FBQztRQUNKLEtBQUssc0JBQVUsQ0FBQyxrQkFBa0I7WUFDaEMseUVBQXlFO1lBQ3pFLHlFQUF5RTtZQUN6RSwwRUFBMEU7WUFDMUUsK0RBQStEO1lBQy9ELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDVixPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBQ0QseUVBQXlFO1lBQ3pFLHdFQUF3RTtZQUN4RSxxRUFBcUU7WUFDckUseUVBQXlFO1lBQ3pFLG9FQUFvRTtZQUNwRSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hDLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUNELDBFQUEwRTtZQUMxRSx3REFBd0Q7WUFDeEQsTUFBTSxJQUFJLEtBQUssQ0FDYixRQUFRO2dCQUNOLCtLQUErSztnQkFDL0ssdVZBQXVWLENBQzFWLENBQUM7UUFDSixLQUFLLHNCQUFVLENBQUMsbUJBQW1CO1lBQ2pDLHFFQUFxRTtZQUNyRSwwRUFBMEU7WUFDMUUsdURBQXVEO1lBQ3ZELE9BQU8sSUFBSSxJQUFJLFNBQVMsQ0FBQztJQUM3QixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgTE9HX1BSRUZJWCwgTmV4dGpzVHlwZSB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBSZWR1Y2VzIGEgYGJhc2VQYXRoYCB0byBhIGJhcmUgcGF0aCBzZWdtZW50IHNvIHZhbHVlcyB0aGF0IGFkZHJlc3MgdGhlIHNhbWVcbiAqIHBhdGggKFwiL2Jhc2VcIiwgXCJiYXNlXCIsIFwiL2Jhc2UvXCIpIGNvbXBhcmUgZXF1YWwgYW5kIGNhbiBiZSBjb25jYXRlbmF0ZWRcbiAqIHdpdGhvdXQgZG91Ymxpbmcgc2VwYXJhdG9ycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZUJhc2VQYXRoKGJhc2VQYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIChiYXNlUGF0aCB8fCBcIlwiKS5yZXBsYWNlKC9eXFwvKy8sIFwiXCIpLnJlcGxhY2UoL1xcLyskLywgXCJcIik7XG59XG5cbi8qKlxuICogSm9pbnMgcGF0aCBwYXJ0cyB3aXRoIGEgc2luZ2xlIFwiL1wiLCBub3JtYWxpemluZyBlYWNoIChzbyBubyBsZWFkaW5nIG9yXG4gKiB0cmFpbGluZyBzbGFzaCBzdXJ2aXZlcywgaW5jbHVkaW5nIG9uIHRoZSByZXN1bHQpIGFuZCBkcm9wcGluZyB0aGUgZW1wdHlcbiAqIG9uZXMsIHNvIGFuIHVuc2V0IGBiYXNlUGF0aGAgb3Iga2V5IHByZWZpeCBsZWF2ZXMgdGhlIHJlc3QgdW50b3VjaGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gam9pblBhdGgoLi4ucGFydHM6IChzdHJpbmcgfCB1bmRlZmluZWQpW10pOiBzdHJpbmcge1xuICByZXR1cm4gcGFydHMubWFwKG5vcm1hbGl6ZUJhc2VQYXRoKS5maWx0ZXIoQm9vbGVhbikuam9pbihcIi9cIik7XG59XG5cbi8qKlxuICogUmVhZCB0aGUgTmV4dC5qcyBhcHAncyBvd24gYGJhc2VQYXRoYCBvdXQgb2YgYHJlcXVpcmVkLXNlcnZlci1maWxlcy5qc29uYCxcbiAqIHdoaWNoIGBuZXh0IGJ1aWxkYCB3cml0ZXMgaW50byBgLm5leHRgIHdpdGggdGhlIGZ1bGx5IHJlc29sdmVkIGNvbmZpZyAoc29cbiAqIHRoaXMgcGlja3MgdXAgYSBgYmFzZVBhdGhgIGNvbXB1dGVkIGluIGBuZXh0LmNvbmZpZy5qc2AsIG5vdCBvbmx5IGEgbGl0ZXJhbFxuICogb25lKS4gTm9ybWFsaXplZCwgZW1wdHkgd2hlbiB0aGUgYXBwIHNldHMgbm9uZS5cbiAqXG4gKiBEZWdyYWRlcyB0byBgXCJcImAgcmF0aGVyIHRoYW4gdGhyb3dpbmcsIHNpbmNlIGFuIHVucmVhZGFibGUgZmlsZSBzaG91bGRuJ3RcbiAqIGZhaWwgYSBkZXBsb3ltZW50IHRoYXQgd291bGQgb3RoZXJ3aXNlIHdvcmsuIEl0IHdhcm5zIGJlY2F1c2UgYFwiXCJgIGlzXG4gKiBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGFuIGFwcCB0aGF0IGdlbnVpbmVseSBzZXRzIG5vIGBiYXNlUGF0aGA6IHRoZVxuICogYE5leHRqc1R5cGVgcyB0aGF0IGRlcml2ZSBgYmFzZVBhdGhgIGZyb20gdGhlIGFwcCB3b3VsZCBxdWlldGx5IG5vdCBkZXJpdmVcbiAqIGl0IGFuZCA0MDQgZXZlcnkgc3RhdGljIGFzc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZE5leHRDb25maWdCYXNlUGF0aChkb3ROZXh0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcmVxdWlyZWRTZXJ2ZXJGaWxlcyA9IGpvaW4oZG90TmV4dFBhdGgsIFwicmVxdWlyZWQtc2VydmVyLWZpbGVzLmpzb25cIik7XG4gIGNvbnN0IGZhbGxiYWNrID0gKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYCR7TE9HX1BSRUZJWH0gJHtyZWFzb259LiBBc3N1bWluZyB5b3VyIE5leHQuanMgYXBwIHNldHMgbm8gXFxgYmFzZVBhdGhcXGA6IGAgK1xuICAgICAgICBcImlmIGl0IGRvZXMgc2V0IG9uZSwgc3RhdGljIGFzc2V0cyB3aWxsIDQwNCBhbmQgYW55IGBiYXNlUGF0aGAgcHJvcCBcIiArXG4gICAgICAgIFwibWlzbWF0Y2ggcmVwb3J0ZWQgYXQgc3ludGggd2lsbCBuYW1lIHRoZSB3cm9uZyB2YWx1ZS5cIixcbiAgICApO1xuICAgIHJldHVybiBcIlwiO1xuICB9O1xuICBpZiAoIWV4aXN0c1N5bmMocmVxdWlyZWRTZXJ2ZXJGaWxlcykpIHtcbiAgICByZXR1cm4gZmFsbGJhY2soXG4gICAgICBgXCJyZXF1aXJlZC1zZXJ2ZXItZmlsZXMuanNvblwiIG5vdCBmb3VuZCBhdCAke3JlcXVpcmVkU2VydmVyRmlsZXN9YCxcbiAgICApO1xuICB9XG4gIHRyeSB7XG4gICAgY29uc3QgeyBjb25maWcgfSA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHJlcXVpcmVkU2VydmVyRmlsZXMsIFwidXRmLThcIikpO1xuICAgIHJldHVybiBub3JtYWxpemVCYXNlUGF0aChjb25maWc/LmJhc2VQYXRoKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gZmFsbGJhY2soXG4gICAgICBgQ291bGQgbm90IHJlYWQgYmFzZVBhdGggZnJvbSAke3JlcXVpcmVkU2VydmVyRmlsZXN9OiAke2Vycm9yfWAsXG4gICAgKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBxdW90ZShiYXNlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGJhc2VQYXRoID8gYFwiLyR7YmFzZVBhdGh9XCJgIDogXCJ1bnNldFwiO1xufVxuXG4vKipcbiAqIFNldHRsZXMgb24gdGhlIHNpbmdsZSBgYmFzZVBhdGhgIHRoZSBpbmZyYXN0cnVjdHVyZSBzaG91bGQgYmUgYnVpbHQgYXJvdW5kLFxuICogZ2l2ZW4gdGhlIENESyBgYmFzZVBhdGhgIHByb3AgYW5kIHRoZSBOZXh0LmpzIGFwcCdzIG93biBgYmFzZVBhdGhgXG4gKiAoYE5leHRqc0J1aWxkLm5leHRDb25maWdCYXNlUGF0aGApLCB0aHJvd2luZyBhdCBzeW50aCBpZiB0aGUgdHdvIGNhbid0IHNlcnZlXG4gKiB0aGUgYXBwIHRvZ2V0aGVyLiBSZXR1cm5zIGEgbm9ybWFsaXplZCB2YWx1ZSwgb3IgYHVuZGVmaW5lZGAgZm9yIG5vXG4gKiBgYmFzZVBhdGhgIGF0IGFsbDsgY29uc3VtZXJzIHRoYXQgbmVlZCBhIGxlYWRpbmcgc2xhc2ggYWRkIHRoZWlyIG93bi5cbiAqXG4gKiBUaGUgdHdvIGlucHV0cyBhcmUgZ2VudWluZWx5IGRpZmZlcmVudCB0aGluZ3Mg4oCUIHRoZSBwcm9wIGlzIHdoZXJlIHRoZVxuICogaW5mcmFzdHJ1Y3R1cmUgc2VydmVzIHRoZSBhcHAgZnJvbSAoYW5kIHdoaWNoIFMzIGtleSBwcmVmaXggdGhlIHN0YXRpYyBhc3NldHNcbiAqIGxhbmQgdW5kZXIpLCB0aGUgY29uZmlnIGlzIHRoZSBwcmVmaXggdGhlIGFwcCBlbWl0cyBpdHMgb3duIGxpbmtzIGFuZCBhc3NldFxuICogaHJlZnMgdW5kZXIg4oCUIHNvIGhvdyBzdHJpY3RseSB0aGV5IGhhdmUgdG8gbGluZSB1cCwgYW5kIHdoZXRoZXIgb25lIGNhbiBzdGFuZFxuICogaW4gZm9yIHRoZSBvdGhlciwgZGVwZW5kcyBvbiBob3cgdGhlIGBOZXh0anNUeXBlYCByb3V0ZXMgc3RhdGljIHJlcXVlc3RzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUJhc2VQYXRoKFxuICBuZXh0anNUeXBlOiBOZXh0anNUeXBlLFxuICBwcm9wQmFzZVBhdGg/OiBzdHJpbmcsXG4gIG5leHRDb25maWdCYXNlUGF0aD86IHN0cmluZyxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHByb3AgPSBub3JtYWxpemVCYXNlUGF0aChwcm9wQmFzZVBhdGgpO1xuICBjb25zdCBjb25maWcgPSBub3JtYWxpemVCYXNlUGF0aChuZXh0Q29uZmlnQmFzZVBhdGgpO1xuICBpZiAocHJvcCA9PT0gY29uZmlnKSB7XG4gICAgcmV0dXJuIHByb3AgfHwgdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgbWlzbWF0Y2ggPVxuICAgIGAke0xPR19QUkVGSVh9IGJhc2VQYXRoIG1pc21hdGNoIGZvciBOZXh0anNUeXBlLiR7bmV4dGpzVHlwZX06IHRoZSBcXGBiYXNlUGF0aFxcYCBwcm9wIGlzICR7cXVvdGUocHJvcCl9IGAgK1xuICAgIGBidXQgeW91ciBOZXh0LmpzIGFwcCdzIGNvbmZpZyBzZXRzIFxcYGJhc2VQYXRoXFxgIHRvICR7cXVvdGUoY29uZmlnKX0uIGA7XG5cbiAgc3dpdGNoIChuZXh0anNUeXBlKSB7XG4gICAgY2FzZSBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlM6XG4gICAgY2FzZSBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTOlxuICAgICAgLy8gYE5leHRqc0Rpc3RyaWJ1dGlvbmAgYnVpbGRzIGl0cyBiZWhhdmlvcnMgYXMgYC8ke2Jhc2VQYXRofS9fbmV4dC9zdGF0aWMqYFxuICAgICAgLy8gYW5kIENsb3VkRnJvbnQgaGFuZHMgYW4gUzMgb3JpZ2luIHRoZSByZXF1ZXN0IHBhdGggdmVyYmF0aW0gYXMgdGhlXG4gICAgICAvLyBvYmplY3Qga2V5LCBzbyB0aGUgb25seSB2YWx1ZSB0aGF0IGNhbiBzZXJ2ZSB0aGUgYXBwIGlzIHRoZSBwcmVmaXggdGhlXG4gICAgICAvLyBhcHAgaXRzZWxmIGVtaXRzLiBUaGF0IGxlYXZlcyB0aGUgcHJvcCBubyByb29tIHRvIGRpZmZlciwgd2hpY2ggbWFrZXNcbiAgICAgIC8vIHRoZSBhcHAncyBjb25maWcgdGhlIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggd29ydGggZGVyaXZpbmcgZnJvbS5cbiAgICAgIGlmICghcHJvcCkge1xuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBtaXNtYXRjaCArXG4gICAgICAgICAgXCJDbG91ZEZyb250IHNlcnZlcyBzdGF0aWMgYXNzZXRzIHN0cmFpZ2h0IGZyb20gUzMgdXNpbmcgdGhlIHJlcXVlc3QgcGF0aCBhcyB0aGUgb2JqZWN0IGtleSwgc28gYSBtaXNtYXRjaCBtZWFucyBldmVyeSBgX25leHQvc3RhdGljYCBhbmQgYHB1YmxpYy9gIHJlcXVlc3QgNDA0cy4gXCIgK1xuICAgICAgICAgIFwiRWl0aGVyIHNldCBib3RoIHRvIHRoZSBzYW1lIHZhbHVlLCBvciBkcm9wIHRoZSBwcm9wIOKAlCBsZWZ0IHVuc2V0LCBpdCBmb2xsb3dzIHlvdXIgYXBwJ3MgYGJhc2VQYXRoYC5cIixcbiAgICAgICk7XG4gICAgY2FzZSBOZXh0anNUeXBlLlJFR0lPTkFMX0ZVTkNUSU9OUzpcbiAgICAgIC8vIERlbGliZXJhdGVseSBub3QgZGVyaXZlZDogQVBJIEdhdGV3YXkgbW91bnRzIHJlc291cmNlcyBiZWxvdyB0aGUgc3RhZ2VcbiAgICAgIC8vIGFuZCBzdHJpcHMgaXQgYmVmb3JlIGludm9raW5nIHRoZSBhcHAsIHNvIGFuIGFwcCB3aG9zZSBiYXNlUGF0aCBpcyB0aGVcbiAgICAgIC8vIHN0YWdlIG5hbWUgKG9yIGEgY3VzdG9tIGRvbWFpbiBiYXNlIHBhdGggbWFwcGluZyB0aGF0IGdldHMgc3RyaXBwZWQgdGhlXG4gICAgICAvLyBzYW1lIHdheSkgaXMgY29ycmVjdCBwcmVjaXNlbHkgYmVjYXVzZSB0aGUgcHJvcCBzdGF5cyB1bnNldC5cbiAgICAgIGlmICghcHJvcCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgLy8gVGhlIHByb3Agb25seSBoYXMgdG8gYmUgdGhlIHRhaWwgb2Ygd2hhdCB0aGUgYXBwIGVtaXRzLCBub3QgYWxsIG9mIGl0LFxuICAgICAgLy8gYmVjYXVzZSB0aGUgc3RyaXBwZWQgcHJlZml4IGlzIHBhcnQgb2YgdGhlIGFwcCdzIGBiYXNlUGF0aGAgYnV0IG5ldmVyXG4gICAgICAvLyBwYXJ0IG9mIHRoZSByZXNvdXJjZSBwYXRoOiBhbiBhcHAgYXQgdGhlIGBwcm9kYCBzdGFnZSBuZXN0ZWQgdW5kZXJcbiAgICAgIC8vIFwiL2Jhc2VcIiBzZXRzIGBiYXNlUGF0aDogXCIvcHJvZC9iYXNlXCJgIGFuZCB0aGUgcHJvcCB0byBcIi9iYXNlXCIuIENoZWNrZWRcbiAgICAgIC8vIG9uIGEgcGF0aCBib3VuZGFyeSBzbyBcIi9wcm9kL2Jhc2VcIiBkb2Vzbid0IGFjY2VwdCBhIHByb3Agb2YgXCJzZVwiLlxuICAgICAgaWYgKGNvbmZpZy5lbmRzV2l0aChgLyR7cHJvcH1gKSkge1xuICAgICAgICByZXR1cm4gcHJvcDtcbiAgICAgIH1cbiAgICAgIC8vIEFueXRoaW5nIGVsc2UgbmV2ZXIgd29ya3M6IHRoZSBwcm9wIG1vdmVzIGV2ZXJ5IHJlc291cmNlLCBpbmNsdWRpbmcgdGhlXG4gICAgICAvLyBgQU5ZYCBjYXRjaC1hbGwsIHVuZGVyIGEgcGF0aCB0aGUgYXBwIG5ldmVyIGxpbmtzIHRvLlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBtaXNtYXRjaCArXG4gICAgICAgICAgXCJUaGUgYGJhc2VQYXRoYCBwcm9wIG5lc3RzIGV2ZXJ5IEFQSSBHYXRld2F5IHJlc291cmNlIHVuZGVyIHRoYXQgcGF0aCwgaW5jbHVkaW5nIHRoZSBjYXRjaC1hbGwsIHNvIHRoZSBhcHAgaGFzIHRvIGVtaXQgaXRzIGxpbmtzIHVuZGVyIHRoZSBzYW1lIHByZWZpeCBvciBldmVyeSByZXF1ZXN0IDQwNHMuIFwiICtcbiAgICAgICAgICAnRWl0aGVyIHNldCB5b3VyIGFwcFxcJ3MgYGJhc2VQYXRoYCB0byBlbmQgd2l0aCB0aGUgcHJvcCAob3B0aW9uYWxseSBwcmVmaXhlZCBieSB0aGUgc3RhZ2Ugb3IgYmFzZSBwYXRoIG1hcHBpbmcgQVBJIEdhdGV3YXkgc3RyaXBzLCBlLmcuIGBiYXNlUGF0aDogXCIvcHJvZC9iYXNlXCJgIHdpdGggYSBwcm9wIG9mIFwiL2Jhc2VcIiksIG9yIGxlYXZlIHRoZSBwcm9wIHVuc2V0IOKAlCB1bnNldCBpcyB3aGF0IHlvdSB3YW50IHdoZW4gdGhlIGFwcFxcJ3MgYGJhc2VQYXRoYCBpcyB0aGUgQVBJIEdhdGV3YXkgc3RhZ2UgbmFtZSwgc2luY2UgdGhlIHN0YWdlIGlzblxcJ3QgcGFydCBvZiB0aGUgcmVzb3VyY2UgcGF0aC4nLFxuICAgICAgKTtcbiAgICBjYXNlIE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSUzpcbiAgICAgIC8vIFRoZSBBTEIgZm9yd2FyZHMgZXZlcnkgcGF0aCB0byB0aGUgY29udGFpbmVyLCB3aGljaCBzZXJ2ZXMgaXRzIG93blxuICAgICAgLy8gc3RhdGljIGFzc2V0cywgc28gaGVyZSBgYmFzZVBhdGhgIG9ubHkgbmFtZXNwYWNlcyB0aGUgUzMgYnVja2V0IGFuZCBoYXNcbiAgICAgIC8vIG5vIHJvdXRpbmcgbWVhbmluZyB0aGF0IGNvdWxkIGRpc2FncmVlIHdpdGggdGhlIGFwcC5cbiAgICAgIHJldHVybiBwcm9wIHx8IHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
|
|
360
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1wYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2Jhc2UtcGF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFZQSw4Q0FFQztBQU9ELHNDQUVDO0FBT0Qsd0NBR0M7QUFjRCw4REFHQztBQU9ELDRCQUVDO0FBb0JELGdEQU9DO0FBc0JELGtEQUVDO0FBMEJELHNEQWdCQztBQWlCRCwwQ0FhQztBQXVIRCwwQ0FtSEM7QUFoYUQ7Ozs7R0FJRztBQUNILDRDQUFzRDtBQUV0RDs7OztHQUlHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsUUFBaUI7SUFDakQsT0FBTyxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQixhQUFhLENBQUMsSUFBWSxFQUFFLE1BQWM7SUFDeEQsT0FBTyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQ3hFLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLFFBQWlCO0lBQzlDLE1BQU0sSUFBSSxHQUFHLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3pDLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDaEMsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0IseUJBQXlCLENBQUMsUUFBaUI7SUFDekQsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hDLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0s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RUFBMEU7WUFDMUUsd0RBQXdEO1lBQ3hELE1BQU0sSUFBSSxLQUFLLENBQ2IsUUFBUTtnQkFDTiwrS0FBK0s7Z0JBQy9LLGtWQUFrVixDQUNyVixDQUFDO1FBQ0osS0FBSyxzQkFBVSxDQUFDLG1CQUFtQjtZQUNqQyxxRUFBcUU7WUFDckUsMEVBQTBFO1lBQzFFLHVEQUF1RDtZQUN2RCxPQUFPLElBQUksSUFBSSxTQUFTLENBQUM7SUFDN0IsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFB1cmUgYGJhc2VQYXRoYCBhbmQgVVJMIHBhdGggaGVscGVycy4gTm90aGluZyBoZXJlIGltcG9ydHMgYGF3cy1jZGstbGliYCBvclxuICogdG91Y2hlcyB0aGUgZmlsZXN5c3RlbSwgc28gdGhlIGFkYXB0ZXIgYW5kIHJ1bnRpbWUgYnVuZGxlcyBjYW4gaW1wb3J0IGl0IGFzXG4gKiB3ZWxsIGFzIHRoZSBjb25zdHJ1Y3RzLlxuICovXG5pbXBvcnQgeyBMT0dfUFJFRklYLCBOZXh0anNUeXBlIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIFJlZHVjZXMgYSBgYmFzZVBhdGhgIHRvIGEgYmFyZSBwYXRoIHNlZ21lbnQgc28gdmFsdWVzIHRoYXQgYWRkcmVzcyB0aGUgc2FtZVxuICogcGF0aCAoXCIvYmFzZVwiLCBcImJhc2VcIiwgXCIvYmFzZS9cIikgY29tcGFyZSBlcXVhbCBhbmQgY2FuIGJlIGNvbmNhdGVuYXRlZFxuICogd2l0aG91dCBkb3VibGluZyBzZXBhcmF0b3JzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplQmFzZVBhdGgoYmFzZVBhdGg/OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gKGJhc2VQYXRoIHx8IFwiXCIpLnJlcGxhY2UoL15cXC8rLywgXCJcIikucmVwbGFjZSgvXFwvKyQvLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGBwYXRoYCBpcyBgcHJlZml4YCBvciB1bmRlciBpdCBvbiBhIHNlZ21lbnQgYm91bmRhcnksIHNvIGAvZG9jc2VhcmNoYFxuICogaXMgbm90IHVuZGVyIGAvZG9jc2AuIEFuIGVtcHR5IGBwcmVmaXhgIG1hdGNoZXMgbm90aGluZy4gQm90aCBzaWRlcyBtdXN0IGJlIGluXG4gKiB0aGUgc2FtZSBmb3JtIChib3RoIHdpdGggb3IgYm90aCB3aXRob3V0IHRoZSBsZWFkaW5nIGAvYCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNQYXRoUHJlZml4KHBhdGg6IHN0cmluZywgcHJlZml4OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuICEhcHJlZml4ICYmIChwYXRoID09PSBwcmVmaXggfHwgcGF0aC5zdGFydHNXaXRoKGAke3ByZWZpeH0vYCkpO1xufVxuXG4vKipcbiAqIEEgYGJhc2VQYXRoYCBhcyBOZXh0LmpzIHNwZWxscyBpdCBhbmQgVVJMcyBzdGFydCB3aXRoIGl0OiBvbmUgbGVhZGluZyBzbGFzaCxcbiAqIG5vIHRyYWlsaW5nIG9uZSAoXCIvYmFzZVwiKSwgYFwiXCJgIGZvciBub25lLiBBY2NlcHRzIGFueSBzcGVsbGluZ1xuICoge0BsaW5rIG5vcm1hbGl6ZUJhc2VQYXRofSBkb2VzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmFzZVBhdGhQcmVmaXgoYmFzZVBhdGg/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBiYXJlID0gbm9ybWFsaXplQmFzZVBhdGgoYmFzZVBhdGgpO1xuICByZXR1cm4gYmFyZSA/IGAvJHtiYXJlfWAgOiBcIlwiO1xufVxuXG4vKipcbiAqIEludmFsaWRhdGlvbiBwYXRocyBjb3ZlcmluZyBldmVyeSBVUkkgb2YgdGhlIGFwcDogd2hhdCBhIGRlcGxveSBpbnZhbGlkYXRlcyxcbiAqIGFuZCB3aGF0IHRoZSBjYWNoZSBoYW5kbGVyJ3Mgb3ZlcnNpemVkIGJhdGNoZXMsIHJldHJpZXMgYWZ0ZXIgYSBxdW90YSBlcnJvcixcbiAqIGFuZCB0YWdzIHdob3NlIHJvdXRlcyBjb3VsZCBub3QgYWxsIGJlIG5hbWVkIGZhbGwgYmFjayB0by5cbiAqXG4gKiBgLypgIGlzIHRoZSB3aG9sZSBhcHAgb25seSB3aXRob3V0IGEgYGJhc2VQYXRoYC4gYC9iYXNlLypgIG1hdGNoZXMgbmVpdGhlciB0aGVcbiAqIGFwcCdzIHJvb3QsIGAvYmFzZWAsIG5vciBpdHMgUlNDIHBheWxvYWQsIGAvYmFzZT9fcnNjPeKApmAgLSB0aGUgc2FtZSByb290IHRoZVxuICogYHJldmFsaWRhdGVQYXRoKFwiL1wiKWAgdGhhdCBvdmVyZmxvd2VkIG1heSBoYXZlIG5hbWVkIC0gc28gdGhvc2UgYXJlIHNwZWxsZWRcbiAqIG91dC4gYC9iYXNlKmAgd291bGQgY292ZXIgdGhlbSBmb3Igb25lIHdpbGRjYXJkLCBidXQgYWxzbyBldmVyeSBzaWJsaW5nXG4gKiBwcmVmaXggKGAvYmFzZTJgLCBgL2Jhc2VtZW50YCksIHdoaWNoIG1heSBiZSBhbm90aGVyIGFwcCBvbiB0aGUgc2FtZVxuICogZGlzdHJpYnV0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2hvbGVBcHBJbnZhbGlkYXRpb25QYXRocyhiYXNlUGF0aD86IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgcHJlZml4ID0gYmFzZVBhdGhQcmVmaXgoYmFzZVBhdGgpO1xuICByZXR1cm4gcHJlZml4ID8gW3ByZWZpeCwgYCR7cHJlZml4fT8qYCwgYCR7cHJlZml4fS8qYF0gOiBbXCIvKlwiXTtcbn1cblxuLyoqXG4gKiBKb2lucyBwYXRoIHBhcnRzIHdpdGggYSBzaW5nbGUgXCIvXCIsIG5vcm1hbGl6aW5nIGVhY2ggKHNvIG5vIGxlYWRpbmcgb3JcbiAqIHRyYWlsaW5nIHNsYXNoIHN1cnZpdmVzLCBpbmNsdWRpbmcgb24gdGhlIHJlc3VsdCkgYW5kIGRyb3BwaW5nIHRoZSBlbXB0eVxuICogb25lcywgc28gYW4gdW5zZXQgYGJhc2VQYXRoYCBvciBrZXkgcHJlZml4IGxlYXZlcyB0aGUgcmVzdCB1bnRvdWNoZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBqb2luUGF0aCguLi5wYXJ0czogKHN0cmluZyB8IHVuZGVmaW5lZClbXSk6IHN0cmluZyB7XG4gIHJldHVybiBwYXJ0cy5tYXAobm9ybWFsaXplQmFzZVBhdGgpLmZpbHRlcihCb29sZWFuKS5qb2luKFwiL1wiKTtcbn1cblxuLyoqXG4gKiBQcmVmaXhlcyBhbiBhYnNvbHV0ZSBhcHAgcGF0aCAoYSBoZWFsdGggY2hlY2sgcGF0aCwgc2F5KSB3aXRoIGBiYXNlUGF0aGAsXG4gKiBhbHdheXMgcmV0dXJuaW5nIGEgbGVhZGluZyBzbGFzaC4gQW4gZW1wdHkgb3IgdW5zZXQgYGJhc2VQYXRoYCBvbmx5XG4gKiBub3JtYWxpemVzIHRoYXQgbGVhZGluZyBzbGFzaC4gQW55dGhpbmcgYWZ0ZXIgdGhlIGZpcnN0IHNlZ21lbnQgaXMgcGFzc2VkXG4gKiB0aHJvdWdoIGFzIGdpdmVuLCB0cmFpbGluZyBzbGFzaCBpbmNsdWRlZCwgc2luY2UgYSBgdHJhaWxpbmdTbGFzaGAgYXBwXG4gKiBhbnN3ZXJzIFwiL2FwaS9oZWFsdGhcIiBhbmQgXCIvYXBpL2hlYWx0aC9cIiBkaWZmZXJlbnRseS5cbiAqXG4gKiBVc2UgdGhpcyBmb3IgcGF0aHMgaGFuZGVkIHRvIHNvbWV0aGluZyB0aGF0IHRhbGtzIHRvIHRoZSBhcHAgZGlyZWN0bHkg4oCUIGFuIEFMQlxuICogdGFyZ2V0IGdyb3VwIGhlYWx0aCBjaGVjaywgdGhlIGNvbnRhaW5lcidzIG93biBoZWFsdGggcHJvYmUg4oCUIHNpbmNlIHRoZSBhcHBcbiAqIG9ubHkgYW5zd2VycyB1bmRlciBpdHMgb3duIGBiYXNlUGF0aGAuXG4gKlxuICogUHJlZml4ZXMgdW5jb25kaXRpb25hbGx5LCBzbyBgcGF0aGAgaGFzIHRvIGFycml2ZSBhcyB0aGUgYXBwIHJvdXRlcyBpdCxcbiAqIHdpdGhvdXQgYGJhc2VQYXRoYDogZm9yIGFuIGFwcCBiYXNlZCBhdCBcIi9iYXNlXCIsIFwiL2Jhc2UvYXBpL2hlYWx0aFwiIGJlY29tZXNcbiAqIFwiL2Jhc2UvYmFzZS9hcGkvaGVhbHRoXCIuIERlbGliZXJhdGVseSBub3Qgc3BlY2lhbC1jYXNlZCDigJQgYW4gYXBwIGNhbiByb3V0ZVxuICogXCIvYmFzZS9iYXNlLy4uLlwiIGxlZ2l0aW1hdGVseSwgYW5kIGFjY2VwdGluZyBib3RoIHNwZWxsaW5ncyB3b3VsZCBnaXZlIHRoZVxuICogcGF0aCB0d28gbWVhbmluZ3MuIFNlZSBgZG9jcy9icmVha2luZy1jaGFuZ2VzLm1kYCAoMC42LjApLCB3aGljaCB0ZWxscyB1c2Vyc1xuICogd2hvIHByZWZpeGVkIGBoZWFsdGhDaGVja1BhdGhgIGJ5IGhhbmQgdG8gZHJvcCB0aGUgcHJlZml4LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlZml4V2l0aEJhc2VQYXRoKFxuICBiYXNlUGF0aDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBwYXRoOiBzdHJpbmcsXG4pOiBzdHJpbmcge1xuICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplQmFzZVBhdGgoYmFzZVBhdGgpO1xuICBjb25zdCBhYnNvbHV0ZSA9IHBhdGguc3RhcnRzV2l0aChcIi9cIikgPyBwYXRoIDogYC8ke3BhdGh9YDtcbiAgcmV0dXJuIG5vcm1hbGl6ZWQgPyBgLyR7bm9ybWFsaXplZH0ke2Fic29sdXRlfWAgOiBhYnNvbHV0ZTtcbn1cblxuLyoqIFdoZXRoZXIgYW4gYGFzc2V0UHJlZml4YCBuYW1lcyBhbiBvcmlnaW4gcmF0aGVyIHRoYW4gYSBwYXRoIG9uIHRoaXMgb25lLiAqL1xuZnVuY3Rpb24gaXNBYnNvbHV0ZUFzc2V0UHJlZml4KGFzc2V0UHJlZml4OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9eKFthLXpdW2EtejAtOSsuLV0qOik/XFwvXFwvL2kudGVzdChhc3NldFByZWZpeCk7XG59XG5cbi8qKlxuICogVGhlIGFwcCdzIG93biBgYXNzZXRQcmVmaXhgIGFzIGEgcGF0aCB3aXRoIGEgbGVhZGluZyBhbmQgbm8gdHJhaWxpbmcgc2xhc2hcbiAqIChcIi9jZG5cIiksIG9yIGBcIlwiYCB3aGVuIHRoZSBhcHAgc2V0cyBub25lLlxuICpcbiAqIFJldHVybnMgYFwiXCJgIGZvciBhbiBhYnNvbHV0ZSBgYXNzZXRQcmVmaXhgIChcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tXCIsIG9yIHRoZVxuICogcHJvdG9jb2wtcmVsYXRpdmUgXCIvL2Nkbi5leGFtcGxlLmNvbVwiKSB0b286IHRoYXQgbmFtZXMgYW4gb3JpZ2luIGNkay1uZXh0anNcbiAqIGRvZXMgbm90IGNvbnRyb2wsIGFuZCBpdCBpcyB0aGUgc3VwcG9ydGVkIHdheSB0byBzZXJ2ZSBhc3NldHMgZnJvbSBlbHNld2hlcmUsXG4gKiBzbyBub3RoaW5nIGFib3V0IGl0IGlzIHdvcnRoIHdhcm5pbmcgYWJvdXQuIFVzZSB7QGxpbmsgYXNzZXRQcmVmaXhQYXRofSBmb3JcbiAqIHdoYXQgdGhlICpkaXN0cmlidXRpb24qIGhhcyB0byBhbnN3ZXIgb24sIHdoaWNoIGluY2x1ZGVzIHRoZSBwYXRoIGFuIGFic29sdXRlXG4gKiBwcmVmaXggY2Fycmllcy5cbiAqXG4gKiBOZXh0LmpzIGFwcGxpZXMgYGFzc2V0UHJlZml4YCBvbiB0b3Agb2YsIG5vdCB1bmRlciwgYGJhc2VQYXRoYCwgc28gdGhlIHJlc3VsdFxuICogaXMgdGhlIHdob2xlIHByZWZpeCBvZiBhIGBfbmV4dC9zdGF0aWNgIFVSTCBhbmQgbXVzdCBub3QgYmUgam9pbmVkIHdpdGhcbiAqIGBiYXNlUGF0aGAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWxhdGl2ZUFzc2V0UHJlZml4KGFzc2V0UHJlZml4OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gaXNBYnNvbHV0ZUFzc2V0UHJlZml4KGFzc2V0UHJlZml4KSA/IFwiXCIgOiBiYXNlUGF0aFByZWZpeChhc3NldFByZWZpeCk7XG59XG5cbi8qKlxuICogV2hldGhlciBhIHBhdGgtc3R5bGUgYGFzc2V0UHJlZml4YCB3b3VsZCBnbyB1bmFuc3dlcmVkIG9uIHRoaXMgYE5leHRqc1R5cGVgLFxuICogaS5lLiB3aGV0aGVyIGV2ZXJ5IGJ1bmRsZSB3b3VsZCA0MDQuXG4gKlxuICogYGFzc2V0UHJlZml4YCBtb3ZlcyBldmVyeSBidW5kbGUgVVJMIHRvIGA8YXNzZXRQcmVmaXg+L19uZXh0L3N0YXRpYy8uLi5gIHdoaWxlXG4gKiB0aGUgb2JqZWN0cyBrZWVwIHRoZWlyIGA8YmFzZVBhdGg+L19uZXh0L3N0YXRpYy8uLi5gIFMzIGtleXMuIFRoZSBHbG9iYWxcbiAqIGBOZXh0anNUeXBlYHMgYW5zd2VyIHRoYXQgd2l0aCBhIGNhY2hlIGJlaGF2aW9yIG9mIHRoZWlyIG93blxuICogKGBOZXh0anNEaXN0cmlidXRpb25gKTsgdGhlIHJlZ2lvbmFsIG9uZXMgaGF2ZSBub3RoaW5nIHRoYXQgbWFwcyB0aGUgcHJlZml4XG4gKiBiYWNrIOKAlCBBUEkgR2F0ZXdheSdzIGBfbmV4dC9zdGF0aWNgIHJlc291cmNlIGFuZCB0aGUgY29udGFpbmVyJ3Mgb3duIGZpbGVzIGFyZVxuICogYm90aCB1bmRlciB0aGUgdW5wcmVmaXhlZCBwYXRoLlxuICpcbiAqIEEgcHJlZml4IGVxdWFsIHRvIHRoZSBhcHAncyBvd24gYGJhc2VQYXRoYCBpcyAqKm5vdCoqIHVuc2VydmVkLCBiZWNhdXNlIHRoYXQgaXNcbiAqIHRoZSB2YWx1ZSBOZXh0LmpzIHJlc29sdmVzIGBhc3NldFByZWZpeGAgdG8gd2hlbiBgYmFzZVBhdGhgIGlzIHNldCBhbmRcbiAqIGBhc3NldFByZWZpeGAgaXMgbm90OiBgLm5leHQvcmVxdWlyZWQtc2VydmVyLWZpbGVzLmpzb25gIGNvbWVzIGJhY2sgYXNcbiAqIGB7XCJhc3NldFByZWZpeFwiOlwiL3Byb2RcIixcImJhc2VQYXRoXCI6XCIvcHJvZFwifWAgZm9yIGFuIGFwcCB0aGF0IG9ubHkgZXZlciBzZXRcbiAqIGBiYXNlUGF0aGAuIFdpdGhvdXQgdGhhdCBleGVtcHRpb24gdGhlIHdhcm5pbmcgZmlyZWQgb24gZXZlcnkgcmVnaW9uYWxcbiAqIGRlcGxveW1lbnQgdGhhdCBzZXRzIGEgYGJhc2VQYXRoYCBhdCBhbGwg4oCUIGluY2x1ZGluZyBgZXhhbXBsZXMvcmVnaW9uYWwtZnVuY3Rpb25zYFxuICog4oCUIHRlbGxpbmcgdXNlcnMgdGhlaXIgYnVuZGxlcyB3b3VsZCA0MDQgYXQgdGhlIG9uZSBwYXRoIHRoYXQgZG9lcyBzZXJ2ZSB0aGVtLlxuICogYE5leHRqc0Rpc3RyaWJ1dGlvbi5yZXNvbHZlQXNzZXRQcmVmaXhgIGRyb3BzIHRoZSBwcmVmaXggZm9yIHRoZSBzYW1lIHJlYXNvbi5cbiAqXG4gKiBCb3RoIHNpZGVzIGdvIHRocm91Z2ggYG5vcm1hbGl6ZUJhc2VQYXRoYCBiZWNhdXNlIHRoZXkgYXJyaXZlIGluIGRpZmZlcmVudFxuICogc2hhcGVzOiBgbmV4dENvbmZpZ0Fzc2V0UHJlZml4YCBjYXJyaWVzIGEgbGVhZGluZyBzbGFzaCAoYFwiL3Byb2RcImApLFxuICogYG5leHRDb25maWdCYXNlUGF0aGAgZG9lcyBub3QgKGBcInByb2RcImApLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBc3NldFByZWZpeFVuc2VydmVkKFxuICBuZXh0anNUeXBlOiBOZXh0anNUeXBlLFxuICBuZXh0Q29uZmlnQXNzZXRQcmVmaXg6IHN0cmluZyxcbiAgbmV4dENvbmZpZ0Jhc2VQYXRoPzogc3RyaW5nLFxuKTogYm9vbGVhbiB7XG4gIGlmICghbmV4dENvbmZpZ0Fzc2V0UHJlZml4KSByZXR1cm4gZmFsc2U7XG4gIGlmIChcbiAgICBuZXh0anNUeXBlID09PSBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlMgfHxcbiAgICBuZXh0anNUeXBlID09PSBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gKFxuICAgIG5vcm1hbGl6ZUJhc2VQYXRoKG5leHRDb25maWdBc3NldFByZWZpeCkgIT09XG4gICAgbm9ybWFsaXplQmFzZVBhdGgobmV4dENvbmZpZ0Jhc2VQYXRoKVxuICApO1xufVxuXG4vKipcbiAqIFRoZSAqcGF0aCogZXZlcnkgYnVuZGxlIFVSTCBjYXJyaWVzLCB3aGljaGV2ZXIgZm9ybSBgYXNzZXRQcmVmaXhgIHRha2VzOiBcIi9jZG5cIlxuICogZm9yIGBhc3NldFByZWZpeDogXCIvY2RuXCJgIGFuZCBmb3IgYGFzc2V0UHJlZml4OlxuICogXCJodHRwczovL2Nkbi5leGFtcGxlLmNvbS9jZG5cImAgYWxpa2UsIGBcIlwiYCB3aGVuIHRoZXJlIGlzIG5vbmUgKGFuIGFic29sdXRlXG4gKiBwcmVmaXggd2l0aCBubyBwYXRoLCBvciBubyBwcmVmaXggYXQgYWxsKS5cbiAqXG4gKiBBbiBhYnNvbHV0ZSBwcmVmaXgncyBwYXRoIGNvdW50cyBiZWNhdXNlIGBuZXh0IGJ1aWxkYCBjb21waWxlcyBhIGBiZWZvcmVGaWxlc2BcbiAqIHJld3JpdGUgb2YgaXRzIG93biBmb3IgaXQg4oCUIGAvY2RuL19uZXh0LzpwYXRoKyDihpIgL19uZXh0LzpwYXRoK2Ag4oCUIHNvIGBuZXh0XG4gKiBzdGFydGAgc2VydmVzIGV2ZXJ5IGJ1bmRsZSB1bmRlciB0aGF0IHBhdGggYXMgd2VsbCBhcyB1bmRlciBgL19uZXh0YC4gQSBDRE5cbiAqIGZyb250aW5nIHRoaXMgZGVwbG95bWVudCBhdCB0aGF0IHBhdGggdGhlcmVmb3JlIGhhcyB0byBiZSBhbnN3ZXJlZCwgYW5kIHRoZVxuICogZGlzdHJpYnV0aW9uJ3MgYGFzc2V0UHJlZml4YCBiZWhhdmlvciBpcyB3aGF0IGFuc3dlcnMgaXQuIE1lYXN1cmVkIGFnYWluc3RcbiAqIGB0ZXN0L2UyZS9hcHAtZGlyL2Fzc2V0LXByZWZpeC1hYnNvbHV0ZWA7IHNlZSBgZG9jcy9oYXJuZXNzLWNvdmVyYWdlLm1kYC5cbiAqIFNoYXJlZCB3aXRoIGBOZXh0anNEaXN0cmlidXRpb25gLCB3aG9zZSBgYXNzZXRQcmVmaXhgIHByb3AgYSB1c2VyIGNhbiBhbHNvXG4gKiBzZXQgYnkgaGFuZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2V0UHJlZml4UGF0aChhc3NldFByZWZpeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKCFhc3NldFByZWZpeCkgcmV0dXJuIFwiXCI7XG4gIGxldCBwYXRoID0gYXNzZXRQcmVmaXg7XG4gIGlmIChpc0Fic29sdXRlQXNzZXRQcmVmaXgoYXNzZXRQcmVmaXgpKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIGAvL2Nkbi5leGFtcGxlLmNvbS9jZG5gIGlzIHByb3RvY29sLXJlbGF0aXZlLCB3aGljaCBgVVJMYCBvbmx5IHBhcnNlc1xuICAgICAgLy8gd2l0aCBhIGJhc2Ug4oCUIGFueSBiYXNlLCBzaW5jZSBvbmx5IHRoZSBwYXRoIGlzIHJlYWQgb2ZmIGl0LlxuICAgICAgcGF0aCA9IG5ldyBVUkwoYXNzZXRQcmVmaXgsIFwiaHR0cHM6Ly9hc3NldC1wcmVmaXguaW52YWxpZFwiKS5wYXRobmFtZTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYmFzZVBhdGhQcmVmaXgocGF0aCk7XG59XG5cbi8qKlxuICogVGhlIHBhdGggcHJlZml4IEFQSSBHYXRld2F5IHN0cmlwcyBiZWZvcmUgbWF0Y2hpbmcgcmVzb3VyY2VzLCBhcyBmYXIgYXMgc3ludGhcbiAqIGNhbiB0ZWxsLiBPbmx5IHJlYWQgYnkgYHJlc29sdmVCYXNlUGF0aGAgZm9yIGBSRUdJT05BTF9GVU5DVElPTlNgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwaUdhdGV3YXlQcmVmaXgge1xuICAvKipcbiAgICogVGhlIHN0YWdlIG5hbWUgb24gdGhlIGV4ZWN1dGUtYXBpIGVuZHBvaW50LCBvciB0aGUgYmFzZSBwYXRoIG1hcHBpbmcgb24gYVxuICAgKiBjdXN0b20gZG9tYWluIChgXCJcImAgd2hlbiBtYXBwZWQgYXQgdGhlIHJvb3QpLiBgdW5kZWZpbmVkYCB3aGVuIGl0IGlzIG5vdFxuICAgKiBrbm93biBhdCBzeW50aCDigJQgYSB0b2tlbiDigJQgaW4gd2hpY2ggY2FzZSBub3RoaW5nIGlzIGRlcml2ZWQuXG4gICAqL1xuICByZWFkb25seSBzdHJpcHBlZFByZWZpeD86IHN0cmluZztcbiAgLyoqIFdoZXRoZXIgYSBjdXN0b20gZG9tYWluIGlzIGNvbmZpZ3VyZWQgdGhyb3VnaCBgcmVzdEFwaVByb3BzLmRvbWFpbk5hbWVgLiAqL1xuICByZWFkb25seSBjdXN0b21Eb21haW46IGJvb2xlYW47XG59XG5cbi8qKiBgUmVzdEFwaWAncyBvd24gZGVmYXVsdHM6IHRoZSBgcHJvZGAgc3RhZ2UsIG5vIGN1c3RvbSBkb21haW4uICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9BUElfR0FURVdBWV9QUkVGSVg6IEFwaUdhdGV3YXlQcmVmaXggPSB7XG4gIHN0cmlwcGVkUHJlZml4OiBcInByb2RcIixcbiAgY3VzdG9tRG9tYWluOiBmYWxzZSxcbn07XG5cbi8qKlxuICogVGhlIHJlc291cmNlIHBhdGggYW4gYXBwJ3MgYGJhc2VQYXRoYCBuZWVkcyBvbiBgUkVHSU9OQUxfRlVOQ1RJT05TYCB3aGVuIHRoZVxuICogYGJhc2VQYXRoYCBwcm9wIGlzIHVuc2V0OiB0aGUgYXBwJ3MgYGJhc2VQYXRoYCB3aXRoIHRoZSBwcmVmaXggQVBJIEdhdGV3YXlcbiAqIHN0cmlwcyB0YWtlbiBvZmYgdGhlIGZyb250LCBvciB0aGUgd2hvbGUgb2YgaXQgd2hlbiBpdCBkb2VzIG5vdCBzdGFydCB3aXRoXG4gKiB0aGF0IHByZWZpeC5cbiAqXG4gKiBBbiBhcHAgYXQgdGhlIGBwcm9kYCBzdGFnZSBlbWl0cyBgL3Byb2QvLi4uYCBhbmQgQVBJIEdhdGV3YXkgc3RyaXBzIGAvcHJvZGBcbiAqIGJlZm9yZSBtYXRjaGluZywgc28gYGJhc2VQYXRoOiBcIi9wcm9kXCJgIG5lZWRzIHJlc291cmNlcyBhdCB0aGUgcm9vdCBhbmRcbiAqIGBiYXNlUGF0aDogXCIvcHJvZC9iYXNlXCJgIG5lZWRzIHRoZW0gdW5kZXIgYGJhc2VgLiBBbiBhcHAgd2hvc2UgYGJhc2VQYXRoYCBBUElcbiAqIEdhdGV3YXkgZG9lcyBub3Qgc3RyaXAg4oCUIGEgY3VzdG9tIGRvbWFpbiBtYXBwZWQgYXQgdGhlIHJvb3QsIHNlcnZpbmdcbiAqIGBiYXNlUGF0aDogXCIvZG9jc1wiYCDigJQgbmVlZHMgdGhlbSB1bmRlciBgZG9jc2AuIExlYXZpbmcgdGhhdCBvbmUgYXQgdGhlIHJvb3QgaXNcbiAqIHdoYXQgdXNlZCB0byBoYXBwZW46IGBfbmV4dC9zdGF0aWNgIGFuZCBgcHVibGljL2AgZmVsbCB0aHJvdWdoIHRvIHRoZVxuICogYHtwcm94eSt9YCBjYXRjaC1hbGwsIGFuZCBldmVyeSBidW5kbGUgNDA0J2Qgd2l0aCBub3RoaW5nIHNhaWQgYXQgc3ludGguXG4gKi9cbmZ1bmN0aW9uIGRlcml2ZUFwaUdhdGV3YXlCYXNlUGF0aChcbiAgY29uZmlnOiBzdHJpbmcsXG4gIHsgc3RyaXBwZWRQcmVmaXgsIGN1c3RvbURvbWFpbiB9OiBBcGlHYXRld2F5UHJlZml4LFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFjb25maWcgfHwgc3RyaXBwZWRQcmVmaXggPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3Qgc3RyaXBwZWQgPSBub3JtYWxpemVCYXNlUGF0aChzdHJpcHBlZFByZWZpeCk7XG4gIGlmIChoYXNQYXRoUHJlZml4KGNvbmZpZywgc3RyaXBwZWQpKSB7XG4gICAgcmV0dXJuIGNvbmZpZy5zbGljZShzdHJpcHBlZC5sZW5ndGggKyAxKSB8fCB1bmRlZmluZWQ7XG4gIH1cbiAgd2FyblVuc3RyaXBwZWRCYXNlUGF0aChjb25maWcsIHsgc3RyaXBwZWRQcmVmaXgsIGN1c3RvbURvbWFpbiB9KTtcbiAgcmV0dXJuIGNvbmZpZztcbn1cblxuLyoqXG4gKiBXYXJuIHRoYXQgYW4gYXBwIG1vdW50ZWQgdW5kZXIgaXRzIHdob2xlIGBiYXNlUGF0aGAgaXMgc2VydmVkIHNvbWV3aGVyZSBpdHNcbiAqIG93biBsaW5rcyBkb24ndCByZWFjaCwgd2hlbiBBUEkgR2F0ZXdheSBzdHJpcHMgYSBwcmVmaXggdGhhdCBgYmFzZVBhdGhgIGxhY2tzLlxuICogQm90aCB3YXlzIG9mIGFycml2aW5nIHRoZXJlIHdhcm46IHRoZSBwcm9wIGxlZnQgdW5zZXQgKGRlcml2ZWQgdG8gdGhlIHdob2xlXG4gKiBgYmFzZVBhdGhgKSBhbmQgdGhlIHByb3Agc2V0IHRvIHRoZSBzYW1lIHZhbHVlLlxuICovXG5mdW5jdGlvbiB3YXJuVW5zdHJpcHBlZEJhc2VQYXRoKFxuICBjb25maWc6IHN0cmluZyxcbiAgeyBzdHJpcHBlZFByZWZpeCwgY3VzdG9tRG9tYWluIH06IEFwaUdhdGV3YXlQcmVmaXgsXG4pOiB2b2lkIHtcbiAgY29uc3Qgc3RyaXBwZWQgPSBub3JtYWxpemVCYXNlUGF0aChzdHJpcHBlZFByZWZpeCk7XG4gIGlmIChzdHJpcHBlZFByZWZpeCA9PT0gdW5kZWZpbmVkIHx8ICFzdHJpcHBlZCkge1xuICAgIC8vIEEgdG9rZW4sIG9yIGEgY3VzdG9tIGRvbWFpbiBtYXBwZWQgYXQgdGhlIHJvb3Q6IG5vdGhpbmcgaXMgc3RyaXBwZWQgdGhhdFxuICAgIC8vIHRoZSBhcHAncyBsaW5rcyBjb3VsZCBtaXNzLlxuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY3VzdG9tRG9tYWluKSB7XG4gICAgLy8gVGhlIHNhbWUgbWlzcyB0aHJvdWdoIGEgY3VzdG9tIGRvbWFpbidzIGJhc2UgcGF0aCBtYXBwaW5nOiBzZXJ2ZWQgYXRcbiAgICAvLyBgLzxtYXBwaW5nPi88YmFzZVBhdGg+YCwgbGlua2luZyB0byBgLzxiYXNlUGF0aD4vLi4uYCwgd2hpY2ggbm8gbWFwcGluZ1xuICAgIC8vIGNvdmVycy5cbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBgJHtMT0dfUFJFRklYfSB5b3VyIE5leHQuanMgYXBwJ3MgXFxgYmFzZVBhdGhcXGAgaXMgJHtxdW90ZShjb25maWcpfSwgd2hpY2ggZG9lcyBub3Qgc3RhcnQgd2l0aCB0aGUgY3VzdG9tIGRvbWFpbidzIGJhc2UgcGF0aCBtYXBwaW5nIFwiLyR7c3RyaXBwZWR9XCIuIGAgK1xuICAgICAgICBcIkl0cyBsaW5rcyBhbmQgYnVuZGxlIFVSTHMgd2lsbCBiZSByZXF1ZXN0ZWQgd2l0aG91dCB0aGUgbWFwcGluZywgd2hpY2ggdGhlIGN1c3RvbSBkb21haW4gYW5zd2VycyB3aXRoIDQwMy4gXCIgK1xuICAgICAgICBgU2V0IFxcYGJhc2VQYXRoOiBcIi8ke2pvaW5QYXRoKHN0cmlwcGVkLCBjb25maWcpfVwiXFxgIGluIHlvdXIgbmV4dC5jb25maWcsIG9yIG1hcCB0aGUgZG9tYWluIGF0IHRoZSByb290LmAsXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBSZXNvdXJjZXMgdW5kZXIgdGhlIGFwcCdzIGJhc2VQYXRoIHNlcnZlIGl0IGF0IGAvPHN0YWdlPi88YmFzZVBhdGg+YCwgYnV0XG4gICAgLy8gdGhlIGFwcCdzIG93biBsaW5rcyBhcmUgYC88YmFzZVBhdGg+Ly4uLmAsIHdoaWNoIG1pc3NlcyB0aGUgc3RhZ2UuIEFcbiAgICAvLyB3YXJuaW5nLCBub3QgYW4gZXJyb3I6IGEgZG9tYWluIGF0dGFjaGVkIGFmdGVyIHN5bnRoIChgYWRkRG9tYWluTmFtZWApXG4gICAgLy8gbWFrZXMgaXQgcmlnaHQsIGFuZCBzeW50aCBjYW5ub3Qgc2VlIHRoYXQuXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYCR7TE9HX1BSRUZJWH0geW91ciBOZXh0LmpzIGFwcCdzIFxcYGJhc2VQYXRoXFxgIGlzICR7cXVvdGUoY29uZmlnKX0sIHdoaWNoIGRvZXMgbm90IHN0YXJ0IHdpdGggdGhlIEFQSSBHYXRld2F5IHN0YWdlIFwiLyR7c3RyaXBwZWR9XCIuIGAgK1xuICAgICAgICBcIkl0cyBsaW5rcyBhbmQgYnVuZGxlIFVSTHMgd2lsbCBiZSByZXF1ZXN0ZWQgd2l0aG91dCB0aGUgc3RhZ2UsIHdoaWNoIHRoZSBleGVjdXRlLWFwaSBlbmRwb2ludCBhbnN3ZXJzIHdpdGggNDAzLiBcIiArXG4gICAgICAgIGBTZXQgXFxgYmFzZVBhdGg6IFwiLyR7am9pblBhdGgoc3RyaXBwZWQsIGNvbmZpZyl9XCJcXGAgaW4geW91ciBuZXh0LmNvbmZpZywgb3Igc2VydmUgdGhlIGFwcCBmcm9tIGEgY3VzdG9tIGRvbWFpbiBtYXBwZWQgYXQgdGhlIHJvb3QuYCxcbiAgICApO1xuICB9XG59XG5cbi8qKiBXaGV0aGVyIEFQSSBHYXRld2F5IHN0cmlwcyB0aGUgZnJvbnQgb2YgYGJhc2VQYXRoYCBiZWZvcmUgbWF0Y2hpbmcgcmVzb3VyY2VzLiAqL1xuZnVuY3Rpb24gc3RhcnRzV2l0aFN0cmlwcGVkUHJlZml4KFxuICBiYXNlUGF0aDogc3RyaW5nLFxuICB7IHN0cmlwcGVkUHJlZml4IH06IEFwaUdhdGV3YXlQcmVmaXgsXG4pOiBib29sZWFuIHtcbiAgY29uc3Qgc3RyaXBwZWQgPSBub3JtYWxpemVCYXNlUGF0aChzdHJpcHBlZFByZWZpeCk7XG4gIHJldHVybiAhIWJhc2VQYXRoICYmIGhhc1BhdGhQcmVmaXgoYmFzZVBhdGgsIHN0cmlwcGVkKTtcbn1cblxuZnVuY3Rpb24gcXVvdGUoYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBiYXNlUGF0aCA/IGBcIi8ke2Jhc2VQYXRofVwiYCA6IFwidW5zZXRcIjtcbn1cblxuLyoqXG4gKiBTZXR0bGVzIG9uIHRoZSBzaW5nbGUgYGJhc2VQYXRoYCB0aGUgaW5mcmFzdHJ1Y3R1cmUgc2hvdWxkIGJlIGJ1aWx0IGFyb3VuZCxcbiAqIGdpdmVuIHRoZSBDREsgYGJhc2VQYXRoYCBwcm9wIGFuZCB0aGUgTmV4dC5qcyBhcHAncyBvd24gYGJhc2VQYXRoYFxuICogKGBOZXh0anNCdWlsZC5uZXh0Q29uZmlnQmFzZVBhdGhgKSwgdGhyb3dpbmcgYXQgc3ludGggaWYgdGhlIHR3byBjYW4ndCBzZXJ2ZVxuICogdGhlIGFwcCB0b2dldGhlci4gUmV0dXJucyBhIG5vcm1hbGl6ZWQgdmFsdWUsIG9yIGB1bmRlZmluZWRgIGZvciBub1xuICogYGJhc2VQYXRoYCBhdCBhbGw7IGNvbnN1bWVycyB0aGF0IG5lZWQgYSBsZWFkaW5nIHNsYXNoIGFkZCB0aGVpciBvd24uXG4gKlxuICogVGhlIHR3byBpbnB1dHMgYXJlIGdlbnVpbmVseSBkaWZmZXJlbnQgdGhpbmdzIOKAlCB0aGUgcHJvcCBpcyB3aGVyZSB0aGVcbiAqIGluZnJhc3RydWN0dXJlIHNlcnZlcyB0aGUgYXBwIGZyb20gKGFuZCB3aGljaCBTMyBrZXkgcHJlZml4IHRoZSBzdGF0aWMgYXNzZXRzXG4gKiBsYW5kIHVuZGVyKSwgdGhlIGNvbmZpZyBpcyB0aGUgcHJlZml4IHRoZSBhcHAgZW1pdHMgaXRzIG93biBsaW5rcyBhbmQgYXNzZXRcbiAqIGhyZWZzIHVuZGVyIOKAlCBzbyBob3cgc3RyaWN0bHkgdGhleSBoYXZlIHRvIGxpbmUgdXAsIGFuZCB3aGV0aGVyIG9uZSBjYW4gc3RhbmRcbiAqIGluIGZvciB0aGUgb3RoZXIsIGRlcGVuZHMgb24gaG93IHRoZSBgTmV4dGpzVHlwZWAgcm91dGVzIHN0YXRpYyByZXF1ZXN0cy5cbiAqXG4gKiBgYXBpR2F0ZXdheWAgaXMgb25seSByZWFkIGZvciBgUkVHSU9OQUxfRlVOQ1RJT05TYCwgYW5kIG9ubHkgd2hlbiB0aGUgcHJvcCBpc1xuICogdW5zZXQ6IHNlZSBgZGVyaXZlQXBpR2F0ZXdheUJhc2VQYXRoYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVCYXNlUGF0aChcbiAgbmV4dGpzVHlwZTogTmV4dGpzVHlwZSxcbiAgcHJvcEJhc2VQYXRoPzogc3RyaW5nLFxuICBuZXh0Q29uZmlnQmFzZVBhdGg/OiBzdHJpbmcsXG4gIGFwaUdhdGV3YXk6IEFwaUdhdGV3YXlQcmVmaXggPSBERUZBVUxUX0FQSV9HQVRFV0FZX1BSRUZJWCxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHByb3AgPSBub3JtYWxpemVCYXNlUGF0aChwcm9wQmFzZVBhdGgpO1xuICBjb25zdCBjb25maWcgPSBub3JtYWxpemVCYXNlUGF0aChuZXh0Q29uZmlnQmFzZVBhdGgpO1xuICBjb25zdCBtaXNtYXRjaCA9XG4gICAgYCR7TE9HX1BSRUZJWH0gYmFzZVBhdGggbWlzbWF0Y2ggZm9yIE5leHRqc1R5cGUuJHtuZXh0anNUeXBlfTogdGhlIFxcYGJhc2VQYXRoXFxgIHByb3AgaXMgJHtxdW90ZShwcm9wKX0gYCArXG4gICAgYGJ1dCB5b3VyIE5leHQuanMgYXBwJ3MgY29uZmlnIHNldHMgXFxgYmFzZVBhdGhcXGAgdG8gJHtxdW90ZShjb25maWcpfS4gYDtcbiAgaWYgKHByb3AgPT09IGNvbmZpZykge1xuICAgIGlmIChcbiAgICAgIG5leHRqc1R5cGUgPT09IE5leHRqc1R5cGUuUkVHSU9OQUxfRlVOQ1RJT05TICYmXG4gICAgICBzdGFydHNXaXRoU3RyaXBwZWRQcmVmaXgocHJvcCwgYXBpR2F0ZXdheSlcbiAgICApIHtcbiAgICAgIC8vIEFncmVlaW5nIGlzIG5vdCBlbm91Z2ggaGVyZTogQVBJIEdhdGV3YXkgc3RyaXBzIHRoZSBzdGFnZSAob3IgYmFzZSBwYXRoXG4gICAgICAvLyBtYXBwaW5nKSBiZWZvcmUgbWF0Y2hpbmcsIHNvIHJlc291cmNlcyB1bmRlciB0aGUgcHJvcCdzIFwicHJvZFwiIGFyZSBvbmx5XG4gICAgICAvLyByZWFjaGVkIGF0IGAvcHJvZC9wcm9kLy4uLmAsIGFuZCBldmVyeSBsaW5rIHRoZSBhcHAgZW1pdHMgNDAzcy5cbiAgICAgIGNvbnN0IHByb2JsZW0gPVxuICAgICAgICBgQVBJIEdhdGV3YXkgc3RyaXBzIFwiLyR7bm9ybWFsaXplQmFzZVBhdGgoYXBpR2F0ZXdheS5zdHJpcHBlZFByZWZpeCl9XCIgYmVmb3JlIG1hdGNoaW5nIHJlc291cmNlcywgc28gYSBwcm9wIHRoYXQgcmVwZWF0cyBpdCBuZXN0cyBldmVyeSByZXNvdXJjZSB1bmRlciBhIHBhdGggbm8gcmVxdWVzdCByZWFjaGVzLiBgICtcbiAgICAgICAgXCJMZWF2ZSB0aGUgcHJvcCB1bnNldDogaXQgaXMgZGVyaXZlZCBmcm9tIHlvdXIgYXBwJ3MgYGJhc2VQYXRoYCB3aXRoIHRoYXQgcHJlZml4IHRha2VuIG9mZi5cIjtcbiAgICAgIGlmIChhcGlHYXRld2F5LmN1c3RvbURvbWFpbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWlzbWF0Y2ggKyBwcm9ibGVtKTtcbiAgICAgIH1cbiAgICAgIC8vIE9uIHRoZSBleGVjdXRlLWFwaSBlbmRwb2ludCB0aGF0IGlzIGNlcnRhaW4sIGJ1dCBhbiBleHBsaWNpdCBwcm9wIHdpbnM6XG4gICAgICAvLyBhIGRvbWFpbiBhdHRhY2hlZCB3aXRoIGBhZGREb21haW5OYW1lKClgLCBpbnZpc2libGUgaGVyZSwgY2FuIG1hcCB0aGVcbiAgICAgIC8vIHN0YWdlIGF0IGl0cyByb290LCBhbmQgdGhlbiBgL3Byb2QvLi4uYCBkb2VzIHJlYWNoIHJlc291cmNlcyB1bmRlclxuICAgICAgLy8gXCJwcm9kXCIuXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIG1pc21hdGNoICtcbiAgICAgICAgICBwcm9ibGVtICtcbiAgICAgICAgICBcIiAoSWdub3JlIHRoaXMgaWYgYSBkb21haW4gYXR0YWNoZWQgd2l0aCBgYWRkRG9tYWluTmFtZSgpYCBzZXJ2ZXMgdGhlIGFwcCB3aXRob3V0IHN0cmlwcGluZyB0aGF0IHByZWZpeC4pXCIsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHByb3A7XG4gICAgfVxuICAgIGlmIChuZXh0anNUeXBlID09PSBOZXh0anNUeXBlLlJFR0lPTkFMX0ZVTkNUSU9OUyAmJiBwcm9wKSB7XG4gICAgICAvLyBBZ3JlZWluZyB0aGUgb3RoZXIgd2F5IHJvdW5kIGhhcyB0aGUgdW5zZXQgY2FzZSdzIHByb2JsZW06IHJlc291cmNlc1xuICAgICAgLy8gdW5kZXIgXCJkb2NzXCIgYXJlIHJlYWNoZWQgYXQgYC9wcm9kL2RvY3MvLi4uYCwgdGhlIGFwcCBsaW5rcyB0b1xuICAgICAgLy8gYC9kb2NzLy4uLmAuXG4gICAgICB3YXJuVW5zdHJpcHBlZEJhc2VQYXRoKGNvbmZpZywgYXBpR2F0ZXdheSk7XG4gICAgfVxuICAgIHJldHVybiBwcm9wIHx8IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHN3aXRjaCAobmV4dGpzVHlwZSkge1xuICAgIGNhc2UgTmV4dGpzVHlwZS5HTE9CQUxfRlVOQ1RJT05TOlxuICAgIGNhc2UgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSUzpcbiAgICAgIC8vIGBOZXh0anNEaXN0cmlidXRpb25gIGJ1aWxkcyBpdHMgYmVoYXZpb3JzIGFzIGAvJHtiYXNlUGF0aH0vX25leHQvc3RhdGljKmBcbiAgICAgIC8vIGFuZCBDbG91ZEZyb250IGhhbmRzIGFuIFMzIG9yaWdpbiB0aGUgcmVxdWVzdCBwYXRoIHZlcmJhdGltIGFzIHRoZVxuICAgICAgLy8gb2JqZWN0IGtleSwgc28gdGhlIG9ubHkgdmFsdWUgdGhhdCBjYW4gc2VydmUgdGhlIGFwcCBpcyB0aGUgcHJlZml4IHRoZVxuICAgICAgLy8gYXBwIGl0c2VsZiBlbWl0cy4gVGhhdCBsZWF2ZXMgdGhlIHByb3Agbm8gcm9vbSB0byBkaWZmZXIsIHdoaWNoIG1ha2VzXG4gICAgICAvLyB0aGUgYXBwJ3MgY29uZmlnIHRoZSBzaW5nbGUgc291cmNlIG9mIHRydXRoIHdvcnRoIGRlcml2aW5nIGZyb20uXG4gICAgICBpZiAoIXByb3ApIHtcbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgbWlzbWF0Y2ggK1xuICAgICAgICAgIFwiQ2xvdWRGcm9udCBzZXJ2ZXMgc3RhdGljIGFzc2V0cyBzdHJhaWdodCBmcm9tIFMzIHVzaW5nIHRoZSByZXF1ZXN0IHBhdGggYXMgdGhlIG9iamVjdCBrZXksIHNvIGEgbWlzbWF0Y2ggbWVhbnMgZXZlcnkgYF9uZXh0L3N0YXRpY2AgYW5kIGBwdWJsaWMvYCByZXF1ZXN0IDQwNHMuIFwiICtcbiAgICAgICAgICBcIkVpdGhlciBzZXQgYm90aCB0byB0aGUgc2FtZSB2YWx1ZSwgb3IgZHJvcCB0aGUgcHJvcCDigJQgbGVmdCB1bnNldCwgaXQgZm9sbG93cyB5b3VyIGFwcCdzIGBiYXNlUGF0aGAuXCIsXG4gICAgICApO1xuICAgIGNhc2UgTmV4dGpzVHlwZS5SRUdJT05BTF9GVU5DVElPTlM6XG4gICAgICBpZiAoIXByb3ApIHtcbiAgICAgICAgLy8gQSBwcm9wIHRoYXQgaXMgc2V0IGJ1dCBuYW1lcyBubyBwYXRoIChcIi9cIikgaXMgYW4gZXhwbGljaXQgcm9vdFxuICAgICAgICAvLyBtb3VudCwgbm90IFwidW5zZXRcIjogaXQgaXMgaG93IGFuIGFwcCBzYXlzIHRoZSBwcmVmaXggaXMgc3RyaXBwZWQgYnlcbiAgICAgICAgLy8gc29tZXRoaW5nIHN5bnRoIGNhbid0IHNlZSDigJQgYSBkb21haW4gYXR0YWNoZWQgbGF0ZXIgd2l0aFxuICAgICAgICAvLyBgYWRkRG9tYWluTmFtZSh7IGJhc2VQYXRoIH0pYCwgc2F5IOKAlCBzbyBkZXJpdmluZyBoZXJlIHdvdWxkIG5lc3QgdGhlXG4gICAgICAgIC8vIHJlc291cmNlcyB1bmRlciBhIHBhdGggdGhlIHN0cmlwcGVkIHJlcXVlc3RzIG5ldmVyIHJlYWNoLlxuICAgICAgICBpZiAocHJvcEJhc2VQYXRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkZXJpdmVBcGlHYXRld2F5QmFzZVBhdGgoY29uZmlnLCBhcGlHYXRld2F5KTtcbiAgICAgIH1cbiAgICAgIC8vIFRoZSBwcm9wIG9ubHkgaGFzIHRvIGJlIHRoZSB0YWlsIG9mIHdoYXQgdGhlIGFwcCBlbWl0cywgbm90IGFsbCBvZiBpdCxcbiAgICAgIC8vIGJlY2F1c2UgdGhlIHN0cmlwcGVkIHByZWZpeCBpcyBwYXJ0IG9mIHRoZSBhcHAncyBgYmFzZVBhdGhgIGJ1dCBuZXZlclxuICAgICAgLy8gcGFydCBvZiB0aGUgcmVzb3VyY2UgcGF0aDogYW4gYXBwIGF0IHRoZSBgcHJvZGAgc3RhZ2UgbmVzdGVkIHVuZGVyXG4gICAgICAvLyBcIi9iYXNlXCIgc2V0cyBgYmFzZVBhdGg6IFwiL3Byb2QvYmFzZVwiYCBhbmQgdGhlIHByb3AgdG8gXCIvYmFzZVwiLiBFeGFjdGx5XG4gICAgICAvLyB0aGUgc3RyaXBwZWQgcHJlZml4IGFuZCB0aGVuIHRoZSBwcm9wLCBub3QgYW55IHRhaWw6IHdpdGggYSBwcm9wIG9mXG4gICAgICAvLyBcIi9iYXNlXCIgYW4gYXBwIGF0IFwiL2Zvby9iYXNlXCIgaXMgc2VydmVkIGF0IGAvcHJvZC9iYXNlLy4uLmAgYW5kIGxpbmtzXG4gICAgICAvLyB0byBgL2Zvby9iYXNlLy4uLmAsIHdoaWNoIDQwM3MuIE9ubHkgYSB0b2tlbiBzdGFnZSwgd2hpY2ggc3ludGggY2FuJ3RcbiAgICAgIC8vIHJlYWQsIGZhbGxzIGJhY2sgdG8gYSB0YWlsIG9uIGEgcGF0aCBib3VuZGFyeS5cbiAgICAgIGlmIChcbiAgICAgICAgYXBpR2F0ZXdheS5zdHJpcHBlZFByZWZpeCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyBjb25maWcuZW5kc1dpdGgoYC8ke3Byb3B9YClcbiAgICAgICAgICA6IGNvbmZpZyA9PT0gam9pblBhdGgoYXBpR2F0ZXdheS5zdHJpcHBlZFByZWZpeCwgcHJvcClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gcHJvcDtcbiAgICAgIH1cbiAgICAgIC8vIEFueSB0YWlsIG9uIGEgcGF0aCBib3VuZGFyeSBpcyBhbHNvIHdoYXQgYSBkb21haW4gYXR0YWNoZWQgd2l0aFxuICAgICAgLy8gYGFkZERvbWFpbk5hbWUoeyBiYXNlUGF0aDogXCJ2MVwiIH0pYCBuZWVkcyBmb3IgYW4gYXBwIGF0IFwiL3YxL2Jhc2VcIjpcbiAgICAgIC8vIHN5bnRoIG9ubHkgc2VlcyB0aGUgc3RhZ2UsIHNvIGl0IGNhbid0IHRlbGwgdGhhdCBzZXR1cCBmcm9tIGEgbWlzdGFrZS5cbiAgICAgIC8vIEFuIGV4cGxpY2l0IHByb3Agd2lucywgc28gdGhhdCB3YXJuczsgYSBjdXN0b20gZG9tYWluIGNvbmZpZ3VyZWQgaW5cbiAgICAgIC8vIGByZXN0QXBpUHJvcHMuZG9tYWluTmFtZWAgaXMgdmlzaWJsZSwgc28gdGhlcmUgaXQgc3RpbGwgdGhyb3dzIGJlbG93LlxuICAgICAgaWYgKCFhcGlHYXRld2F5LmN1c3RvbURvbWFpbiAmJiBjb25maWcuZW5kc1dpdGgoYC8ke3Byb3B9YCkpIHtcbiAgICAgICAgY29uc3QgbGVhZGluZyA9IGNvbmZpZy5zbGljZSgwLCAtcHJvcC5sZW5ndGggLSAxKTtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGAke0xPR19QUkVGSVh9IHRoZSBcXGBiYXNlUGF0aFxcYCBwcm9wIGlzICR7cXVvdGUocHJvcCl9IGFuZCB5b3VyIE5leHQuanMgYXBwJ3MgXFxgYmFzZVBhdGhcXGAgaXMgJHtxdW90ZShjb25maWcpfSwgYCArXG4gICAgICAgICAgICBgc28gdGhlIGFwcCBpcyBzZXJ2ZWQgYXQgXCIvJHtqb2luUGF0aChub3JtYWxpemVCYXNlUGF0aChhcGlHYXRld2F5LnN0cmlwcGVkUHJlZml4KSwgcHJvcCl9XCIgb24gdGhlIGV4ZWN1dGUtYXBpIGVuZHBvaW50IGFuZCBsaW5rcyB0byBcIi8ke2NvbmZpZ31cIi4gYCArXG4gICAgICAgICAgICBgVGhhdCBvbmx5IHdvcmtzIHRocm91Z2ggYSBjdXN0b20gZG9tYWluIHdob3NlIGJhc2UgcGF0aCBtYXBwaW5nIHN0cmlwcyBcIi8ke2xlYWRpbmd9XCIgKFxcYGFkZERvbWFpbk5hbWUoeyBiYXNlUGF0aDogXCIke2xlYWRpbmd9XCIgfSlcXGApOyBvdGhlcndpc2UgZXZlcnkgcmVxdWVzdCA0MDNzLmAsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBwcm9wO1xuICAgICAgfVxuICAgICAgLy8gQW55dGhpbmcgZWxzZSBuZXZlciB3b3JrczogdGhlIHByb3AgbW92ZXMgZXZlcnkgcmVzb3VyY2UsIGluY2x1ZGluZyB0aGVcbiAgICAgIC8vIGBBTllgIGNhdGNoLWFsbCwgdW5kZXIgYSBwYXRoIHRoZSBhcHAgbmV2ZXIgbGlua3MgdG8uXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIG1pc21hdGNoICtcbiAgICAgICAgICBcIlRoZSBgYmFzZVBhdGhgIHByb3AgbmVzdHMgZXZlcnkgQVBJIEdhdGV3YXkgcmVzb3VyY2UgdW5kZXIgdGhhdCBwYXRoLCBpbmNsdWRpbmcgdGhlIGNhdGNoLWFsbCwgc28gdGhlIGFwcCBoYXMgdG8gZW1pdCBpdHMgbGlua3MgdW5kZXIgdGhlIHNhbWUgcHJlZml4IG9yIGV2ZXJ5IHJlcXVlc3QgNDA0cy4gXCIgK1xuICAgICAgICAgICdFaXRoZXIgc2V0IHlvdXIgYXBwXFwncyBgYmFzZVBhdGhgIHRvIHRoZSBwcm9wLCBvciB0byB0aGUgcHJvcCBwcmVmaXhlZCBieSB0aGUgc3RhZ2Ugb3IgYmFzZSBwYXRoIG1hcHBpbmcgQVBJIEdhdGV3YXkgc3RyaXBzIChlLmcuIGBiYXNlUGF0aDogXCIvcHJvZC9iYXNlXCJgIHdpdGggYSBwcm9wIG9mIFwiL2Jhc2VcIiksIG9yIGxlYXZlIHRoZSBwcm9wIHVuc2V0IOKAlCB1bnNldCBpcyB3aGF0IHlvdSB3YW50IHdoZW4gdGhlIGFwcFxcJ3MgYGJhc2VQYXRoYCBpcyB0aGUgQVBJIEdhdGV3YXkgc3RhZ2UgbmFtZSwgc2luY2UgdGhlIHN0YWdlIGlzblxcJ3QgcGFydCBvZiB0aGUgcmVzb3VyY2UgcGF0aC4nLFxuICAgICAgKTtcbiAgICBjYXNlIE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSUzpcbiAgICAgIC8vIFRoZSBBTEIgZm9yd2FyZHMgZXZlcnkgcGF0aCB0byB0aGUgY29udGFpbmVyLCB3aGljaCBzZXJ2ZXMgaXRzIG93blxuICAgICAgLy8gc3RhdGljIGFzc2V0cywgc28gaGVyZSBgYmFzZVBhdGhgIG9ubHkgbmFtZXNwYWNlcyB0aGUgUzMgYnVja2V0IGFuZCBoYXNcbiAgICAgIC8vIG5vIHJvdXRpbmcgbWVhbmluZyB0aGF0IGNvdWxkIGRpc2FncmVlIHdpdGggdGhlIGFwcC5cbiAgICAgIHJldHVybiBwcm9wIHx8IHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
|