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/nextjs-api.test.js
CHANGED
|
@@ -6,7 +6,26 @@ const assertions_1 = require("aws-cdk-lib/assertions");
|
|
|
6
6
|
const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
|
|
7
7
|
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
8
8
|
const aws_s3_1 = require("aws-cdk-lib/aws-s3");
|
|
9
|
+
const function_groups_1 = require("./adapter/function-groups");
|
|
9
10
|
const nextjs_api_1 = require("./nextjs-api");
|
|
11
|
+
/**
|
|
12
|
+
* `functionGroups` and the `functionGroupBehaviors` the build would record for
|
|
13
|
+
* them: `routes` as routed (an optional catch-all's parent listed by hand),
|
|
14
|
+
* with data-URL behaviors for a group that owns a Pages Router page.
|
|
15
|
+
*/
|
|
16
|
+
function grouped(groups) {
|
|
17
|
+
return {
|
|
18
|
+
functionGroups: groups.map(({ name, function: fn }) => ({
|
|
19
|
+
name,
|
|
20
|
+
function: fn,
|
|
21
|
+
})),
|
|
22
|
+
functionGroupBehaviors: groups.flatMap((group) => group.routes.flatMap((route) => (0, function_groups_1.pathPatternsFor)(route, {
|
|
23
|
+
hasDataRoutes: group.hasDataRoutes ?? false,
|
|
24
|
+
trailingSlash: group.trailingSlash,
|
|
25
|
+
buildId: "abc123",
|
|
26
|
+
}).map((pattern) => ({ group: group.name, route, pattern })))),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
10
29
|
describe("NextjsApi", () => {
|
|
11
30
|
let stack;
|
|
12
31
|
beforeEach(() => {
|
|
@@ -61,6 +80,46 @@ describe("NextjsApi", () => {
|
|
|
61
80
|
createApi("/branch-x/");
|
|
62
81
|
expect(s3IntegrationKeys()).toContain("branch-x/_next/static/{key}");
|
|
63
82
|
});
|
|
83
|
+
/** The statements of the API Gateway → S3 integration role's policy. */
|
|
84
|
+
function staticIntegrationStatements() {
|
|
85
|
+
const policies = assertions_1.Template.fromStack(stack).findResources("AWS::IAM::Policy", {
|
|
86
|
+
Properties: {
|
|
87
|
+
Roles: [{ Ref: assertions_1.Match.stringLikeRegexp("StaticIntegrationRole") }],
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
return Object.values(policies).flatMap((policy) => policy.Properties.PolicyDocument.Statement);
|
|
91
|
+
}
|
|
92
|
+
it("scopes the S3 integration role to the static assets key prefix", () => {
|
|
93
|
+
// A shared bucket holds other apps' assets under their own prefixes.
|
|
94
|
+
createApi("/branch-x/");
|
|
95
|
+
const bucketArn = {
|
|
96
|
+
"Fn::Join": ["", ["arn:", { Ref: "AWS::Partition" }, ":s3:::my-bucket"]],
|
|
97
|
+
};
|
|
98
|
+
expect(staticIntegrationStatements()).toEqual([
|
|
99
|
+
{
|
|
100
|
+
Action: "s3:GetObject",
|
|
101
|
+
Effect: "Allow",
|
|
102
|
+
Resource: {
|
|
103
|
+
"Fn::Join": [
|
|
104
|
+
"",
|
|
105
|
+
["arn:", { Ref: "AWS::Partition" }, ":s3:::my-bucket/branch-x/*"],
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
// Unconditioned: S3 checks it during a GetObject, with no `s3:prefix`.
|
|
111
|
+
Action: "s3:ListBucket",
|
|
112
|
+
Effect: "Allow",
|
|
113
|
+
Resource: bucketArn,
|
|
114
|
+
},
|
|
115
|
+
]);
|
|
116
|
+
});
|
|
117
|
+
it("lets the S3 integration role read the whole bucket without a key prefix", () => {
|
|
118
|
+
createApi();
|
|
119
|
+
const statements = staticIntegrationStatements();
|
|
120
|
+
expect(statements).toHaveLength(2);
|
|
121
|
+
expect(statements[0].Resource["Fn::Join"][1]).toContain(":s3:::my-bucket/*");
|
|
122
|
+
});
|
|
64
123
|
it("keeps the key prefix independent of basePath, which is the URL prefix", () => {
|
|
65
124
|
// A NextjsRegionalFunctions app whose `basePath` matches the API Gateway
|
|
66
125
|
// stage still has its assets at the bucket root.
|
|
@@ -78,6 +137,51 @@ describe("NextjsApi", () => {
|
|
|
78
137
|
// ...served under the stage-matching URL prefix.
|
|
79
138
|
assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::ApiGateway::Resource", { PathPart: "prod" });
|
|
80
139
|
});
|
|
140
|
+
// API Gateway path parts can't contain "/", so a nested basePath passed whole
|
|
141
|
+
// to `addResource` fails CDK's `validateResourcePathPart` at synth. It's
|
|
142
|
+
// reachable: `resolveBasePath` accepts a nested prop for REGIONAL_FUNCTIONS as
|
|
143
|
+
// long as the app's basePath ends with it.
|
|
144
|
+
describe("nested basePath", () => {
|
|
145
|
+
function pathParts() {
|
|
146
|
+
const resources = assertions_1.Template.fromStack(stack).findResources("AWS::ApiGateway::Resource");
|
|
147
|
+
return Object.values(resources).map((resource) => resource.Properties.PathPart);
|
|
148
|
+
}
|
|
149
|
+
function createApiWithBasePath(basePath) {
|
|
150
|
+
return new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
151
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
152
|
+
basePath,
|
|
153
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
154
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
155
|
+
handler: "index.handler",
|
|
156
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
157
|
+
}),
|
|
158
|
+
publicDirEntries: [],
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
it("creates one resource per segment", () => {
|
|
162
|
+
expect(() => createApiWithBasePath("/team/app")).not.toThrow();
|
|
163
|
+
expect(pathParts()).toEqual(expect.arrayContaining(["team", "app", "_next", "{proxy+}"]));
|
|
164
|
+
// Not the unsplit value, which API Gateway would reject.
|
|
165
|
+
expect(pathParts()).not.toContain("team/app");
|
|
166
|
+
});
|
|
167
|
+
it("nests the segments so the app is reachable under the full path", () => {
|
|
168
|
+
createApiWithBasePath("/team/app");
|
|
169
|
+
const resources = assertions_1.Template.fromStack(stack).findResources("AWS::ApiGateway::Resource");
|
|
170
|
+
const byPathPart = Object.fromEntries(Object.entries(resources).map(([logicalId, resource]) => [
|
|
171
|
+
resource.Properties.PathPart,
|
|
172
|
+
{ logicalId, parentId: resource.Properties.ParentId },
|
|
173
|
+
]));
|
|
174
|
+
// "app" hangs off "team", not off the API root.
|
|
175
|
+
expect(byPathPart.app.parentId).toEqual({
|
|
176
|
+
Ref: byPathPart.team.logicalId,
|
|
177
|
+
});
|
|
178
|
+
expect(byPathPart.team.parentId).toHaveProperty("Fn::GetAtt");
|
|
179
|
+
});
|
|
180
|
+
it("still creates a single resource for a flat basePath", () => {
|
|
181
|
+
createApiWithBasePath("/base");
|
|
182
|
+
expect(pathParts()).toContain("base");
|
|
183
|
+
});
|
|
184
|
+
});
|
|
81
185
|
describe("url", () => {
|
|
82
186
|
function createApiWithOverrides(props = {}) {
|
|
83
187
|
return new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
@@ -140,5 +244,482 @@ describe("NextjsApi", () => {
|
|
|
140
244
|
}))).toBe("https://{NextjsApiRestApiCustomDomain}/team-a");
|
|
141
245
|
});
|
|
142
246
|
});
|
|
247
|
+
describe("functionGroups resource tree", () => {
|
|
248
|
+
/** Lambda functions that `ANY` on the resource at `pathPart` invokes. */
|
|
249
|
+
function anyTargets(pathPart) {
|
|
250
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
251
|
+
const resources = template.findResources("AWS::ApiGateway::Resource", {
|
|
252
|
+
Properties: { PathPart: pathPart },
|
|
253
|
+
});
|
|
254
|
+
const ids = Object.keys(resources);
|
|
255
|
+
expect(ids).toHaveLength(1);
|
|
256
|
+
const methods = template.findResources("AWS::ApiGateway::Method", {
|
|
257
|
+
Properties: { HttpMethod: "ANY", ResourceId: { Ref: ids[0] } },
|
|
258
|
+
});
|
|
259
|
+
return Object.values(methods).map((method) => JSON.stringify(method.Properties.Integration.Uri).match(/(ServerFn|GroupFn|ReportsFn)[A-F0-9]+/)[1]);
|
|
260
|
+
}
|
|
261
|
+
it("sends a group's parent paths to the default function", () => {
|
|
262
|
+
// API Gateway answers a methodless resource with 403 rather than falling
|
|
263
|
+
// back to the root `{proxy+}`, so `/api` and `/api/reports` need one.
|
|
264
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
265
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
266
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
267
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
268
|
+
handler: "index.handler",
|
|
269
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
270
|
+
}),
|
|
271
|
+
publicDirEntries: [],
|
|
272
|
+
...grouped([
|
|
273
|
+
{
|
|
274
|
+
name: "reports",
|
|
275
|
+
routes: ["/api/reports/**", "/api/export"],
|
|
276
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
277
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
278
|
+
handler: "index.handler",
|
|
279
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
280
|
+
}),
|
|
281
|
+
},
|
|
282
|
+
]),
|
|
283
|
+
});
|
|
284
|
+
expect(anyTargets("api")).toEqual(["ServerFn"]);
|
|
285
|
+
expect(anyTargets("reports")).toEqual(["ServerFn"]);
|
|
286
|
+
expect(anyTargets("export")).toEqual(["GroupFn"]);
|
|
287
|
+
});
|
|
288
|
+
it("sends a parent under another group's subtree to that group", () => {
|
|
289
|
+
// `assignRoutesToGroups` packages `/api/reports` into `api`, and
|
|
290
|
+
// CloudFront's `api/*` sends it there; so must API Gateway.
|
|
291
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
292
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
293
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
294
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
295
|
+
handler: "index.handler",
|
|
296
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
297
|
+
}),
|
|
298
|
+
publicDirEntries: [],
|
|
299
|
+
...grouped([
|
|
300
|
+
{
|
|
301
|
+
name: "api",
|
|
302
|
+
routes: ["/api/**"],
|
|
303
|
+
hasDataRoutes: true,
|
|
304
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
305
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
306
|
+
handler: "index.handler",
|
|
307
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
308
|
+
}),
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: "reports",
|
|
312
|
+
routes: ["/api/reports/q1/**"],
|
|
313
|
+
hasDataRoutes: true,
|
|
314
|
+
function: new aws_lambda_1.Function(stack, "ReportsFn", {
|
|
315
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
316
|
+
handler: "index.handler",
|
|
317
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
318
|
+
}),
|
|
319
|
+
},
|
|
320
|
+
]),
|
|
321
|
+
});
|
|
322
|
+
// Each path part below appears twice, under `/` and under the data
|
|
323
|
+
// prefix, so check the tree by path.
|
|
324
|
+
const targets = anyTargetsByPath();
|
|
325
|
+
expect(targets["/api"]).toEqual(["ServerFn"]);
|
|
326
|
+
expect(targets["/api/reports"]).toEqual(["GroupFn"]);
|
|
327
|
+
expect(targets["/api/reports/q1"]).toEqual(["GroupFn"]);
|
|
328
|
+
expect(targets["/api/reports/q1/{proxy+}"]).toEqual(["ReportsFn"]);
|
|
329
|
+
expect(targets["/_next/data/{buildId}/api/reports"]).toEqual(["GroupFn"]);
|
|
330
|
+
expect(targets["/_next/data/{buildId}"]).toEqual(["ServerFn"]);
|
|
331
|
+
});
|
|
332
|
+
function createGroupedApi(hasDataRoutes) {
|
|
333
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
334
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
335
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
336
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
337
|
+
handler: "index.handler",
|
|
338
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
339
|
+
}),
|
|
340
|
+
publicDirEntries: [],
|
|
341
|
+
...grouped([
|
|
342
|
+
{
|
|
343
|
+
name: "reports",
|
|
344
|
+
routes: ["/reports/**", "/docs/intro"],
|
|
345
|
+
hasDataRoutes,
|
|
346
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
347
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
348
|
+
handler: "index.handler",
|
|
349
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
350
|
+
}),
|
|
351
|
+
},
|
|
352
|
+
]),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
/** Every resource path in the API, e.g. `/_next/data/{buildId}/x.json`. */
|
|
356
|
+
function resourcePaths() {
|
|
357
|
+
const resources = assertions_1.Template.fromStack(stack).findResources("AWS::ApiGateway::Resource");
|
|
358
|
+
const pathOf = (id) => {
|
|
359
|
+
const { ParentId, PathPart } = resources[id].Properties;
|
|
360
|
+
const parent = ParentId.Ref;
|
|
361
|
+
return parent && resources[parent]
|
|
362
|
+
? `${pathOf(parent)}/${PathPart}`
|
|
363
|
+
: `/${PathPart}`;
|
|
364
|
+
};
|
|
365
|
+
return Object.keys(resources).map(pathOf).sort();
|
|
366
|
+
}
|
|
367
|
+
/** Resource path → the Lambda functions `ANY` on it invokes. */
|
|
368
|
+
function anyTargetsByPath() {
|
|
369
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
370
|
+
const resources = template.findResources("AWS::ApiGateway::Resource");
|
|
371
|
+
const pathOf = (id) => {
|
|
372
|
+
const { ParentId, PathPart } = resources[id].Properties;
|
|
373
|
+
const parent = ParentId.Ref;
|
|
374
|
+
return parent && resources[parent]
|
|
375
|
+
? `${pathOf(parent)}/${PathPart}`
|
|
376
|
+
: `/${PathPart}`;
|
|
377
|
+
};
|
|
378
|
+
const methods = template.findResources("AWS::ApiGateway::Method", {
|
|
379
|
+
Properties: { HttpMethod: "ANY" },
|
|
380
|
+
});
|
|
381
|
+
const targets = {};
|
|
382
|
+
for (const method of Object.values(methods)) {
|
|
383
|
+
const id = method.Properties.ResourceId?.Ref;
|
|
384
|
+
if (!id || !resources[id])
|
|
385
|
+
continue;
|
|
386
|
+
(targets[pathOf(id)] ??= []).push(JSON.stringify(method.Properties.Integration.Uri).match(/(ServerFn|GroupFn|ReportsFn)[A-F0-9]+/)[1]);
|
|
387
|
+
}
|
|
388
|
+
return targets;
|
|
389
|
+
}
|
|
390
|
+
it("routes a group's Pages Router data URLs to it too", () => {
|
|
391
|
+
createGroupedApi(true);
|
|
392
|
+
const paths = resourcePaths();
|
|
393
|
+
expect(paths).toContain("/_next/data/{buildId}/reports/{proxy+}");
|
|
394
|
+
expect(paths).toContain("/_next/data/{buildId}/docs/intro.json");
|
|
395
|
+
expect(anyTargets("intro.json")).toEqual(["GroupFn"]);
|
|
396
|
+
// A methodless parent answers 403, so the data prefix needs the default.
|
|
397
|
+
expect(anyTargets("{buildId}")).toEqual(["ServerFn"]);
|
|
398
|
+
});
|
|
399
|
+
it("keeps each group's data URLs to its own subtree (A)", () => {
|
|
400
|
+
// `{buildId}` is one path segment, where CloudFront's `*` crossed `/`:
|
|
401
|
+
// `/_next/data/<id>/docs/blog/x.json` has no way into blog's resource.
|
|
402
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
403
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
404
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
405
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
406
|
+
handler: "index.handler",
|
|
407
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
408
|
+
}),
|
|
409
|
+
publicDirEntries: [],
|
|
410
|
+
...grouped([
|
|
411
|
+
{
|
|
412
|
+
name: "blog",
|
|
413
|
+
routes: ["/blog/**"],
|
|
414
|
+
hasDataRoutes: true,
|
|
415
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
416
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
417
|
+
handler: "index.handler",
|
|
418
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
419
|
+
}),
|
|
420
|
+
},
|
|
421
|
+
]),
|
|
422
|
+
});
|
|
423
|
+
expect(resourcePaths().filter((path) => path.startsWith("/_next/data"))).toEqual([
|
|
424
|
+
"/_next/data",
|
|
425
|
+
"/_next/data/{buildId}",
|
|
426
|
+
"/_next/data/{buildId}/blog",
|
|
427
|
+
"/_next/data/{buildId}/blog/{proxy+}",
|
|
428
|
+
]);
|
|
429
|
+
});
|
|
430
|
+
it("routes an optional catch-all's parent to the group when it is listed (B)", () => {
|
|
431
|
+
// The build routes `/shop` alongside `/shop/**` when the group owns
|
|
432
|
+
// `shop/[[...slug]]` (see `routedPatterns`): `{proxy+}` does not match
|
|
433
|
+
// the parent, which would otherwise reach the default function.
|
|
434
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
435
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
436
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
437
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
438
|
+
handler: "index.handler",
|
|
439
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
440
|
+
}),
|
|
441
|
+
publicDirEntries: [],
|
|
442
|
+
...grouped([
|
|
443
|
+
{
|
|
444
|
+
name: "shop",
|
|
445
|
+
routes: ["/shop/**", "/shop"],
|
|
446
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
447
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
448
|
+
handler: "index.handler",
|
|
449
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
450
|
+
}),
|
|
451
|
+
},
|
|
452
|
+
]),
|
|
453
|
+
});
|
|
454
|
+
expect(anyTargets("shop")).toEqual(["GroupFn"]);
|
|
455
|
+
});
|
|
456
|
+
it.each([
|
|
457
|
+
[{ name: "docs", isDirectory: true }, "/docs/**", "directory"],
|
|
458
|
+
[{ name: "docs", isDirectory: true }, "/docs/guide/**", "directory"],
|
|
459
|
+
[{ name: "robots.txt", isDirectory: false }, "/robots.txt", "file"],
|
|
460
|
+
])("rejects a group route on a public/ entry's resource: %p with %p (E)", (entry, route, kind) => {
|
|
461
|
+
expect(() => new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
462
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
463
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
464
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
465
|
+
handler: "index.handler",
|
|
466
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
467
|
+
}),
|
|
468
|
+
publicDirEntries: [entry],
|
|
469
|
+
...grouped([
|
|
470
|
+
{
|
|
471
|
+
name: "g",
|
|
472
|
+
routes: [route],
|
|
473
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
474
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
475
|
+
handler: "index.handler",
|
|
476
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
477
|
+
}),
|
|
478
|
+
},
|
|
479
|
+
]),
|
|
480
|
+
})).toThrow(`overlaps the top-level public/ ${kind} "${entry.name}"`);
|
|
481
|
+
});
|
|
482
|
+
it("allows an exact route named like a public/ directory, which is not under it", () => {
|
|
483
|
+
expect(() => new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
484
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
485
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
486
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
487
|
+
handler: "index.handler",
|
|
488
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
489
|
+
}),
|
|
490
|
+
publicDirEntries: [{ name: "docs", isDirectory: true }],
|
|
491
|
+
...grouped([
|
|
492
|
+
{
|
|
493
|
+
name: "g",
|
|
494
|
+
routes: ["/docs"],
|
|
495
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
496
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
497
|
+
handler: "index.handler",
|
|
498
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
499
|
+
}),
|
|
500
|
+
},
|
|
501
|
+
]),
|
|
502
|
+
})).not.toThrow();
|
|
503
|
+
});
|
|
504
|
+
it("routes an exact route's trailingSlash form through its one resource", () => {
|
|
505
|
+
// CloudFront needs `pricing/` as a behavior of its own; API Gateway
|
|
506
|
+
// matches `/pricing/` on the `pricing` resource, so the variant adds
|
|
507
|
+
// nothing here and must not add the resource twice.
|
|
508
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
509
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
510
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
511
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
512
|
+
handler: "index.handler",
|
|
513
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
514
|
+
}),
|
|
515
|
+
publicDirEntries: [],
|
|
516
|
+
...grouped([
|
|
517
|
+
{
|
|
518
|
+
name: "pricing",
|
|
519
|
+
routes: ["/pricing"],
|
|
520
|
+
trailingSlash: true,
|
|
521
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
522
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
523
|
+
handler: "index.handler",
|
|
524
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
525
|
+
}),
|
|
526
|
+
},
|
|
527
|
+
]),
|
|
528
|
+
});
|
|
529
|
+
expect(resourcePaths().filter((path) => !path.startsWith("/_next/static"))).toEqual(["/_next", "/pricing", "/{proxy+}"]);
|
|
530
|
+
expect(anyTargetsByPath()).toEqual({
|
|
531
|
+
"/pricing": ["GroupFn"],
|
|
532
|
+
"/{proxy+}": ["ServerFn"],
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
it("rejects a behavior for a group it was not given", () => {
|
|
536
|
+
const { functionGroupBehaviors } = grouped([
|
|
537
|
+
{
|
|
538
|
+
name: "api",
|
|
539
|
+
routes: ["/api/**"],
|
|
540
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
541
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
542
|
+
handler: "index.handler",
|
|
543
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
544
|
+
}),
|
|
545
|
+
},
|
|
546
|
+
]);
|
|
547
|
+
expect(() => new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
548
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
549
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
550
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
551
|
+
handler: "index.handler",
|
|
552
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
553
|
+
}),
|
|
554
|
+
publicDirEntries: [],
|
|
555
|
+
functionGroupBehaviors,
|
|
556
|
+
})).toThrow(/routes to function group "api", which is not in/);
|
|
557
|
+
});
|
|
558
|
+
it("adds no data routes for an app without Pages Router routes", () => {
|
|
559
|
+
createGroupedApi(false);
|
|
560
|
+
expect(resourcePaths().filter((path) => path.startsWith("/_next/data"))).toEqual([]);
|
|
561
|
+
});
|
|
562
|
+
it("grants each function one API-scoped permission, not two per method", () => {
|
|
563
|
+
// Per-method permissions put two statements in the function's resource
|
|
564
|
+
// policy for every `ANY`, which outgrows Lambda's 20 KB cap.
|
|
565
|
+
createGroupedApi(true);
|
|
566
|
+
const permissions = Object.values(assertions_1.Template.fromStack(stack).findResources("AWS::Lambda::Permission", {
|
|
567
|
+
Properties: { Principal: "apigateway.amazonaws.com" },
|
|
568
|
+
}));
|
|
569
|
+
expect(permissions).toHaveLength(2);
|
|
570
|
+
for (const permission of permissions) {
|
|
571
|
+
const sourceArn = JSON.stringify(permission.Properties.SourceArn);
|
|
572
|
+
expect(sourceArn).toContain(":execute-api:");
|
|
573
|
+
expect(sourceArn).toContain("/*/*/*");
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
it("names the group and pattern API Gateway cannot route", () => {
|
|
578
|
+
expect(() => new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
579
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
580
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
581
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
582
|
+
handler: "index.handler",
|
|
583
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
584
|
+
}),
|
|
585
|
+
publicDirEntries: [],
|
|
586
|
+
...grouped([
|
|
587
|
+
{
|
|
588
|
+
name: "about",
|
|
589
|
+
routes: ["/about~us"],
|
|
590
|
+
function: new aws_lambda_1.Function(stack, "GroupFn", {
|
|
591
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
592
|
+
handler: "index.handler",
|
|
593
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
594
|
+
}),
|
|
595
|
+
},
|
|
596
|
+
]),
|
|
597
|
+
})).toThrow(/pattern "\/about~us" \(group "about"\) has a segment/);
|
|
598
|
+
});
|
|
599
|
+
describe("a public/ entry API Gateway cannot address", () => {
|
|
600
|
+
it("warns and skips it instead of failing the synth", () => {
|
|
601
|
+
// `public/hello world.jpg` is a valid Next.js asset that `addResource`
|
|
602
|
+
// rejects outright, taking the whole app's synth with it. The Global types
|
|
603
|
+
// serve it with a wildcard path pattern; here the honest outcome is one
|
|
604
|
+
// 404ing asset and a warning that names it.
|
|
605
|
+
const api = new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
606
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
607
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
608
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
609
|
+
handler: "index.handler",
|
|
610
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
611
|
+
}),
|
|
612
|
+
publicDirEntries: [
|
|
613
|
+
{ name: "hello world.jpg", isDirectory: false },
|
|
614
|
+
{ name: "äöüščří.png", isDirectory: false },
|
|
615
|
+
{ name: "favicon.ico", isDirectory: false },
|
|
616
|
+
],
|
|
617
|
+
});
|
|
618
|
+
const message = assertions_1.Annotations.fromStack(stack)
|
|
619
|
+
.findWarning(`/${api.node.path}`, assertions_1.Match.anyValue())
|
|
620
|
+
.map((warning) => warning.entry.data)
|
|
621
|
+
.join("\n");
|
|
622
|
+
expect(message).toContain('"hello world.jpg"');
|
|
623
|
+
expect(message).toContain('"äöüščří.png"');
|
|
624
|
+
expect(message).not.toContain('"favicon.ico"');
|
|
625
|
+
// The expressible one is still served.
|
|
626
|
+
expect(s3IntegrationKeys()).toContain("favicon.ico");
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
describe("NextjsApi redeploy after update", () => {
|
|
631
|
+
function synth(props = {}) {
|
|
632
|
+
const stack = new aws_cdk_lib_1.Stack(new aws_cdk_lib_1.App(), "TestStack", {
|
|
633
|
+
env: { account: "123456789012", region: "us-east-1" },
|
|
634
|
+
});
|
|
635
|
+
new nextjs_api_1.NextjsApi(stack, "NextjsApi", {
|
|
636
|
+
staticAssetsBucket: aws_s3_1.Bucket.fromBucketName(stack, "Bucket", "my-bucket"),
|
|
637
|
+
serverFunction: new aws_lambda_1.Function(stack, "ServerFn", {
|
|
638
|
+
runtime: aws_lambda_1.Runtime.NODEJS_22_X,
|
|
639
|
+
handler: "index.handler",
|
|
640
|
+
code: aws_lambda_1.Code.fromInline("exports.handler = async () => {};"),
|
|
641
|
+
}),
|
|
642
|
+
publicDirEntries: [],
|
|
643
|
+
...props,
|
|
644
|
+
});
|
|
645
|
+
return assertions_1.Template.fromStack(stack);
|
|
646
|
+
}
|
|
647
|
+
/** The `Fn::Join` parts of every resource the redeploy role is granted. */
|
|
648
|
+
function grantedResources(template) {
|
|
649
|
+
const [policy] = Object.values(template.findResources("AWS::IAM::Policy", {
|
|
650
|
+
Properties: {
|
|
651
|
+
PolicyName: assertions_1.Match.stringLikeRegexp("RedeployFn"),
|
|
652
|
+
},
|
|
653
|
+
}));
|
|
654
|
+
return policy.Properties.PolicyDocument.Statement.map((statement) => ({
|
|
655
|
+
action: statement.Action,
|
|
656
|
+
resources: JSON.stringify(statement.Resource),
|
|
657
|
+
}));
|
|
658
|
+
}
|
|
659
|
+
it("redeploys the stage on this stack's UPDATE_COMPLETE", () => {
|
|
660
|
+
const template = synth();
|
|
661
|
+
template.hasResourceProperties("AWS::Events::Rule", {
|
|
662
|
+
EventPattern: {
|
|
663
|
+
source: ["aws.cloudformation"],
|
|
664
|
+
"detail-type": ["CloudFormation Stack Status Change"],
|
|
665
|
+
detail: {
|
|
666
|
+
"stack-id": [{ Ref: "AWS::StackId" }],
|
|
667
|
+
"status-details": {
|
|
668
|
+
status: ["UPDATE_COMPLETE", "UPDATE_ROLLBACK_COMPLETE"],
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
Targets: [
|
|
673
|
+
assertions_1.Match.objectLike({
|
|
674
|
+
Arn: { "Fn::GetAtt": [assertions_1.Match.stringLikeRegexp("RedeployFn"), "Arn"] },
|
|
675
|
+
}),
|
|
676
|
+
],
|
|
677
|
+
});
|
|
678
|
+
template.hasResourceProperties("AWS::Lambda::Function", {
|
|
679
|
+
Handler: "index.handler",
|
|
680
|
+
Environment: {
|
|
681
|
+
Variables: {
|
|
682
|
+
REST_API_ID: { Ref: assertions_1.Match.stringLikeRegexp("RestApi") },
|
|
683
|
+
STAGE_NAME: { Ref: assertions_1.Match.stringLikeRegexp("DeploymentStage") },
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
it("scopes its API Gateway access to this REST API", () => {
|
|
689
|
+
const statements = grantedResources(synth());
|
|
690
|
+
expect(statements.map((s) => s.action)).toEqual([
|
|
691
|
+
"apigateway:POST",
|
|
692
|
+
"apigateway:GET",
|
|
693
|
+
"apigateway:DELETE",
|
|
694
|
+
]);
|
|
695
|
+
for (const { resources } of statements) {
|
|
696
|
+
expect(resources).toContain("/restapis/");
|
|
697
|
+
expect(resources).toMatch(/"Ref":"NextjsApiRestApi[0-9A-F]+"/);
|
|
698
|
+
expect(resources).not.toMatch(/restapis\/\*/);
|
|
699
|
+
}
|
|
700
|
+
expect(statements[0].resources).toContain("/deployments");
|
|
701
|
+
expect(statements[2].resources).toContain("/deployments/*");
|
|
702
|
+
});
|
|
703
|
+
it("is off when redeployAfterUpdate is false", () => {
|
|
704
|
+
const template = synth({ redeployAfterUpdate: false });
|
|
705
|
+
template.resourceCountIs("AWS::Events::Rule", 0);
|
|
706
|
+
});
|
|
707
|
+
it("is off when the API deploys no stage", () => {
|
|
708
|
+
const template = synth({
|
|
709
|
+
overrides: { restApiProps: { deploy: false } },
|
|
710
|
+
});
|
|
711
|
+
template.resourceCountIs("AWS::Events::Rule", 0);
|
|
712
|
+
});
|
|
713
|
+
it("takes function overrides", () => {
|
|
714
|
+
const template = synth({
|
|
715
|
+
overrides: { redeployFunctionProps: { memorySize: 512 } },
|
|
716
|
+
});
|
|
717
|
+
template.hasResourceProperties("AWS::Lambda::Function", {
|
|
718
|
+
MemorySize: 512,
|
|
719
|
+
Environment: {
|
|
720
|
+
Variables: { REST_API_ID: assertions_1.Match.anyValue() },
|
|
721
|
+
},
|
|
722
|
+
});
|
|
723
|
+
});
|
|
143
724
|
});
|
|
144
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWFwaS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25leHRqcy1hcGkudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHNEQUFzRDtBQUN0RCw2Q0FBeUM7QUFDekMsdURBQWtEO0FBQ2xELCtFQUFpRTtBQUNqRSx1REFJZ0M7QUFDaEMsK0NBQTRDO0FBQzVDLDZDQUF5RDtBQUV6RCxRQUFRLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRTtJQUN6QixJQUFJLEtBQVksQ0FBQztJQUVqQixVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsS0FBSyxHQUFHLElBQUksbUJBQUssQ0FBQyxJQUFJLGlCQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUU7WUFDeEMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFO1NBQ3RELENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsU0FBUyxTQUFTLENBQUMscUJBQThCO1FBQy9DLE9BQU8sSUFBSSxzQkFBUyxDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUU7WUFDdkMsa0JBQWtCLEVBQUUsZUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQztZQUN2RSxxQkFBcUI7WUFDckIsY0FBYyxFQUFFLElBQUkscUJBQWMsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFO2dCQUNwRCxPQUFPLEVBQUUsb0JBQU8sQ0FBQyxXQUFXO2dCQUM1QixPQUFPLEVBQUUsZUFBZTtnQkFDeEIsSUFBSSxFQUFFLGlCQUFJLENBQUMsVUFBVSxDQUFDLG1DQUFtQyxDQUFDO2FBQzNELENBQUM7WUFDRixnQkFBZ0IsRUFBRTtnQkFDaEIsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUU7Z0JBQzNDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFO2FB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InNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llcyAqL1xuaW1wb3J0IHsgQXBwLCBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXNzZXJ0aW9uc1wiO1xuaW1wb3J0IHsgQ2VydGlmaWNhdGUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlclwiO1xuaW1wb3J0IHtcbiAgQ29kZSxcbiAgRnVuY3Rpb24gYXMgTGFtYmRhRnVuY3Rpb24sXG4gIFJ1bnRpbWUsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBOZXh0anNBcGksIE5leHRqc0FwaVByb3BzIH0gZnJvbSBcIi4vbmV4dGpzLWFwaVwiO1xuXG5kZXNjcmliZShcIk5leHRqc0FwaVwiLCAoKSA9PiB7XG4gIGxldCBzdGFjazogU3RhY2s7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgc3RhY2sgPSBuZXcgU3RhY2sobmV3IEFwcCgpLCBcIlRlc3RTdGFja1wiLCB7XG4gICAgICBlbnY6IHsgYWNjb3VudDogXCIxMjM0NTY3ODkwMTJcIiwgcmVnaW9uOiBcInVzLWVhc3QtMVwiIH0sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZUFwaShzdGF0aWNBc3NldHNLZXlQcmVmaXg/OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IE5leHRqc0FwaShzdGFjaywgXCJOZXh0anNBcGlcIiwge1xuICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgc3RhdGljQXNzZXRzS2V5UHJlZml4LFxuICAgICAgc2VydmVyRnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJTZXJ2ZXJGblwiLCB7XG4gICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICB9KSxcbiAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtcbiAgICAgICAgeyBuYW1lOiBcImZhdmljb24uaWNvXCIsIGlzRGlyZWN0b3J5OiBmYWxzZSB9LFxuICAgICAgICB7IG5hbWU6IFwiaW1hZ2VzXCIsIGlzRGlyZWN0b3J5OiB0cnVlIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBTMyBpbnRlZ3JhdGlvbnMgYWRkcmVzcyBvYmplY3RzIGJ5IGtleSwgc28gdGhlIHVwbG9hZGVkIGtleSBwcmVmaXggaGFzXG4gICAqIHRvIGFwcGVhciBpbiB0aGUgaW50ZWdyYXRpb24gVVJJIG9yIGV2ZXJ5IHN0YXRpYyByZXF1ZXN0IDQwNHMuXG4gICAqL1xuICBmdW5jdGlvbiBzM0ludGVncmF0aW9uS2V5cygpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgbWV0aG9kcyA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjaykuZmluZFJlc291cmNlcyhcbiAgICAgIFwiQVdTOjpBcGlHYXRld2F5OjpNZXRob2RcIixcbiAgICApO1xuICAgIGNvbnN0IG1hcmtlciA9IFwiczM6cGF0aC9teS1idWNrZXQvXCI7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXMobWV0aG9kcylcbiAgICAgIC5mbGF0TWFwKChtZXRob2QpID0+IG1ldGhvZC5Qcm9wZXJ0aWVzLkludGVncmF0aW9uLlVyaVtcIkZuOjpKb2luXCJdWzFdKVxuICAgICAgLmZpbHRlcihcbiAgICAgICAgKHBhcnQ6IHVua25vd24pOiBwYXJ0IGlzIHN0cmluZyA9PlxuICAgICAgICAgIHR5cGVvZiBwYXJ0ID09PSBcInN0cmluZ1wiICYmIHBhcnQuaW5jbHVkZXMobWFya2VyKSxcbiAgICAgIClcbiAgICAgIC5tYXAoKHBhcnQpID0+IHBhcnQuc3BsaXQobWFya2VyKVsxXSk7XG4gIH1cblxuICBpdChcImFkZHJlc3NlcyBvYmplY3RzIGF0IHRoZSBidWNrZXQgcm9vdCB3aGVuIG5vIGtleSBwcmVmaXggaXMgc2V0XCIsICgpID0+IHtcbiAgICBjcmVhdGVBcGkoKTtcblxuICAgIGV4cGVjdChzM0ludGVncmF0aW9uS2V5cygpLnNvcnQoKSkudG9FcXVhbChbXG4gICAgICBcIl9uZXh0L3N0YXRpYy97a2V5fVwiLFxuICAgICAgXCJmYXZpY29uLmljb1wiLFxuICAgICAgXCJpbWFnZXMve2tleX1cIixcbiAgICBdKTtcbiAgfSk7XG5cbiAgaXQoXCJwcmVmaXhlcyBldmVyeSBTMyBpbnRlZ3JhdGlvbiBrZXkgd2l0aCB0aGUgc3RhdGljIGFzc2V0cyBrZXkgcHJlZml4XCIsICgpID0+IHtcbiAgICBjcmVhdGVBcGkoXCJicmFuY2gteFwiKTtcblxuICAgIGV4cGVjdChzM0ludGVncmF0aW9uS2V5cygpLnNvcnQoKSkudG9FcXVhbChbXG4gICAgICBcImJyYW5jaC14L19uZXh0L3N0YXRpYy97a2V5fVwiLFxuICAgICAgXCJicmFuY2gteC9mYXZpY29uLmljb1wiLFxuICAgICAgXCJicmFuY2gteC9pbWFnZXMve2tleX1cIixcbiAgICBdKTtcbiAgfSk7XG5cbiAgaXQoXCJub3JtYWxpemVzIHN1cnJvdW5kaW5nIHNsYXNoZXMgb24gdGhlIGtleSBwcmVmaXhcIiwgKCkgPT4ge1xuICAgIGNyZWF0ZUFwaShcIi9icmFuY2gteC9cIik7XG5cbiAgICBleHBlY3QoczNJbnRlZ3JhdGlvbktleXMoKSkudG9Db250YWluKFwiYnJhbmNoLXgvX25leHQvc3RhdGljL3trZXl9XCIpO1xuICB9KTtcblxuICBpdChcImtlZXBzIHRoZSBrZXkgcHJlZml4IGluZGVwZW5kZW50IG9mIGJhc2VQYXRoLCB3aGljaCBpcyB0aGUgVVJMIHByZWZpeFwiLCAoKSA9PiB7XG4gICAgLy8gQSBOZXh0anNSZWdpb25hbEZ1bmN0aW9ucyBhcHAgd2hvc2UgYGJhc2VQYXRoYCBtYXRjaGVzIHRoZSBBUEkgR2F0ZXdheVxuICAgIC8vIHN0YWdlIHN0aWxsIGhhcyBpdHMgYXNzZXRzIGF0IHRoZSBidWNrZXQgcm9vdC5cbiAgICBuZXcgTmV4dGpzQXBpKHN0YWNrLCBcIk5leHRqc0FwaVwiLCB7XG4gICAgICBzdGF0aWNBc3NldHNCdWNrZXQ6IEJ1Y2tldC5mcm9tQnVja2V0TmFtZShzdGFjaywgXCJCdWNrZXRcIiwgXCJteS1idWNrZXRcIiksXG4gICAgICBiYXNlUGF0aDogXCIvcHJvZFwiLFxuICAgICAgc2VydmVyRnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJTZXJ2ZXJGblwiLCB7XG4gICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICB9KSxcbiAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtdLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHMzSW50ZWdyYXRpb25LZXlzKCkpLnRvRXF1YWwoW1wiX25leHQvc3RhdGljL3trZXl9XCJdKTtcbiAgICAvLyAuLi5zZXJ2ZWQgdW5kZXIgdGhlIHN0YWdlLW1hdGNoaW5nIFVSTCBwcmVmaXguXG4gICAgVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXG4gICAgICBcIkFXUzo6QXBpR2F0ZXdheTo6UmVzb3VyY2VcIixcbiAgICAgIHsgUGF0aFBhcnQ6IFwicHJvZFwiIH0sXG4gICAgKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJ1cmxcIiwgKCkgPT4ge1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUFwaVdpdGhPdmVycmlkZXMoXG4gICAgICBwcm9wczogUGFydGlhbDxOZXh0anNBcGlQcm9wcz4gPSB7fSxcbiAgICApOiBOZXh0anNBcGkge1xuICAgICAgcmV0dXJuIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgfSksXG4gICAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtdLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbWFpbk5hbWUoYmFzZVBhdGg/OiBzdHJpbmcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRvbWFpbk5hbWU6IFwiYXBwLmV4YW1wbGUuY29tXCIsXG4gICAgICAgIGNlcnRpZmljYXRlOiBDZXJ0aWZpY2F0ZS5mcm9tQ2VydGlmaWNhdGVBcm4oXG4gICAgICAgICAgc3RhY2ssXG4gICAgICAgICAgXCJDZXJ0XCIsXG4gICAgICAgICAgXCJhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlL2FiY1wiLFxuICAgICAgICApLFxuICAgICAgICBiYXNlUGF0aCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIFJFU1QgQVBJIGlkLCB0aGUgc3RhZ2UgbmFtZSBhbmQgdGhlIGRvbWFpbiBuYW1lIGFyZSBhbGwgdG9rZW5zIHRoYXRcbiAgICAgKiBvbmx5IHJlc29sdmUgYXQgZGVwbG95IHRpbWUsIHNvIGZsYXR0ZW4gdGhlIHJlc29sdmVkIGBGbjo6Sm9pbmAgYW5kIHN0YW5kXG4gICAgICogZWFjaCByZWZlcmVuY2UgaW4gZm9yIHRoZSByZXNvdXJjZSBpdCBwb2ludHMgYXQgKG1pbnVzIENESydzIGxvZ2ljYWwgaWRcbiAgICAgKiBoYXNoIHN1ZmZpeCkuIFRoYXQga2VlcHMgdGhlIGFzc2VydGlvbnMgYWJvdXQgKndoaWNoKiByZXNvdXJjZSBzdXBwbGllc1xuICAgICAqIGVhY2ggcGFydCBvZiB0aGUgVVJMLCB3aGljaCBpcyB0aGUgd2hvbGUgcXVlc3Rpb24gaGVyZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXNvbHZlVXJsKGFwaTogTmV4dGpzQXBpKTogc3RyaW5nIHtcbiAgICAgIGNvbnN0IHJlc29sdmVkID0gc3RhY2sucmVzb2x2ZShhcGkudXJsKTtcbiAgICAgIGlmICh0eXBlb2YgcmVzb2x2ZWQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc29sdmVkW1wiRm46OkpvaW5cIl1bMV1cbiAgICAgICAgLm1hcCgocGFydDogdW5rbm93bikgPT5cbiAgICAgICAgICB0eXBlb2YgcGFydCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgPyBwYXJ0XG4gICAgICAgICAgICA6IGB7JHsocGFydCBhcyB7IFJlZjogc3RyaW5nIH0pLlJlZi5yZXBsYWNlKC9bMC05QS1GXXs4fSQvLCBcIlwiKX19YCxcbiAgICAgICAgKVxuICAgICAgICAuam9pbihcIlwiKTtcbiAgICB9XG5cbiAgICBpdChcInJlcG9ydHMgdGhlIGV4ZWN1dGUtYXBpIGVuZHBvaW50IHdpdGggdGhlIHN0YWdlIGFwcGVuZGVkIHdoZW4gdGhlcmUncyBubyBjdXN0b20gZG9tYWluXCIsICgpID0+IHtcbiAgICAgIC8vIFRoZSBzdGFnZSBpcyBpbiB0aGUgcGF0aCBvbmx5IGhlcmUsIHdoaWNoIGlzIHRoZSB3aG9sZSByZWFzb24gdGhlXG4gICAgICAvLyByZWdpb25hbC1mdW5jdGlvbnMgZXhhbXBsZSBzZXRzIGFuIGFwcCBiYXNlUGF0aCBvZiBcIi9wcm9kXCIuXG4gICAgICBleHBlY3QocmVzb2x2ZVVybChjcmVhdGVBcGlXaXRoT3ZlcnJpZGVzKCkpKS50b0JlKFxuICAgICAgICBcImh0dHBzOi8ve05leHRqc0FwaVJlc3RBcGl9LmV4ZWN1dGUtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tL3tOZXh0anNBcGlSZXN0QXBpRGVwbG95bWVudFN0YWdlcHJvZH1cIixcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdChcImFwcGVuZHMgYmFzZVBhdGgsIHdoaWNoIG5lc3RzIGV2ZXJ5IHJlc291cmNlIGEgbGV2ZWwgZG93blwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoXG4gICAgICAgIHJlc29sdmVVcmwoY3JlYXRlQXBpV2l0aE92ZXJyaWRlcyh7IGJhc2VQYXRoOiBcIi9teS1iYXNlLXBhdGhcIiB9KSksXG4gICAgICApLnRvQmUoXG4gICAgICAgIFwiaHR0cHM6Ly97TmV4dGpzQXBpUmVzdEFwaX0uZXhlY3V0ZS1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20ve05leHRqc0FwaVJlc3RBcGlEZXBsb3ltZW50U3RhZ2Vwcm9kfS9teS1iYXNlLXBhdGhcIixcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdChcInByZWZlcnMgYSBjdXN0b20gZG9tYWluIGFuZCBkcm9wcyB0aGUgc3RhZ2UgZnJvbSB0aGUgcGF0aFwiLCAoKSA9PiB7XG4gICAgICAvLyBBIGRvbWFpbiBtYXBwZWQgYXQgdGhlIHJvb3QgaXMgdGhlIGNsZWFuZXN0IFJlZ2lvbmFsIHNldHVwOiBubyBzdGFnZSBpblxuICAgICAgLy8gdGhlIFVSTCBtZWFucyBubyBiYXNlUGF0aCBhbmQgbm8gc3RhZ2Ugd29ya2Fyb3VuZHMgYW55d2hlcmUuIFRoZSBzdGFnZSBpc1xuICAgICAgLy8gcmVhY2hlZCB0aHJvdWdoIHRoZSBkb21haW4ncyBiYXNlIHBhdGggbWFwcGluZyBpbnN0ZWFkLlxuICAgICAgZXhwZWN0KFxuICAgICAgICByZXNvbHZlVXJsKFxuICAgICAgICAgIGNyZWF0ZUFwaVdpdGhPdmVycmlkZXMoe1xuICAgICAgICAgICAgb3ZlcnJpZGVzOiB7IHJlc3RBcGlQcm9wczogeyBkb21haW5OYW1lOiBkb21haW5OYW1lKCkgfSB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKS50b0JlKFwiaHR0cHM6Ly97TmV4dGpzQXBpUmVzdEFwaUN1c3RvbURvbWFpbn1cIik7XG4gICAgfSk7XG5cbiAgICBpdChcImluY2x1ZGVzIGEgY3VzdG9tIGRvbWFpbidzIGJhc2UgcGF0aCBtYXBwaW5nXCIsICgpID0+IHtcbiAgICAgIC8vIENESyByZWplY3RzIHN1cnJvdW5kaW5nIHNsYXNoZXMgb24gYSBtYXBwaW5nLCBzbyBpdCdzIGFsd2F5cyBhIGJhcmVcbiAgICAgIC8vIHNlZ21lbnQgYnkgdGhlIHRpbWUgaXQgZ2V0cyBoZXJlLlxuICAgICAgZXhwZWN0KFxuICAgICAgICByZXNvbHZlVXJsKFxuICAgICAgICAgIGNyZWF0ZUFwaVdpdGhPdmVycmlkZXMoe1xuICAgICAgICAgICAgb3ZlcnJpZGVzOiB7IHJlc3RBcGlQcm9wczogeyBkb21haW5OYW1lOiBkb21haW5OYW1lKFwidGVhbS1hXCIpIH0gfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgICkudG9CZShcImh0dHBzOi8ve05leHRqc0FwaVJlc3RBcGlDdXN0b21Eb21haW59L3RlYW0tYVwiKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|
|
725
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWFwaS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25leHRqcy1hcGkudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHNEQUFzRDtBQUN0RCw2Q0FBeUM7QUFDekMsdURBQXNFO0FBQ3RFLCtFQUFpRTtBQUNqRSx1REFLZ0M7QUFDaEMsK0NBQTRDO0FBQzVDLCtEQUE0RDtBQUM1RCw2Q0FBeUQ7QUFFekQ7Ozs7R0FJRztBQUNILFNBQVMsT0FBTyxDQUNkLE1BTUc7SUFFSCxPQUFPO1FBQ0wsY0FBYyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdEQsSUFBSTtZQUNKLFFBQVEsRUFBRSxFQUFFO1NBQ2IsQ0FBQyxDQUFDO1FBQ0gsc0JBQXNCLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQy9DLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDN0IsSUFBQSxpQ0FBZSxFQUFDLEtBQUssRUFBRTtZQUNyQixhQUFhLEVBQUUsS0FBSyxDQUFDLGFBQWEsSUFBSSxLQUFLO1lBQzNDLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYTtZQUNsQyxPQUFPLEVBQUUsUUFBUTtTQUNsQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FDN0QsQ0FDRjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQsUUFBUSxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUU7SUFDekIsSUFBSSxLQUFZLENBQUM7SUFFakIsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNkLEtBQUssR0FB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UUFDbEQsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUV2RCxRQUFRLENBQUMsZUFBZSxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtRQUM5QyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUM7WUFDckIsU0FBUyxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFO1NBQy9DLENBQUMsQ0FBQztRQUVILFFBQVEsQ0FBQyxlQUFlLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsMEJBQTBCLEVBQUUsR0FBRyxFQUFFO1FBQ2xDLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQztZQUNyQixTQUFTLEVBQUUsRUFBRSxxQkFBcUIsRUFBRSxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsRUFBRTtTQUMxRCxDQUFDLENBQUM7UUFFSCxRQUFRLENBQUMscUJBQXFCLENBQUMsdUJBQXVCLEVBQUU7WUFDdEQsVUFBVSxFQUFFLEdBQUc7WUFDZixXQUFXLEVBQUU7Z0JBQ1gsU0FBUyxFQUFFLEVBQUUsV0FBVyxFQUFFLGtCQUFLLENBQUMsUUFBUSxFQUFFLEVBQUU7YUFDN0M7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5pbXBvcnQgeyBBcHAsIFN0YWNrIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucywgTWF0Y2gsIFRlbXBsYXRlIH0gZnJvbSBcImF3cy1jZGstbGliL2Fzc2VydGlvbnNcIjtcbmltcG9ydCB7IENlcnRpZmljYXRlIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jZXJ0aWZpY2F0ZW1hbmFnZXJcIjtcbmltcG9ydCB7XG4gIENvZGUsXG4gIEZ1bmN0aW9uIGFzIExhbWJkYUZ1bmN0aW9uLFxuICBJRnVuY3Rpb24sXG4gIFJ1bnRpbWUsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBCdWNrZXQgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQgeyBwYXRoUGF0dGVybnNGb3IgfSBmcm9tIFwiLi9hZGFwdGVyL2Z1bmN0aW9uLWdyb3Vwc1wiO1xuaW1wb3J0IHsgTmV4dGpzQXBpLCBOZXh0anNBcGlQcm9wcyB9IGZyb20gXCIuL25leHRqcy1hcGlcIjtcblxuLyoqXG4gKiBgZnVuY3Rpb25Hcm91cHNgIGFuZCB0aGUgYGZ1bmN0aW9uR3JvdXBCZWhhdmlvcnNgIHRoZSBidWlsZCB3b3VsZCByZWNvcmQgZm9yXG4gKiB0aGVtOiBgcm91dGVzYCBhcyByb3V0ZWQgKGFuIG9wdGlvbmFsIGNhdGNoLWFsbCdzIHBhcmVudCBsaXN0ZWQgYnkgaGFuZCksXG4gKiB3aXRoIGRhdGEtVVJMIGJlaGF2aW9ycyBmb3IgYSBncm91cCB0aGF0IG93bnMgYSBQYWdlcyBSb3V0ZXIgcGFnZS5cbiAqL1xuZnVuY3Rpb24gZ3JvdXBlZChcbiAgZ3JvdXBzOiB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHJvdXRlczogc3RyaW5nW107XG4gICAgaGFzRGF0YVJvdXRlcz86IGJvb2xlYW47XG4gICAgdHJhaWxpbmdTbGFzaD86IGJvb2xlYW47XG4gICAgZnVuY3Rpb246IElGdW5jdGlvbjtcbiAgfVtdLFxuKTogUGljazxOZXh0anNBcGlQcm9wcywgXCJmdW5jdGlvbkdyb3Vwc1wiIHwgXCJmdW5jdGlvbkdyb3VwQmVoYXZpb3JzXCI+IHtcbiAgcmV0dXJuIHtcbiAgICBmdW5jdGlvbkdyb3VwczogZ3JvdXBzLm1hcCgoeyBuYW1lLCBmdW5jdGlvbjogZm4gfSkgPT4gKHtcbiAgICAgIG5hbWUsXG4gICAgICBmdW5jdGlvbjogZm4sXG4gICAgfSkpLFxuICAgIGZ1bmN0aW9uR3JvdXBCZWhhdmlvcnM6IGdyb3Vwcy5mbGF0TWFwKChncm91cCkgPT5cbiAgICAgIGdyb3VwLnJvdXRlcy5mbGF0TWFwKChyb3V0ZSkgPT5cbiAgICAgICAgcGF0aFBhdHRlcm5zRm9yKHJvdXRlLCB7XG4gICAgICAgICAgaGFzRGF0YVJvdXRlczogZ3JvdXAuaGFzRGF0YVJvdXRlcyA/PyBmYWxzZSxcbiAgICAgICAgICB0cmFpbGluZ1NsYXNoOiBncm91cC50cmFpbGluZ1NsYXNoLFxuICAgICAgICAgIGJ1aWxkSWQ6IFwiYWJjMTIzXCIsXG4gICAgICAgIH0pLm1hcCgocGF0dGVybikgPT4gKHsgZ3JvdXA6IGdyb3VwLm5hbWUsIHJvdXRlLCBwYXR0ZXJuIH0pKSxcbiAgICAgICksXG4gICAgKSxcbiAgfTtcbn1cblxuZGVzY3JpYmUoXCJOZXh0anNBcGlcIiwgKCkgPT4ge1xuICBsZXQgc3RhY2s6IFN0YWNrO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIHN0YWNrID0gbmV3IFN0YWNrKG5ldyBBcHAoKSwgXCJUZXN0U3RhY2tcIiwge1xuICAgICAgZW52OiB7IGFjY291bnQ6IFwiMTIzNDU2Nzg5MDEyXCIsIHJlZ2lvbjogXCJ1cy1lYXN0LTFcIiB9LFxuICAgIH0pO1xuICB9KTtcblxuICBmdW5jdGlvbiBjcmVhdGVBcGkoc3RhdGljQXNzZXRzS2V5UHJlZml4Pzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgIHN0YXRpY0Fzc2V0c0J1Y2tldDogQnVja2V0LmZyb21CdWNrZXROYW1lKHN0YWNrLCBcIkJ1Y2tldFwiLCBcIm15LWJ1Y2tldFwiKSxcbiAgICAgIHN0YXRpY0Fzc2V0c0tleVByZWZpeCxcbiAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgfSksXG4gICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbXG4gICAgICAgIHsgbmFtZTogXCJmYXZpY29uLmljb1wiLCBpc0RpcmVjdG9yeTogZmFsc2UgfSxcbiAgICAgICAgeyBuYW1lOiBcImltYWdlc1wiLCBpc0RpcmVjdG9yeTogdHJ1ZSB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgUzMgaW50ZWdyYXRpb25zIGFkZHJlc3Mgb2JqZWN0cyBieSBrZXksIHNvIHRoZSB1cGxvYWRlZCBrZXkgcHJlZml4IGhhc1xuICAgKiB0byBhcHBlYXIgaW4gdGhlIGludGVncmF0aW9uIFVSSSBvciBldmVyeSBzdGF0aWMgcmVxdWVzdCA0MDRzLlxuICAgKi9cbiAgZnVuY3Rpb24gczNJbnRlZ3JhdGlvbktleXMoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IG1ldGhvZHMgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmZpbmRSZXNvdXJjZXMoXG4gICAgICBcIkFXUzo6QXBpR2F0ZXdheTo6TWV0aG9kXCIsXG4gICAgKTtcbiAgICBjb25zdCBtYXJrZXIgPSBcInMzOnBhdGgvbXktYnVja2V0L1wiO1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKG1ldGhvZHMpXG4gICAgICAuZmxhdE1hcCgobWV0aG9kKSA9PiBtZXRob2QuUHJvcGVydGllcy5JbnRlZ3JhdGlvbi5VcmlbXCJGbjo6Sm9pblwiXVsxXSlcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChwYXJ0OiB1bmtub3duKTogcGFydCBpcyBzdHJpbmcgPT5cbiAgICAgICAgICB0eXBlb2YgcGFydCA9PT0gXCJzdHJpbmdcIiAmJiBwYXJ0LmluY2x1ZGVzKG1hcmtlciksXG4gICAgICApXG4gICAgICAubWFwKChwYXJ0KSA9PiBwYXJ0LnNwbGl0KG1hcmtlcilbMV0pO1xuICB9XG5cbiAgaXQoXCJhZGRyZXNzZXMgb2JqZWN0cyBhdCB0aGUgYnVja2V0IHJvb3Qgd2hlbiBubyBrZXkgcHJlZml4IGlzIHNldFwiLCAoKSA9PiB7XG4gICAgY3JlYXRlQXBpKCk7XG5cbiAgICBleHBlY3QoczNJbnRlZ3JhdGlvbktleXMoKS5zb3J0KCkpLnRvRXF1YWwoW1xuICAgICAgXCJfbmV4dC9zdGF0aWMve2tleX1cIixcbiAgICAgIFwiZmF2aWNvbi5pY29cIixcbiAgICAgIFwiaW1hZ2VzL3trZXl9XCIsXG4gICAgXSk7XG4gIH0pO1xuXG4gIGl0KFwicHJlZml4ZXMgZXZlcnkgUzMgaW50ZWdyYXRpb24ga2V5IHdpdGggdGhlIHN0YXRpYyBhc3NldHMga2V5IHByZWZpeFwiLCAoKSA9PiB7XG4gICAgY3JlYXRlQXBpKFwiYnJhbmNoLXhcIik7XG5cbiAgICBleHBlY3QoczNJbnRlZ3JhdGlvbktleXMoKS5zb3J0KCkpLnRvRXF1YWwoW1xuICAgICAgXCJicmFuY2gteC9fbmV4dC9zdGF0aWMve2tleX1cIixcbiAgICAgIFwiYnJhbmNoLXgvZmF2aWNvbi5pY29cIixcbiAgICAgIFwiYnJhbmNoLXgvaW1hZ2VzL3trZXl9XCIsXG4gICAgXSk7XG4gIH0pO1xuXG4gIGl0KFwibm9ybWFsaXplcyBzdXJyb3VuZGluZyBzbGFzaGVzIG9uIHRoZSBrZXkgcHJlZml4XCIsICgpID0+IHtcbiAgICBjcmVhdGVBcGkoXCIvYnJhbmNoLXgvXCIpO1xuXG4gICAgZXhwZWN0KHMzSW50ZWdyYXRpb25LZXlzKCkpLnRvQ29udGFpbihcImJyYW5jaC14L19uZXh0L3N0YXRpYy97a2V5fVwiKTtcbiAgfSk7XG5cbiAgLyoqIFRoZSBzdGF0ZW1lbnRzIG9mIHRoZSBBUEkgR2F0ZXdheSDihpIgUzMgaW50ZWdyYXRpb24gcm9sZSdzIHBvbGljeS4gKi9cbiAgZnVuY3Rpb24gc3RhdGljSW50ZWdyYXRpb25TdGF0ZW1lbnRzKCkge1xuICAgIGNvbnN0IHBvbGljaWVzID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKS5maW5kUmVzb3VyY2VzKFxuICAgICAgXCJBV1M6OklBTTo6UG9saWN5XCIsXG4gICAgICB7XG4gICAgICAgIFByb3BlcnRpZXM6IHtcbiAgICAgICAgICBSb2xlczogW3sgUmVmOiBNYXRjaC5zdHJpbmdMaWtlUmVnZXhwKFwiU3RhdGljSW50ZWdyYXRpb25Sb2xlXCIpIH1dLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICApO1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHBvbGljaWVzKS5mbGF0TWFwKFxuICAgICAgKHBvbGljeSkgPT4gcG9saWN5LlByb3BlcnRpZXMuUG9saWN5RG9jdW1lbnQuU3RhdGVtZW50LFxuICAgICk7XG4gIH1cblxuICBpdChcInNjb3BlcyB0aGUgUzMgaW50ZWdyYXRpb24gcm9sZSB0byB0aGUgc3RhdGljIGFzc2V0cyBrZXkgcHJlZml4XCIsICgpID0+IHtcbiAgICAvLyBBIHNoYXJlZCBidWNrZXQgaG9sZHMgb3RoZXIgYXBwcycgYXNzZXRzIHVuZGVyIHRoZWlyIG93biBwcmVmaXhlcy5cbiAgICBjcmVhdGVBcGkoXCIvYnJhbmNoLXgvXCIpO1xuXG4gICAgY29uc3QgYnVja2V0QXJuID0ge1xuICAgICAgXCJGbjo6Sm9pblwiOiBbXCJcIiwgW1wiYXJuOlwiLCB7IFJlZjogXCJBV1M6OlBhcnRpdGlvblwiIH0sIFwiOnMzOjo6bXktYnVja2V0XCJdXSxcbiAgICB9O1xuICAgIGV4cGVjdChzdGF0aWNJbnRlZ3JhdGlvblN0YXRlbWVudHMoKSkudG9FcXVhbChbXG4gICAgICB7XG4gICAgICAgIEFjdGlvbjogXCJzMzpHZXRPYmplY3RcIixcbiAgICAgICAgRWZmZWN0OiBcIkFsbG93XCIsXG4gICAgICAgIFJlc291cmNlOiB7XG4gICAgICAgICAgXCJGbjo6Sm9pblwiOiBbXG4gICAgICAgICAgICBcIlwiLFxuICAgICAgICAgICAgW1wiYXJuOlwiLCB7IFJlZjogXCJBV1M6OlBhcnRpdGlvblwiIH0sIFwiOnMzOjo6bXktYnVja2V0L2JyYW5jaC14LypcIl0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIC8vIFVuY29uZGl0aW9uZWQ6IFMzIGNoZWNrcyBpdCBkdXJpbmcgYSBHZXRPYmplY3QsIHdpdGggbm8gYHMzOnByZWZpeGAuXG4gICAgICAgIEFjdGlvbjogXCJzMzpMaXN0QnVja2V0XCIsXG4gICAgICAgIEVmZmVjdDogXCJBbGxvd1wiLFxuICAgICAgICBSZXNvdXJjZTogYnVja2V0QXJuLFxuICAgICAgfSxcbiAgICBdKTtcbiAgfSk7XG5cbiAgaXQoXCJsZXRzIHRoZSBTMyBpbnRlZ3JhdGlvbiByb2xlIHJlYWQgdGhlIHdob2xlIGJ1Y2tldCB3aXRob3V0IGEga2V5IHByZWZpeFwiLCAoKSA9PiB7XG4gICAgY3JlYXRlQXBpKCk7XG5cbiAgICBjb25zdCBzdGF0ZW1lbnRzID0gc3RhdGljSW50ZWdyYXRpb25TdGF0ZW1lbnRzKCk7XG4gICAgZXhwZWN0KHN0YXRlbWVudHMpLnRvSGF2ZUxlbmd0aCgyKTtcbiAgICBleHBlY3Qoc3RhdGVtZW50c1swXS5SZXNvdXJjZVtcIkZuOjpKb2luXCJdWzFdKS50b0NvbnRhaW4oXG4gICAgICBcIjpzMzo6Om15LWJ1Y2tldC8qXCIsXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoXCJrZWVwcyB0aGUga2V5IHByZWZpeCBpbmRlcGVuZGVudCBvZiBiYXNlUGF0aCwgd2hpY2ggaXMgdGhlIFVSTCBwcmVmaXhcIiwgKCkgPT4ge1xuICAgIC8vIEEgTmV4dGpzUmVnaW9uYWxGdW5jdGlvbnMgYXBwIHdob3NlIGBiYXNlUGF0aGAgbWF0Y2hlcyB0aGUgQVBJIEdhdGV3YXlcbiAgICAvLyBzdGFnZSBzdGlsbCBoYXMgaXRzIGFzc2V0cyBhdCB0aGUgYnVja2V0IHJvb3QuXG4gICAgbmV3IE5leHRqc0FwaShzdGFjaywgXCJOZXh0anNBcGlcIiwge1xuICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgYmFzZVBhdGg6IFwiL3Byb2RcIixcbiAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgfSksXG4gICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbXSxcbiAgICB9KTtcblxuICAgIGV4cGVjdChzM0ludGVncmF0aW9uS2V5cygpKS50b0VxdWFsKFtcIl9uZXh0L3N0YXRpYy97a2V5fVwiXSk7XG4gICAgLy8gLi4uc2VydmVkIHVuZGVyIHRoZSBzdGFnZS1tYXRjaGluZyBVUkwgcHJlZml4LlxuICAgIFRlbXBsYXRlLmZyb21TdGFjayhzdGFjaykuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFxuICAgICAgXCJBV1M6OkFwaUdhdGV3YXk6OlJlc291cmNlXCIsXG4gICAgICB7IFBhdGhQYXJ0OiBcInByb2RcIiB9LFxuICAgICk7XG4gIH0pO1xuXG4gIC8vIEFQSSBHYXRld2F5IHBhdGggcGFydHMgY2FuJ3QgY29udGFpbiBcIi9cIiwgc28gYSBuZXN0ZWQgYmFzZVBhdGggcGFzc2VkIHdob2xlXG4gIC8vIHRvIGBhZGRSZXNvdXJjZWAgZmFpbHMgQ0RLJ3MgYHZhbGlkYXRlUmVzb3VyY2VQYXRoUGFydGAgYXQgc3ludGguIEl0J3NcbiAgLy8gcmVhY2hhYmxlOiBgcmVzb2x2ZUJhc2VQYXRoYCBhY2NlcHRzIGEgbmVzdGVkIHByb3AgZm9yIFJFR0lPTkFMX0ZVTkNUSU9OUyBhc1xuICAvLyBsb25nIGFzIHRoZSBhcHAncyBiYXNlUGF0aCBlbmRzIHdpdGggaXQuXG4gIGRlc2NyaWJlKFwibmVzdGVkIGJhc2VQYXRoXCIsICgpID0+IHtcbiAgICBmdW5jdGlvbiBwYXRoUGFydHMoKTogc3RyaW5nW10ge1xuICAgICAgY29uc3QgcmVzb3VyY2VzID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKS5maW5kUmVzb3VyY2VzKFxuICAgICAgICBcIkFXUzo6QXBpR2F0ZXdheTo6UmVzb3VyY2VcIixcbiAgICAgICk7XG4gICAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhyZXNvdXJjZXMpLm1hcChcbiAgICAgICAgKHJlc291cmNlKSA9PiByZXNvdXJjZS5Qcm9wZXJ0aWVzLlBhdGhQYXJ0LFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVBcGlXaXRoQmFzZVBhdGgoYmFzZVBhdGg6IHN0cmluZykge1xuICAgICAgcmV0dXJuIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgICBiYXNlUGF0aCxcbiAgICAgICAgc2VydmVyRnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJTZXJ2ZXJGblwiLCB7XG4gICAgICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICAgIH0pLFxuICAgICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbXSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGl0KFwiY3JlYXRlcyBvbmUgcmVzb3VyY2UgcGVyIHNlZ21lbnRcIiwgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IGNyZWF0ZUFwaVdpdGhCYXNlUGF0aChcIi90ZWFtL2FwcFwiKSkubm90LnRvVGhyb3coKTtcblxuICAgICAgZXhwZWN0KHBhdGhQYXJ0cygpKS50b0VxdWFsKFxuICAgICAgICBleHBlY3QuYXJyYXlDb250YWluaW5nKFtcInRlYW1cIiwgXCJhcHBcIiwgXCJfbmV4dFwiLCBcIntwcm94eSt9XCJdKSxcbiAgICAgICk7XG4gICAgICAvLyBOb3QgdGhlIHVuc3BsaXQgdmFsdWUsIHdoaWNoIEFQSSBHYXRld2F5IHdvdWxkIHJlamVjdC5cbiAgICAgIGV4cGVjdChwYXRoUGFydHMoKSkubm90LnRvQ29udGFpbihcInRlYW0vYXBwXCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJuZXN0cyB0aGUgc2VnbWVudHMgc28gdGhlIGFwcCBpcyByZWFjaGFibGUgdW5kZXIgdGhlIGZ1bGwgcGF0aFwiLCAoKSA9PiB7XG4gICAgICBjcmVhdGVBcGlXaXRoQmFzZVBhdGgoXCIvdGVhbS9hcHBcIik7XG5cbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjaykuZmluZFJlc291cmNlcyhcbiAgICAgICAgXCJBV1M6OkFwaUdhdGV3YXk6OlJlc291cmNlXCIsXG4gICAgICApO1xuICAgICAgY29uc3QgYnlQYXRoUGFydCA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgT2JqZWN0LmVudHJpZXMocmVzb3VyY2VzKS5tYXAoKFtsb2dpY2FsSWQsIHJlc291cmNlXSkgPT4gW1xuICAgICAgICAgIHJlc291cmNlLlByb3BlcnRpZXMuUGF0aFBhcnQsXG4gICAgICAgICAgeyBsb2dpY2FsSWQsIHBhcmVudElkOiByZXNvdXJjZS5Qcm9wZXJ0aWVzLlBhcmVudElkIH0sXG4gICAgICAgIF0pLFxuICAgICAgKTtcbiAgICAgIC8vIFwiYXBwXCIgaGFuZ3Mgb2ZmIFwidGVhbVwiLCBub3Qgb2ZmIHRoZSBBUEkgcm9vdC5cbiAgICAgIGV4cGVjdChieVBhdGhQYXJ0LmFwcC5wYXJlbnRJZCkudG9FcXVhbCh7XG4gICAgICAgIFJlZjogYnlQYXRoUGFydC50ZWFtLmxvZ2ljYWxJZCxcbiAgICAgIH0pO1xuICAgICAgZXhwZWN0KGJ5UGF0aFBhcnQudGVhbS5wYXJlbnRJZCkudG9IYXZlUHJvcGVydHkoXCJGbjo6R2V0QXR0XCIpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJzdGlsbCBjcmVhdGVzIGEgc2luZ2xlIHJlc291cmNlIGZvciBhIGZsYXQgYmFzZVBhdGhcIiwgKCkgPT4ge1xuICAgICAgY3JlYXRlQXBpV2l0aEJhc2VQYXRoKFwiL2Jhc2VcIik7XG5cbiAgICAgIGV4cGVjdChwYXRoUGFydHMoKSkudG9Db250YWluKFwiYmFzZVwiKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJ1cmxcIiwgKCkgPT4ge1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUFwaVdpdGhPdmVycmlkZXMoXG4gICAgICBwcm9wczogUGFydGlhbDxOZXh0anNBcGlQcm9wcz4gPSB7fSxcbiAgICApOiBOZXh0anNBcGkge1xuICAgICAgcmV0dXJuIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgfSksXG4gICAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtdLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvbWFpbk5hbWUoYmFzZVBhdGg/OiBzdHJpbmcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRvbWFpbk5hbWU6IFwiYXBwLmV4YW1wbGUuY29tXCIsXG4gICAgICAgIGNlcnRpZmljYXRlOiBDZXJ0aWZpY2F0ZS5mcm9tQ2VydGlmaWNhdGVBcm4oXG4gICAgICAgICAgc3RhY2ssXG4gICAgICAgICAgXCJDZXJ0XCIsXG4gICAgICAgICAgXCJhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlL2FiY1wiLFxuICAgICAgICApLFxuICAgICAgICBiYXNlUGF0aCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIFJFU1QgQVBJIGlkLCB0aGUgc3RhZ2UgbmFtZSBhbmQgdGhlIGRvbWFpbiBuYW1lIGFyZSBhbGwgdG9rZW5zIHRoYXRcbiAgICAgKiBvbmx5IHJlc29sdmUgYXQgZGVwbG95IHRpbWUsIHNvIGZsYXR0ZW4gdGhlIHJlc29sdmVkIGBGbjo6Sm9pbmAgYW5kIHN0YW5kXG4gICAgICogZWFjaCByZWZlcmVuY2UgaW4gZm9yIHRoZSByZXNvdXJjZSBpdCBwb2ludHMgYXQgKG1pbnVzIENESydzIGxvZ2ljYWwgaWRcbiAgICAgKiBoYXNoIHN1ZmZpeCkuIFRoYXQga2VlcHMgdGhlIGFzc2VydGlvbnMgYWJvdXQgKndoaWNoKiByZXNvdXJjZSBzdXBwbGllc1xuICAgICAqIGVhY2ggcGFydCBvZiB0aGUgVVJMLCB3aGljaCBpcyB0aGUgd2hvbGUgcXVlc3Rpb24gaGVyZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXNvbHZlVXJsKGFwaTogTmV4dGpzQXBpKTogc3RyaW5nIHtcbiAgICAgIGNvbnN0IHJlc29sdmVkID0gc3RhY2sucmVzb2x2ZShhcGkudXJsKTtcbiAgICAgIGlmICh0eXBlb2YgcmVzb2x2ZWQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc29sdmVkW1wiRm46OkpvaW5cIl1bMV1cbiAgICAgICAgLm1hcCgocGFydDogdW5rbm93bikgPT5cbiAgICAgICAgICB0eXBlb2YgcGFydCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgPyBwYXJ0XG4gICAgICAgICAgICA6IGB7JHsocGFydCBhcyB7IFJlZjogc3RyaW5nIH0pLlJlZi5yZXBsYWNlKC9bMC05QS1GXXs4fSQvLCBcIlwiKX19YCxcbiAgICAgICAgKVxuICAgICAgICAuam9pbihcIlwiKTtcbiAgICB9XG5cbiAgICBpdChcInJlcG9ydHMgdGhlIGV4ZWN1dGUtYXBpIGVuZHBvaW50IHdpdGggdGhlIHN0YWdlIGFwcGVuZGVkIHdoZW4gdGhlcmUncyBubyBjdXN0b20gZG9tYWluXCIsICgpID0+IHtcbiAgICAgIC8vIFRoZSBzdGFnZSBpcyBpbiB0aGUgcGF0aCBvbmx5IGhlcmUsIHdoaWNoIGlzIHRoZSB3aG9sZSByZWFzb24gdGhlXG4gICAgICAvLyByZWdpb25hbC1mdW5jdGlvbnMgZXhhbXBsZSBzZXRzIGFuIGFwcCBiYXNlUGF0aCBvZiBcIi9wcm9kXCIuXG4gICAgICBleHBlY3QocmVzb2x2ZVVybChjcmVhdGVBcGlXaXRoT3ZlcnJpZGVzKCkpKS50b0JlKFxuICAgICAgICBcImh0dHBzOi8ve05leHRqc0FwaVJlc3RBcGl9LmV4ZWN1dGUtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tL3tOZXh0anNBcGlSZXN0QXBpRGVwbG95bWVudFN0YWdlcHJvZH1cIixcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdChcImFwcGVuZHMgYmFzZVBhdGgsIHdoaWNoIG5lc3RzIGV2ZXJ5IHJlc291cmNlIGEgbGV2ZWwgZG93blwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoXG4gICAgICAgIHJlc29sdmVVcmwoY3JlYXRlQXBpV2l0aE92ZXJyaWRlcyh7IGJhc2VQYXRoOiBcIi9teS1iYXNlLXBhdGhcIiB9KSksXG4gICAgICApLnRvQmUoXG4gICAgICAgIFwiaHR0cHM6Ly97TmV4dGpzQXBpUmVzdEFwaX0uZXhlY3V0ZS1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20ve05leHRqc0FwaVJlc3RBcGlEZXBsb3ltZW50U3RhZ2Vwcm9kfS9teS1iYXNlLXBhdGhcIixcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdChcInByZWZlcnMgYSBjdXN0b20gZG9tYWluIGFuZCBkcm9wcyB0aGUgc3RhZ2UgZnJvbSB0aGUgcGF0aFwiLCAoKSA9PiB7XG4gICAgICAvLyBBIGRvbWFpbiBtYXBwZWQgYXQgdGhlIHJvb3QgaXMgdGhlIGNsZWFuZXN0IFJlZ2lvbmFsIHNldHVwOiBubyBzdGFnZSBpblxuICAgICAgLy8gdGhlIFVSTCBtZWFucyBubyBiYXNlUGF0aCBhbmQgbm8gc3RhZ2Ugd29ya2Fyb3VuZHMgYW55d2hlcmUuIFRoZSBzdGFnZSBpc1xuICAgICAgLy8gcmVhY2hlZCB0aHJvdWdoIHRoZSBkb21haW4ncyBiYXNlIHBhdGggbWFwcGluZyBpbnN0ZWFkLlxuICAgICAgZXhwZWN0KFxuICAgICAgICByZXNvbHZlVXJsKFxuICAgICAgICAgIGNyZWF0ZUFwaVdpdGhPdmVycmlkZXMoe1xuICAgICAgICAgICAgb3ZlcnJpZGVzOiB7IHJlc3RBcGlQcm9wczogeyBkb21haW5OYW1lOiBkb21haW5OYW1lKCkgfSB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKS50b0JlKFwiaHR0cHM6Ly97TmV4dGpzQXBpUmVzdEFwaUN1c3RvbURvbWFpbn1cIik7XG4gICAgfSk7XG5cbiAgICBpdChcImluY2x1ZGVzIGEgY3VzdG9tIGRvbWFpbidzIGJhc2UgcGF0aCBtYXBwaW5nXCIsICgpID0+IHtcbiAgICAgIC8vIENESyByZWplY3RzIHN1cnJvdW5kaW5nIHNsYXNoZXMgb24gYSBtYXBwaW5nLCBzbyBpdCdzIGFsd2F5cyBhIGJhcmVcbiAgICAgIC8vIHNlZ21lbnQgYnkgdGhlIHRpbWUgaXQgZ2V0cyBoZXJlLlxuICAgICAgZXhwZWN0KFxuICAgICAgICByZXNvbHZlVXJsKFxuICAgICAgICAgIGNyZWF0ZUFwaVdpdGhPdmVycmlkZXMoe1xuICAgICAgICAgICAgb3ZlcnJpZGVzOiB7IHJlc3RBcGlQcm9wczogeyBkb21haW5OYW1lOiBkb21haW5OYW1lKFwidGVhbS1hXCIpIH0gfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgICkudG9CZShcImh0dHBzOi8ve05leHRqc0FwaVJlc3RBcGlDdXN0b21Eb21haW59L3RlYW0tYVwiKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJmdW5jdGlvbkdyb3VwcyByZXNvdXJjZSB0cmVlXCIsICgpID0+IHtcbiAgICAvKiogTGFtYmRhIGZ1bmN0aW9ucyB0aGF0IGBBTllgIG9uIHRoZSByZXNvdXJjZSBhdCBgcGF0aFBhcnRgIGludm9rZXMuICovXG4gICAgZnVuY3Rpb24gYW55VGFyZ2V0cyhwYXRoUGFydDogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgY29uc3QgcmVzb3VyY2VzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcyhcIkFXUzo6QXBpR2F0ZXdheTo6UmVzb3VyY2VcIiwge1xuICAgICAgICBQcm9wZXJ0aWVzOiB7IFBhdGhQYXJ0OiBwYXRoUGFydCB9LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBpZHMgPSBPYmplY3Qua2V5cyhyZXNvdXJjZXMpO1xuICAgICAgZXhwZWN0KGlkcykudG9IYXZlTGVuZ3RoKDEpO1xuICAgICAgY29uc3QgbWV0aG9kcyA9IHRlbXBsYXRlLmZpbmRSZXNvdXJjZXMoXCJBV1M6OkFwaUdhdGV3YXk6Ok1ldGhvZFwiLCB7XG4gICAgICAgIFByb3BlcnRpZXM6IHsgSHR0cE1ldGhvZDogXCJBTllcIiwgUmVzb3VyY2VJZDogeyBSZWY6IGlkc1swXSB9IH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBPYmplY3QudmFsdWVzKG1ldGhvZHMpLm1hcChcbiAgICAgICAgKG1ldGhvZCkgPT5cbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShtZXRob2QuUHJvcGVydGllcy5JbnRlZ3JhdGlvbi5VcmkpLm1hdGNoKFxuICAgICAgICAgICAgLyhTZXJ2ZXJGbnxHcm91cEZufFJlcG9ydHNGbilbQS1GMC05XSsvLFxuICAgICAgICAgICkhWzFdLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpdChcInNlbmRzIGEgZ3JvdXAncyBwYXJlbnQgcGF0aHMgdG8gdGhlIGRlZmF1bHQgZnVuY3Rpb25cIiwgKCkgPT4ge1xuICAgICAgLy8gQVBJIEdhdGV3YXkgYW5zd2VycyBhIG1ldGhvZGxlc3MgcmVzb3VyY2Ugd2l0aCA0MDMgcmF0aGVyIHRoYW4gZmFsbGluZ1xuICAgICAgLy8gYmFjayB0byB0aGUgcm9vdCBge3Byb3h5K31gLCBzbyBgL2FwaWAgYW5kIGAvYXBpL3JlcG9ydHNgIG5lZWQgb25lLlxuICAgICAgbmV3IE5leHRqc0FwaShzdGFjaywgXCJOZXh0anNBcGlcIiwge1xuICAgICAgICBzdGF0aWNBc3NldHNCdWNrZXQ6IEJ1Y2tldC5mcm9tQnVja2V0TmFtZShzdGFjaywgXCJCdWNrZXRcIiwgXCJteS1idWNrZXRcIiksXG4gICAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICB9KSxcbiAgICAgICAgcHVibGljRGlyRW50cmllczogW10sXG4gICAgICAgIC4uLmdyb3VwZWQoW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwicmVwb3J0c1wiLFxuICAgICAgICAgICAgcm91dGVzOiBbXCIvYXBpL3JlcG9ydHMvKipcIiwgXCIvYXBpL2V4cG9ydFwiXSxcbiAgICAgICAgICAgIGZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiR3JvdXBGblwiLCB7XG4gICAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICBdKSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoYW55VGFyZ2V0cyhcImFwaVwiKSkudG9FcXVhbChbXCJTZXJ2ZXJGblwiXSk7XG4gICAgICBleHBlY3QoYW55VGFyZ2V0cyhcInJlcG9ydHNcIikpLnRvRXF1YWwoW1wiU2VydmVyRm5cIl0pO1xuICAgICAgZXhwZWN0KGFueVRhcmdldHMoXCJleHBvcnRcIikpLnRvRXF1YWwoW1wiR3JvdXBGblwiXSk7XG4gICAgfSk7XG5cbiAgICBpdChcInNlbmRzIGEgcGFyZW50IHVuZGVyIGFub3RoZXIgZ3JvdXAncyBzdWJ0cmVlIHRvIHRoYXQgZ3JvdXBcIiwgKCkgPT4ge1xuICAgICAgLy8gYGFzc2lnblJvdXRlc1RvR3JvdXBzYCBwYWNrYWdlcyBgL2FwaS9yZXBvcnRzYCBpbnRvIGBhcGlgLCBhbmRcbiAgICAgIC8vIENsb3VkRnJvbnQncyBgYXBpLypgIHNlbmRzIGl0IHRoZXJlOyBzbyBtdXN0IEFQSSBHYXRld2F5LlxuICAgICAgbmV3IE5leHRqc0FwaShzdGFjaywgXCJOZXh0anNBcGlcIiwge1xuICAgICAgICBzdGF0aWNBc3NldHNCdWNrZXQ6IEJ1Y2tldC5mcm9tQnVja2V0TmFtZShzdGFjaywgXCJCdWNrZXRcIiwgXCJteS1idWNrZXRcIiksXG4gICAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICB9KSxcbiAgICAgICAgcHVibGljRGlyRW50cmllczogW10sXG4gICAgICAgIC4uLmdyb3VwZWQoW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiYXBpXCIsXG4gICAgICAgICAgICByb3V0ZXM6IFtcIi9hcGkvKipcIl0sXG4gICAgICAgICAgICBoYXNEYXRhUm91dGVzOiB0cnVlLFxuICAgICAgICAgICAgZnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJHcm91cEZuXCIsIHtcbiAgICAgICAgICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogXCJyZXBvcnRzXCIsXG4gICAgICAgICAgICByb3V0ZXM6IFtcIi9hcGkvcmVwb3J0cy9xMS8qKlwiXSxcbiAgICAgICAgICAgIGhhc0RhdGFSb3V0ZXM6IHRydWUsXG4gICAgICAgICAgICBmdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlJlcG9ydHNGblwiLCB7XG4gICAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICBdKSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBFYWNoIHBhdGggcGFydCBiZWxvdyBhcHBlYXJzIHR3aWNlLCB1bmRlciBgL2AgYW5kIHVuZGVyIHRoZSBkYXRhXG4gICAgICAvLyBwcmVmaXgsIHNvIGNoZWNrIHRoZSB0cmVlIGJ5IHBhdGguXG4gICAgICBjb25zdCB0YXJnZXRzID0gYW55VGFyZ2V0c0J5UGF0aCgpO1xuICAgICAgZXhwZWN0KHRhcmdldHNbXCIvYXBpXCJdKS50b0VxdWFsKFtcIlNlcnZlckZuXCJdKTtcbiAgICAgIGV4cGVjdCh0YXJnZXRzW1wiL2FwaS9yZXBvcnRzXCJdKS50b0VxdWFsKFtcIkdyb3VwRm5cIl0pO1xuICAgICAgZXhwZWN0KHRhcmdldHNbXCIvYXBpL3JlcG9ydHMvcTFcIl0pLnRvRXF1YWwoW1wiR3JvdXBGblwiXSk7XG4gICAgICBleHBlY3QodGFyZ2V0c1tcIi9hcGkvcmVwb3J0cy9xMS97cHJveHkrfVwiXSkudG9FcXVhbChbXCJSZXBvcnRzRm5cIl0pO1xuICAgICAgZXhwZWN0KHRhcmdldHNbXCIvX25leHQvZGF0YS97YnVpbGRJZH0vYXBpL3JlcG9ydHNcIl0pLnRvRXF1YWwoW1wiR3JvdXBGblwiXSk7XG4gICAgICBleHBlY3QodGFyZ2V0c1tcIi9fbmV4dC9kYXRhL3tidWlsZElkfVwiXSkudG9FcXVhbChbXCJTZXJ2ZXJGblwiXSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVHcm91cGVkQXBpKGhhc0RhdGFSb3V0ZXM6IGJvb2xlYW4pIHtcbiAgICAgIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgfSksXG4gICAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtdLFxuICAgICAgICAuLi5ncm91cGVkKFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcInJlcG9ydHNcIixcbiAgICAgICAgICAgIHJvdXRlczogW1wiL3JlcG9ydHMvKipcIiwgXCIvZG9jcy9pbnRyb1wiXSxcbiAgICAgICAgICAgIGhhc0RhdGFSb3V0ZXMsXG4gICAgICAgICAgICBmdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIkdyb3VwRm5cIiwge1xuICAgICAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogRXZlcnkgcmVzb3VyY2UgcGF0aCBpbiB0aGUgQVBJLCBlLmcuIGAvX25leHQvZGF0YS97YnVpbGRJZH0veC5qc29uYC4gKi9cbiAgICBmdW5jdGlvbiByZXNvdXJjZVBhdGhzKCk6IHN0cmluZ1tdIHtcbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjaykuZmluZFJlc291cmNlcyhcbiAgICAgICAgXCJBV1M6OkFwaUdhdGV3YXk6OlJlc291cmNlXCIsXG4gICAgICApO1xuICAgICAgY29uc3QgcGF0aE9mID0gKGlkOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgICAgICBjb25zdCB7IFBhcmVudElkLCBQYXRoUGFydCB9ID0gcmVzb3VyY2VzW2lkXS5Qcm9wZXJ0aWVzO1xuICAgICAgICBjb25zdCBwYXJlbnQgPSBQYXJlbnRJZC5SZWY7XG4gICAgICAgIHJldHVybiBwYXJlbnQgJiYgcmVzb3VyY2VzW3BhcmVudF1cbiAgICAgICAgICA/IGAke3BhdGhPZihwYXJlbnQpfS8ke1BhdGhQYXJ0fWBcbiAgICAgICAgICA6IGAvJHtQYXRoUGFydH1gO1xuICAgICAgfTtcbiAgICAgIHJldHVybiBPYmplY3Qua2V5cyhyZXNvdXJjZXMpLm1hcChwYXRoT2YpLnNvcnQoKTtcbiAgICB9XG5cbiAgICAvKiogUmVzb3VyY2UgcGF0aCDihpIgdGhlIExhbWJkYSBmdW5jdGlvbnMgYEFOWWAgb24gaXQgaW52b2tlcy4gKi9cbiAgICBmdW5jdGlvbiBhbnlUYXJnZXRzQnlQYXRoKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiB7XG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gICAgICBjb25zdCByZXNvdXJjZXMgPSB0ZW1wbGF0ZS5maW5kUmVzb3VyY2VzKFwiQVdTOjpBcGlHYXRld2F5OjpSZXNvdXJjZVwiKTtcbiAgICAgIGNvbnN0IHBhdGhPZiA9IChpZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgICAgY29uc3QgeyBQYXJlbnRJZCwgUGF0aFBhcnQgfSA9IHJlc291cmNlc1tpZF0uUHJvcGVydGllcztcbiAgICAgICAgY29uc3QgcGFyZW50ID0gUGFyZW50SWQuUmVmO1xuICAgICAgICByZXR1cm4gcGFyZW50ICYmIHJlc291cmNlc1twYXJlbnRdXG4gICAgICAgICAgPyBgJHtwYXRoT2YocGFyZW50KX0vJHtQYXRoUGFydH1gXG4gICAgICAgICAgOiBgLyR7UGF0aFBhcnR9YDtcbiAgICAgIH07XG4gICAgICBjb25zdCBtZXRob2RzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcyhcIkFXUzo6QXBpR2F0ZXdheTo6TWV0aG9kXCIsIHtcbiAgICAgICAgUHJvcGVydGllczogeyBIdHRwTWV0aG9kOiBcIkFOWVwiIH0sXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHRhcmdldHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9O1xuICAgICAgZm9yIChjb25zdCBtZXRob2Qgb2YgT2JqZWN0LnZhbHVlcyhtZXRob2RzKSkge1xuICAgICAgICBjb25zdCBpZCA9IG1ldGhvZC5Qcm9wZXJ0aWVzLlJlc291cmNlSWQ/LlJlZjtcbiAgICAgICAgaWYgKCFpZCB8fCAhcmVzb3VyY2VzW2lkXSkgY29udGludWU7XG4gICAgICAgICh0YXJnZXRzW3BhdGhPZihpZCldID8/PSBbXSkucHVzaChcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShtZXRob2QuUHJvcGVydGllcy5JbnRlZ3JhdGlvbi5VcmkpLm1hdGNoKFxuICAgICAgICAgICAgLyhTZXJ2ZXJGbnxHcm91cEZufFJlcG9ydHNGbilbQS1GMC05XSsvLFxuICAgICAgICAgICkhWzFdLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRhcmdldHM7XG4gICAgfVxuXG4gICAgaXQoXCJyb3V0ZXMgYSBncm91cCdzIFBhZ2VzIFJvdXRlciBkYXRhIFVSTHMgdG8gaXQgdG9vXCIsICgpID0+IHtcbiAgICAgIGNyZWF0ZUdyb3VwZWRBcGkodHJ1ZSk7XG5cbiAgICAgIGNvbnN0IHBhdGhzID0gcmVzb3VyY2VQYXRocygpO1xuICAgICAgZXhwZWN0KHBhdGhzKS50b0NvbnRhaW4oXCIvX25leHQvZGF0YS97YnVpbGRJZH0vcmVwb3J0cy97cHJveHkrfVwiKTtcbiAgICAgIGV4cGVjdChwYXRocykudG9Db250YWluKFwiL19uZXh0L2RhdGEve2J1aWxkSWR9L2RvY3MvaW50cm8uanNvblwiKTtcbiAgICAgIGV4cGVjdChhbnlUYXJnZXRzKFwiaW50cm8uanNvblwiKSkudG9FcXVhbChbXCJHcm91cEZuXCJdKTtcbiAgICAgIC8vIEEgbWV0aG9kbGVzcyBwYXJlbnQgYW5zd2VycyA0MDMsIHNvIHRoZSBkYXRhIHByZWZpeCBuZWVkcyB0aGUgZGVmYXVsdC5cbiAgICAgIGV4cGVjdChhbnlUYXJnZXRzKFwie2J1aWxkSWR9XCIpKS50b0VxdWFsKFtcIlNlcnZlckZuXCJdKTtcbiAgICB9KTtcblxuICAgIGl0KFwia2VlcHMgZWFjaCBncm91cCdzIGRhdGEgVVJMcyB0byBpdHMgb3duIHN1YnRyZWUgKEEpXCIsICgpID0+IHtcbiAgICAgIC8vIGB7YnVpbGRJZH1gIGlzIG9uZSBwYXRoIHNlZ21lbnQsIHdoZXJlIENsb3VkRnJvbnQncyBgKmAgY3Jvc3NlZCBgL2A6XG4gICAgICAvLyBgL19uZXh0L2RhdGEvPGlkPi9kb2NzL2Jsb2cveC5qc29uYCBoYXMgbm8gd2F5IGludG8gYmxvZydzIHJlc291cmNlLlxuICAgICAgbmV3IE5leHRqc0FwaShzdGFjaywgXCJOZXh0anNBcGlcIiwge1xuICAgICAgICBzdGF0aWNBc3NldHNCdWNrZXQ6IEJ1Y2tldC5mcm9tQnVja2V0TmFtZShzdGFjaywgXCJCdWNrZXRcIiwgXCJteS1idWNrZXRcIiksXG4gICAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICB9KSxcbiAgICAgICAgcHVibGljRGlyRW50cmllczogW10sXG4gICAgICAgIC4uLmdyb3VwZWQoW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiYmxvZ1wiLFxuICAgICAgICAgICAgcm91dGVzOiBbXCIvYmxvZy8qKlwiXSxcbiAgICAgICAgICAgIGhhc0RhdGFSb3V0ZXM6IHRydWUsXG4gICAgICAgICAgICBmdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIkdyb3VwRm5cIiwge1xuICAgICAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSksXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChcbiAgICAgICAgcmVzb3VyY2VQYXRocygpLmZpbHRlcigocGF0aCkgPT4gcGF0aC5zdGFydHNXaXRoKFwiL19uZXh0L2RhdGFcIikpLFxuICAgICAgKS50b0VxdWFsKFtcbiAgICAgICAgXCIvX25leHQvZGF0YVwiLFxuICAgICAgICBcIi9fbmV4dC9kYXRhL3tidWlsZElkfVwiLFxuICAgICAgICBcIi9fbmV4dC9kYXRhL3tidWlsZElkfS9ibG9nXCIsXG4gICAgICAgIFwiL19uZXh0L2RhdGEve2J1aWxkSWR9L2Jsb2cve3Byb3h5K31cIixcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJyb3V0ZXMgYW4gb3B0aW9uYWwgY2F0Y2gtYWxsJ3MgcGFyZW50IHRvIHRoZSBncm91cCB3aGVuIGl0IGlzIGxpc3RlZCAoQilcIiwgKCkgPT4ge1xuICAgICAgLy8gVGhlIGJ1aWxkIHJvdXRlcyBgL3Nob3BgIGFsb25nc2lkZSBgL3Nob3AvKipgIHdoZW4gdGhlIGdyb3VwIG93bnNcbiAgICAgIC8vIGBzaG9wL1tbLi4uc2x1Z11dYCAoc2VlIGByb3V0ZWRQYXR0ZXJuc2ApOiBge3Byb3h5K31gIGRvZXMgbm90IG1hdGNoXG4gICAgICAvLyB0aGUgcGFyZW50LCB3aGljaCB3b3VsZCBvdGhlcndpc2UgcmVhY2ggdGhlIGRlZmF1bHQgZnVuY3Rpb24uXG4gICAgICBuZXcgTmV4dGpzQXBpKHN0YWNrLCBcIk5leHRqc0FwaVwiLCB7XG4gICAgICAgIHN0YXRpY0Fzc2V0c0J1Y2tldDogQnVja2V0LmZyb21CdWNrZXROYW1lKHN0YWNrLCBcIkJ1Y2tldFwiLCBcIm15LWJ1Y2tldFwiKSxcbiAgICAgICAgc2VydmVyRnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJTZXJ2ZXJGblwiLCB7XG4gICAgICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICAgIH0pLFxuICAgICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbXSxcbiAgICAgICAgLi4uZ3JvdXBlZChbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogXCJzaG9wXCIsXG4gICAgICAgICAgICByb3V0ZXM6IFtcIi9zaG9wLyoqXCIsIFwiL3Nob3BcIl0sXG4gICAgICAgICAgICBmdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIkdyb3VwRm5cIiwge1xuICAgICAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSksXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChhbnlUYXJnZXRzKFwic2hvcFwiKSkudG9FcXVhbChbXCJHcm91cEZuXCJdKTtcbiAgICB9KTtcblxuICAgIGl0LmVhY2goW1xuICAgICAgW3sgbmFtZTogXCJkb2NzXCIsIGlzRGlyZWN0b3J5OiB0cnVlIH0sIFwiL2RvY3MvKipcIiwgXCJkaXJlY3RvcnlcIl0sXG4gICAgICBbeyBuYW1lOiBcImRvY3NcIiwgaXNEaXJlY3Rvcnk6IHRydWUgfSwgXCIvZG9jcy9ndWlkZS8qKlwiLCBcImRpcmVjdG9yeVwiXSxcbiAgICAgIFt7IG5hbWU6IFwicm9ib3RzLnR4dFwiLCBpc0RpcmVjdG9yeTogZmFsc2UgfSwgXCIvcm9ib3RzLnR4dFwiLCBcImZpbGVcIl0sXG4gICAgXSkoXG4gICAgICBcInJlamVjdHMgYSBncm91cCByb3V0ZSBvbiBhIHB1YmxpYy8gZW50cnkncyByZXNvdXJjZTogJXAgd2l0aCAlcCAoRSlcIixcbiAgICAgIChlbnRyeSwgcm91dGUsIGtpbmQpID0+IHtcbiAgICAgICAgZXhwZWN0KFxuICAgICAgICAgICgpID0+XG4gICAgICAgICAgICBuZXcgTmV4dGpzQXBpKHN0YWNrLCBcIk5leHRqc0FwaVwiLCB7XG4gICAgICAgICAgICAgIHN0YXRpY0Fzc2V0c0J1Y2tldDogQnVja2V0LmZyb21CdWNrZXROYW1lKFxuICAgICAgICAgICAgICAgIHN0YWNrLFxuICAgICAgICAgICAgICAgIFwiQnVja2V0XCIsXG4gICAgICAgICAgICAgICAgXCJteS1idWNrZXRcIixcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgc2VydmVyRnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJTZXJ2ZXJGblwiLCB7XG4gICAgICAgICAgICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbZW50cnldLFxuICAgICAgICAgICAgICAuLi5ncm91cGVkKFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBuYW1lOiBcImdcIixcbiAgICAgICAgICAgICAgICAgIHJvdXRlczogW3JvdXRlXSxcbiAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiR3JvdXBGblwiLCB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoXCJleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiB7fTtcIiksXG4gICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApLnRvVGhyb3coYG92ZXJsYXBzIHRoZSB0b3AtbGV2ZWwgcHVibGljLyAke2tpbmR9IFwiJHtlbnRyeS5uYW1lfVwiYCk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICBpdChcImFsbG93cyBhbiBleGFjdCByb3V0ZSBuYW1lZCBsaWtlIGEgcHVibGljLyBkaXJlY3RvcnksIHdoaWNoIGlzIG5vdCB1bmRlciBpdFwiLCAoKSA9PiB7XG4gICAgICBleHBlY3QoXG4gICAgICAgICgpID0+XG4gICAgICAgICAgbmV3IE5leHRqc0FwaShzdGFjaywgXCJOZXh0anNBcGlcIiwge1xuICAgICAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoXG4gICAgICAgICAgICAgIHN0YWNrLFxuICAgICAgICAgICAgICBcIkJ1Y2tldFwiLFxuICAgICAgICAgICAgICBcIm15LWJ1Y2tldFwiLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbeyBuYW1lOiBcImRvY3NcIiwgaXNEaXJlY3Rvcnk6IHRydWUgfV0sXG4gICAgICAgICAgICAuLi5ncm91cGVkKFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG5hbWU6IFwiZ1wiLFxuICAgICAgICAgICAgICAgIHJvdXRlczogW1wiL2RvY3NcIl0sXG4gICAgICAgICAgICAgICAgZnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJHcm91cEZuXCIsIHtcbiAgICAgICAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0pLFxuICAgICAgICAgIH0pLFxuICAgICAgKS5ub3QudG9UaHJvdygpO1xuICAgIH0pO1xuXG4gICAgaXQoXCJyb3V0ZXMgYW4gZXhhY3Qgcm91dGUncyB0cmFpbGluZ1NsYXNoIGZvcm0gdGhyb3VnaCBpdHMgb25lIHJlc291cmNlXCIsICgpID0+IHtcbiAgICAgIC8vIENsb3VkRnJvbnQgbmVlZHMgYHByaWNpbmcvYCBhcyBhIGJlaGF2aW9yIG9mIGl0cyBvd247IEFQSSBHYXRld2F5XG4gICAgICAvLyBtYXRjaGVzIGAvcHJpY2luZy9gIG9uIHRoZSBgcHJpY2luZ2AgcmVzb3VyY2UsIHNvIHRoZSB2YXJpYW50IGFkZHNcbiAgICAgIC8vIG5vdGhpbmcgaGVyZSBhbmQgbXVzdCBub3QgYWRkIHRoZSByZXNvdXJjZSB0d2ljZS5cbiAgICAgIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgfSksXG4gICAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtdLFxuICAgICAgICAuLi5ncm91cGVkKFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcInByaWNpbmdcIixcbiAgICAgICAgICAgIHJvdXRlczogW1wiL3ByaWNpbmdcIl0sXG4gICAgICAgICAgICB0cmFpbGluZ1NsYXNoOiB0cnVlLFxuICAgICAgICAgICAgZnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJHcm91cEZuXCIsIHtcbiAgICAgICAgICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pLFxuICAgICAgfSk7XG4gICAgICBleHBlY3QoXG4gICAgICAgIHJlc291cmNlUGF0aHMoKS5maWx0ZXIoKHBhdGgpID0+ICFwYXRoLnN0YXJ0c1dpdGgoXCIvX25leHQvc3RhdGljXCIpKSxcbiAgICAgICkudG9FcXVhbChbXCIvX25leHRcIiwgXCIvcHJpY2luZ1wiLCBcIi97cHJveHkrfVwiXSk7XG4gICAgICBleHBlY3QoYW55VGFyZ2V0c0J5UGF0aCgpKS50b0VxdWFsKHtcbiAgICAgICAgXCIvcHJpY2luZ1wiOiBbXCJHcm91cEZuXCJdLFxuICAgICAgICBcIi97cHJveHkrfVwiOiBbXCJTZXJ2ZXJGblwiXSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJyZWplY3RzIGEgYmVoYXZpb3IgZm9yIGEgZ3JvdXAgaXQgd2FzIG5vdCBnaXZlblwiLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IGZ1bmN0aW9uR3JvdXBCZWhhdmlvcnMgfSA9IGdyb3VwZWQoW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJhcGlcIixcbiAgICAgICAgICByb3V0ZXM6IFtcIi9hcGkvKipcIl0sXG4gICAgICAgICAgZnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJHcm91cEZuXCIsIHtcbiAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgICAgZXhwZWN0KFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgICAgIHN0YXRpY0Fzc2V0c0J1Y2tldDogQnVja2V0LmZyb21CdWNrZXROYW1lKFxuICAgICAgICAgICAgICBzdGFjayxcbiAgICAgICAgICAgICAgXCJCdWNrZXRcIixcbiAgICAgICAgICAgICAgXCJteS1idWNrZXRcIixcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgcHVibGljRGlyRW50cmllczogW10sXG4gICAgICAgICAgICBmdW5jdGlvbkdyb3VwQmVoYXZpb3JzLFxuICAgICAgICAgIH0pLFxuICAgICAgKS50b1Rocm93KC9yb3V0ZXMgdG8gZnVuY3Rpb24gZ3JvdXAgXCJhcGlcIiwgd2hpY2ggaXMgbm90IGluLyk7XG4gICAgfSk7XG5cbiAgICBpdChcImFkZHMgbm8gZGF0YSByb3V0ZXMgZm9yIGFuIGFwcCB3aXRob3V0IFBhZ2VzIFJvdXRlciByb3V0ZXNcIiwgKCkgPT4ge1xuICAgICAgY3JlYXRlR3JvdXBlZEFwaShmYWxzZSk7XG5cbiAgICAgIGV4cGVjdChcbiAgICAgICAgcmVzb3VyY2VQYXRocygpLmZpbHRlcigocGF0aCkgPT4gcGF0aC5zdGFydHNXaXRoKFwiL19uZXh0L2RhdGFcIikpLFxuICAgICAgKS50b0VxdWFsKFtdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZ3JhbnRzIGVhY2ggZnVuY3Rpb24gb25lIEFQSS1zY29wZWQgcGVybWlzc2lvbiwgbm90IHR3byBwZXIgbWV0aG9kXCIsICgpID0+IHtcbiAgICAgIC8vIFBlci1tZXRob2QgcGVybWlzc2lvbnMgcHV0IHR3byBzdGF0ZW1lbnRzIGluIHRoZSBmdW5jdGlvbidzIHJlc291cmNlXG4gICAgICAvLyBwb2xpY3kgZm9yIGV2ZXJ5IGBBTllgLCB3aGljaCBvdXRncm93cyBMYW1iZGEncyAyMCBLQiBjYXAuXG4gICAgICBjcmVhdGVHcm91cGVkQXBpKHRydWUpO1xuXG4gICAgICBjb25zdCBwZXJtaXNzaW9ucyA9IE9iamVjdC52YWx1ZXMoXG4gICAgICAgIFRlbXBsYXRlLmZyb21TdGFjayhzdGFjaykuZmluZFJlc291cmNlcyhcIkFXUzo6TGFtYmRhOjpQZXJtaXNzaW9uXCIsIHtcbiAgICAgICAgICBQcm9wZXJ0aWVzOiB7IFByaW5jaXBhbDogXCJhcGlnYXRld2F5LmFtYXpvbmF3cy5jb21cIiB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBleHBlY3QocGVybWlzc2lvbnMpLnRvSGF2ZUxlbmd0aCgyKTtcbiAgICAgIGZvciAoY29uc3QgcGVybWlzc2lvbiBvZiBwZXJtaXNzaW9ucykge1xuICAgICAgICBjb25zdCBzb3VyY2VBcm4gPSBKU09OLnN0cmluZ2lmeShwZXJtaXNzaW9uLlByb3BlcnRpZXMuU291cmNlQXJuKTtcbiAgICAgICAgZXhwZWN0KHNvdXJjZUFybikudG9Db250YWluKFwiOmV4ZWN1dGUtYXBpOlwiKTtcbiAgICAgICAgZXhwZWN0KHNvdXJjZUFybikudG9Db250YWluKFwiLyovKi8qXCIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBpdChcIm5hbWVzIHRoZSBncm91cCBhbmQgcGF0dGVybiBBUEkgR2F0ZXdheSBjYW5ub3Qgcm91dGVcIiwgKCkgPT4ge1xuICAgIGV4cGVjdChcbiAgICAgICgpID0+XG4gICAgICAgIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgICBzdGF0aWNBc3NldHNCdWNrZXQ6IEJ1Y2tldC5mcm9tQnVja2V0TmFtZShcbiAgICAgICAgICAgIHN0YWNrLFxuICAgICAgICAgICAgXCJCdWNrZXRcIixcbiAgICAgICAgICAgIFwibXktYnVja2V0XCIsXG4gICAgICAgICAgKSxcbiAgICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbXSxcbiAgICAgICAgICAuLi5ncm91cGVkKFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbmFtZTogXCJhYm91dFwiLFxuICAgICAgICAgICAgICByb3V0ZXM6IFtcIi9hYm91dH51c1wiXSxcbiAgICAgICAgICAgICAgZnVuY3Rpb246IG5ldyBMYW1iZGFGdW5jdGlvbihzdGFjaywgXCJHcm91cEZuXCIsIHtcbiAgICAgICAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0pLFxuICAgICAgICB9KSxcbiAgICApLnRvVGhyb3coL3BhdHRlcm4gXCJcXC9hYm91dH51c1wiIFxcKGdyb3VwIFwiYWJvdXRcIlxcKSBoYXMgYSBzZWdtZW50Lyk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiYSBwdWJsaWMvIGVudHJ5IEFQSSBHYXRld2F5IGNhbm5vdCBhZGRyZXNzXCIsICgpID0+IHtcbiAgICBpdChcIndhcm5zIGFuZCBza2lwcyBpdCBpbnN0ZWFkIG9mIGZhaWxpbmcgdGhlIHN5bnRoXCIsICgpID0+IHtcbiAgICAgIC8vIGBwdWJsaWMvaGVsbG8gd29ybGQuanBnYCBpcyBhIHZhbGlkIE5leHQuanMgYXNzZXQgdGhhdCBgYWRkUmVzb3VyY2VgXG4gICAgICAvLyByZWplY3RzIG91dHJpZ2h0LCB0YWtpbmcgdGhlIHdob2xlIGFwcCdzIHN5bnRoIHdpdGggaXQuIFRoZSBHbG9iYWwgdHlwZXNcbiAgICAgIC8vIHNlcnZlIGl0IHdpdGggYSB3aWxkY2FyZCBwYXRoIHBhdHRlcm47IGhlcmUgdGhlIGhvbmVzdCBvdXRjb21lIGlzIG9uZVxuICAgICAgLy8gNDA0aW5nIGFzc2V0IGFuZCBhIHdhcm5pbmcgdGhhdCBuYW1lcyBpdC5cbiAgICAgIGNvbnN0IGFwaSA9IG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgICAgc3RhdGljQXNzZXRzQnVja2V0OiBCdWNrZXQuZnJvbUJ1Y2tldE5hbWUoc3RhY2ssIFwiQnVja2V0XCIsIFwibXktYnVja2V0XCIpLFxuICAgICAgICBzZXJ2ZXJGdW5jdGlvbjogbmV3IExhbWJkYUZ1bmN0aW9uKHN0YWNrLCBcIlNlcnZlckZuXCIsIHtcbiAgICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUlubGluZShcImV4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+IHt9O1wiKSxcbiAgICAgICAgfSksXG4gICAgICAgIHB1YmxpY0RpckVudHJpZXM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaGVsbG8gd29ybGQuanBnXCIsIGlzRGlyZWN0b3J5OiBmYWxzZSB9LFxuICAgICAgICAgIHsgbmFtZTogXCLDpMO2w7zFocSNxZnDrS5wbmdcIiwgaXNEaXJlY3Rvcnk6IGZhbHNlIH0sXG4gICAgICAgICAgeyBuYW1lOiBcImZhdmljb24uaWNvXCIsIGlzRGlyZWN0b3J5OiBmYWxzZSB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBBbm5vdGF0aW9ucy5mcm9tU3RhY2soc3RhY2spXG4gICAgICAgIC5maW5kV2FybmluZyhgLyR7YXBpLm5vZGUucGF0aH1gLCBNYXRjaC5hbnlWYWx1ZSgpKVxuICAgICAgICAubWFwKCh3YXJuaW5nKSA9PiB3YXJuaW5nLmVudHJ5LmRhdGEgYXMgc3RyaW5nKVxuICAgICAgICAuam9pbihcIlxcblwiKTtcbiAgICAgIGV4cGVjdChtZXNzYWdlKS50b0NvbnRhaW4oJ1wiaGVsbG8gd29ybGQuanBnXCInKTtcbiAgICAgIGV4cGVjdChtZXNzYWdlKS50b0NvbnRhaW4oJ1wiw6TDtsO8xaHEjcWZw60ucG5nXCInKTtcbiAgICAgIGV4cGVjdChtZXNzYWdlKS5ub3QudG9Db250YWluKCdcImZhdmljb24uaWNvXCInKTtcbiAgICAgIC8vIFRoZSBleHByZXNzaWJsZSBvbmUgaXMgc3RpbGwgc2VydmVkLlxuICAgICAgZXhwZWN0KHMzSW50ZWdyYXRpb25LZXlzKCkpLnRvQ29udGFpbihcImZhdmljb24uaWNvXCIpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcIk5leHRqc0FwaSByZWRlcGxveSBhZnRlciB1cGRhdGVcIiwgKCkgPT4ge1xuICBmdW5jdGlvbiBzeW50aChwcm9wczogUGFydGlhbDxOZXh0anNBcGlQcm9wcz4gPSB7fSkge1xuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKG5ldyBBcHAoKSwgXCJUZXN0U3RhY2tcIiwge1xuICAgICAgZW52OiB7IGFjY291bnQ6IFwiMTIzNDU2Nzg5MDEyXCIsIHJlZ2lvbjogXCJ1cy1lYXN0LTFcIiB9LFxuICAgIH0pO1xuICAgIG5ldyBOZXh0anNBcGkoc3RhY2ssIFwiTmV4dGpzQXBpXCIsIHtcbiAgICAgIHN0YXRpY0Fzc2V0c0J1Y2tldDogQnVja2V0LmZyb21CdWNrZXROYW1lKHN0YWNrLCBcIkJ1Y2tldFwiLCBcIm15LWJ1Y2tldFwiKSxcbiAgICAgIHNlcnZlckZ1bmN0aW9uOiBuZXcgTGFtYmRhRnVuY3Rpb24oc3RhY2ssIFwiU2VydmVyRm5cIiwge1xuICAgICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKFwiZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKCkgPT4ge307XCIpLFxuICAgICAgfSksXG4gICAgICBwdWJsaWNEaXJFbnRyaWVzOiBbXSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICAgIHJldHVybiBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICB9XG5cbiAgLyoqIFRoZSBgRm46OkpvaW5gIHBhcnRzIG9mIGV2ZXJ5IHJlc291cmNlIHRoZSByZWRlcGxveSByb2xlIGlzIGdyYW50ZWQuICovXG4gIGZ1bmN0aW9uIGdyYW50ZWRSZXNvdXJjZXModGVtcGxhdGU6IFRlbXBsYXRlKSB7XG4gICAgY29uc3QgW3BvbGljeV0gPSBPYmplY3QudmFsdWVzKFxuICAgICAgdGVtcGxhdGUuZmluZFJlc291cmNlcyhcIkFXUzo6SUFNOjpQb2xpY3lcIiwge1xuICAgICAgICBQcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgUG9saWN5TmFtZTogTWF0Y2guc3RyaW5nTGlrZVJlZ2V4cChcIlJlZGVwbG95Rm5cIiksXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiBwb2xpY3kuUHJvcGVydGllcy5Qb2xpY3lEb2N1bWVudC5TdGF0ZW1lbnQubWFwKFxuICAgICAgKHN0YXRlbWVudDogeyBBY3Rpb246IHN0cmluZzsgUmVzb3VyY2U6IHVua25vd24gfSkgPT4gKHtcbiAgICAgICAgYWN0aW9uOiBzdGF0ZW1lbnQuQWN0aW9uLFxuICAgICAgICByZXNvdXJjZXM6IEpTT04uc3RyaW5naWZ5KHN0YXRlbWVudC5SZXNvdXJjZSksXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgaXQoXCJyZWRlcGxveXMgdGhlIHN0YWdlIG9uIHRoaXMgc3RhY2sncyBVUERBVEVfQ09NUExFVEVcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHRlbXBsYXRlID0gc3ludGgoKTtcblxuICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6RXZlbnRzOjpSdWxlXCIsIHtcbiAgICAgIEV2ZW50UGF0dGVybjoge1xuICAgICAgICBzb3VyY2U6IFtcImF3cy5jbG91ZGZvcm1hdGlvblwiXSxcbiAgICAgICAgXCJkZXRhaWwtdHlwZVwiOiBbXCJDbG91ZEZvcm1hdGlvbiBTdGFjayBTdGF0dXMgQ2hhbmdlXCJdLFxuICAgICAgICBkZXRhaWw6IHtcbiAgICAgICAgICBcInN0YWNrLWlkXCI6IFt7IFJlZjogXCJBV1M6OlN0YWNrSWRcIiB9XSxcbiAgICAgICAgICBcInN0YXR1cy1kZXRhaWxzXCI6IHtcbiAgICAgICAgICAgIHN0YXR1czogW1wiVVBEQVRFX0NPTVBMRVRFXCIsIFwiVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFXCJdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgVGFyZ2V0czogW1xuICAgICAgICBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICBBcm46IHsgXCJGbjo6R2V0QXR0XCI6IFtNYXRjaC5zdHJpbmdMaWtlUmVnZXhwKFwiUmVkZXBsb3lGblwiKSwgXCJBcm5cIl0gfSxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH0pO1xuICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLCB7XG4gICAgICBIYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgIFJFU1RfQVBJX0lEOiB7IFJlZjogTWF0Y2guc3RyaW5nTGlrZVJlZ2V4cChcIlJlc3RBcGlcIikgfSxcbiAgICAgICAgICBTVEFHRV9OQU1FOiB7IFJlZjogTWF0Y2guc3RyaW5nTGlrZVJlZ2V4cChcIkRlcGxveW1lbnRTdGFnZVwiKSB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoXCJzY29wZXMgaXRzIEFQSSBHYXRld2F5IGFjY2VzcyB0byB0aGlzIFJFU1QgQVBJXCIsICgpID0+IHtcbiAgICBjb25zdCBzdGF0ZW1lbnRzID0gZ3JhbnRlZFJlc291cmNlcyhzeW50aCgpKTtcblxuICAgIGV4cGVjdChzdGF0ZW1lbnRzLm1hcCgoczogeyBhY3Rpb246IHN0cmluZyB9KSA9PiBzLmFjdGlvbikpLnRvRXF1YWwoW1xuICAgICAgXCJhcGlnYXRld2F5OlBPU1RcIixcbiAgICAgIFwiYXBpZ2F0ZXdheTpHRVRcIixcbiAgICAgIFwiYXBpZ2F0ZXdheTpERUxFVEVcIixcbiAgICBdKTtcbiAgICBmb3IgKGNvbnN0IHsgcmVzb3VyY2VzIH0gb2Ygc3RhdGVtZW50cykge1xuICAgICAgZXhwZWN0KHJlc291cmNlcykudG9Db250YWluKFwiL3Jlc3RhcGlzL1wiKTtcbiAgICAgIGV4cGVjdChyZXNvdXJjZXMpLnRvTWF0Y2goL1wiUmVmXCI6XCJOZXh0anNBcGlSZXN0QXBpWzAtOUEtRl0rXCIvKTtcbiAgICAgIGV4cGVjdChyZXNvdXJjZXMpLm5vdC50b01hdGNoKC9yZXN0YXBpc1xcL1xcKi8pO1xuICAgIH1cbiAgICBleHBlY3Qoc3RhdGVtZW50c1swXS5yZXNvdXJjZXMpLnRvQ29udGFpbihcIi9kZXBsb3ltZW50c1wiKTtcbiAgICBleHBlY3Qoc3RhdGVtZW50c1syXS5yZXNvdXJjZXMpLnRvQ29udGFpbihcIi9kZXBsb3ltZW50cy8qXCIpO1xuICB9KTtcblxuICBpdChcImlzIG9mZiB3aGVuIHJlZGVwbG95QWZ0ZXJVcGRhdGUgaXMgZmFsc2VcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHRlbXBsYXRlID0gc3ludGgoeyByZWRlcGxveUFmdGVyVXBkYXRlOiBmYWxzZSB9KTtcblxuICAgIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6RXZlbnRzOjpSdWxlXCIsIDApO1xuICB9KTtcblxuICBpdChcImlzIG9mZiB3aGVuIHRoZSBBUEkgZGVwbG95cyBubyBzdGFnZVwiLCAoKSA9PiB7XG4gICAgY29uc3QgdGVtcGxhdGUgPSBzeW50aCh7XG4gICAgICBvdmVycmlkZXM6IHsgcmVzdEFwaVByb3BzOiB7IGRlcGxveTogZmFsc2UgfSB9LFxuICAgIH0pO1xuXG4gICAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpFdmVudHM6OlJ1bGVcIiwgMCk7XG4gIH0pO1xuXG4gIGl0KFwidGFrZXMgZnVuY3Rpb24gb3ZlcnJpZGVzXCIsICgpID0+IHtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9IHN5bnRoKHtcbiAgICAgIG92ZXJyaWRlczogeyByZWRlcGxveUZ1bmN0aW9uUHJvcHM6IHsgbWVtb3J5U2l6ZTogNTEyIH0gfSxcbiAgICB9KTtcblxuICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLCB7XG4gICAgICBNZW1vcnlTaXplOiA1MTIsXG4gICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICBWYXJpYWJsZXM6IHsgUkVTVF9BUElfSUQ6IE1hdGNoLmFueVZhbHVlKCkgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|