cdk-nextjs 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2404 -2723
- package/.jsii.tabl.json +1 -1
- package/API.md +1681 -1930
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +667 -4
- package/docs/caching-guide.md +156 -112
- package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
- package/docs/development-guide.md +1 -1
- package/docs/harness-coverage.md +598 -0
- package/docs/init-cache-deployment.md +32 -1
- package/docs/next-build-output-guide.md +30 -20
- package/examples/README.md +5 -1
- package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
- package/lib/adapter/__fixtures__/app-playground.json +4917 -0
- package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
- package/lib/adapter/adapter.mjs +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 +8 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +2 -4
- package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
- package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
- package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
- package/lib/lambdas/post-deploy/prune-s3.js +41 -12
- package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
- package/lib/nextjs-api.d.ts +102 -18
- package/lib/nextjs-api.js +338 -38
- package/lib/nextjs-api.test.js +537 -1
- package/lib/nextjs-build/global-containers.Dockerfile +15 -10
- package/lib/nextjs-build/nextjs-build.d.ts +339 -63
- package/lib/nextjs-build/nextjs-build.js +684 -327
- package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
- package/lib/nextjs-build/nextjs-build.test.js +412 -0
- package/lib/nextjs-build/patch-fetch.js +1 -1
- package/lib/nextjs-build/patch-fetch.test.js +166 -11
- package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
- package/lib/nextjs-cache.d.ts +82 -4
- package/lib/nextjs-cache.js +186 -10
- package/lib/nextjs-cache.test.js +176 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
- package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
- package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
- package/lib/nextjs-compute/nextjs-containers.js +57 -20
- package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
- package/lib/nextjs-compute/nextjs-functions.js +113 -67
- package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
- package/lib/nextjs-distribution.d.ts +194 -23
- package/lib/nextjs-distribution.js +535 -62
- package/lib/nextjs-distribution.test.d.ts +1 -0
- package/lib/nextjs-distribution.test.js +697 -0
- package/lib/nextjs-post-deploy.d.ts +13 -5
- package/lib/nextjs-post-deploy.js +13 -10
- package/lib/nextjs-post-deploy.test.d.ts +1 -0
- package/lib/nextjs-post-deploy.test.js +34 -0
- package/lib/nextjs-static-assets.d.ts +17 -4
- package/lib/nextjs-static-assets.js +22 -5
- package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
- package/lib/root-constructs/nextjs-base-construct.js +139 -47
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -71
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -70
- package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
- package/lib/root-constructs/nextjs-regional-containers.js +8 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -26
- package/lib/runtime/api-gateway-path.d.ts +34 -0
- package/lib/runtime/api-gateway-path.js +71 -0
- package/lib/runtime/api-gateway-path.test.d.ts +1 -0
- package/lib/runtime/api-gateway-path.test.js +65 -0
- package/lib/runtime/case-redirect.d.ts +22 -0
- package/lib/runtime/case-redirect.js +63 -0
- package/lib/runtime/case-redirect.test.d.ts +1 -0
- package/lib/runtime/case-redirect.test.js +32 -0
- package/lib/runtime/core.d.ts +234 -0
- package/lib/runtime/core.js +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 +106 -13
- package/lib/utils/base-path.js +254 -41
- package/lib/utils/base-path.test.js +219 -51
- package/lib/utils/get-architecture.d.ts +7 -8
- package/lib/utils/get-architecture.js +12 -13
- package/lib/utils/zip-directory.d.ts +14 -0
- package/lib/utils/zip-directory.js +121 -0
- package/lib/utils/zip-directory.test.d.ts +1 -0
- package/lib/utils/zip-directory.test.js +99 -0
- package/package.json +22 -3
- package/scripts/capture-adapter-fixture.mjs +325 -0
- package/scripts/e2e-deploy.sh +398 -0
- package/scripts/e2e-harness/README.md +707 -0
- package/scripts/e2e-harness/app.js +370 -0
- package/scripts/e2e-harness/common.sh +249 -0
- package/scripts/e2e-harness/screen.mjs +302 -0
- package/scripts/e2e-harness/stage-proxy.mjs +145 -0
- package/scripts/e2e-harness/type-filters.mjs +47 -0
- package/scripts/e2e-logs.sh +75 -0
- package/scripts/e2e-offline.sh +91 -0
- package/scripts/e2e-sweep.sh +370 -0
- package/scripts/e2e-warm.sh +114 -0
- package/scripts/zero-config-build.mjs +418 -0
- package/docs/1k-concurrent-users-executions.png +0 -0
- package/docs/plans/adapter-runtime-release.md +0 -362
- package/docs/plans/phase-0-image-function-opt-in.md +0 -295
- package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
- package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
- package/lib/image-optimization/handler-utils.d.ts +0 -34
- package/lib/image-optimization/handler-utils.js +0 -83
- package/lib/image-optimization/handler-utils.test.js +0 -178
- package/lib/nextjs-build/functions.Dockerfile +0 -31
- package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
- package/lib/nextjs-compute/nextjs-image-function.js +0 -59
- package/lib/utils/experimental-flags.d.ts +0 -24
- package/lib/utils/experimental-flags.js +0 -30
- /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
4
|
+
jest.mock("@aws-sdk/client-s3");
|
|
5
|
+
// The real module, with the one step that needs `sharp` stubbed out: these tests
|
|
6
|
+
// are about the response `handle` writes, not about optimizing an image.
|
|
7
|
+
jest.mock("next/dist/server/image-optimizer.js", () => ({
|
|
8
|
+
...jest.requireActual("next/dist/server/image-optimizer.js"),
|
|
9
|
+
imageOptimizer: jest.fn(),
|
|
10
|
+
}));
|
|
11
|
+
const node_fs_1 = require("node:fs");
|
|
12
|
+
const node_http_1 = require("node:http");
|
|
13
|
+
const node_os_1 = require("node:os");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
const node_stream_1 = require("node:stream");
|
|
16
|
+
const image_optimizer_js_1 = require("next/dist/server/image-optimizer.js");
|
|
17
|
+
const image_config_js_1 = require("next/dist/shared/lib/image-config.js");
|
|
18
|
+
const request_1 = require("./http/request");
|
|
19
|
+
const response_1 = require("./http/response");
|
|
20
|
+
const sink_1 = require("./http/sink");
|
|
21
|
+
const image_1 = require("./image");
|
|
22
|
+
const next_modules_1 = require("./next-modules");
|
|
23
|
+
const PNG = Buffer.from("optimized-bytes");
|
|
24
|
+
const ETAG = "abc123";
|
|
25
|
+
/** Just what `loadImageRuntime` reads: where `required-server-files.json` is. */
|
|
26
|
+
function stage(extraConfig = {}) {
|
|
27
|
+
const root = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-image-"));
|
|
28
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.join)(root, ".next"));
|
|
29
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(root, ".next/required-server-files.json"), JSON.stringify({
|
|
30
|
+
config: {
|
|
31
|
+
basePath: "",
|
|
32
|
+
experimental: {},
|
|
33
|
+
images: { ...image_config_js_1.imageConfigDefault, localPatterns: undefined },
|
|
34
|
+
...extraConfig,
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
return root;
|
|
38
|
+
}
|
|
39
|
+
/** The app's `cacheHandler`, reduced to a map: what the S3 handler is to it. */
|
|
40
|
+
class MapCacheHandler {
|
|
41
|
+
static entries = new Map();
|
|
42
|
+
static options;
|
|
43
|
+
constructor(options) {
|
|
44
|
+
MapCacheHandler.options = options;
|
|
45
|
+
}
|
|
46
|
+
async get(key) {
|
|
47
|
+
return MapCacheHandler.entries.get(key) ?? null;
|
|
48
|
+
}
|
|
49
|
+
async set(key, value) {
|
|
50
|
+
MapCacheHandler.entries.set(key, { value, lastModified: Date.now() });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
let imported;
|
|
54
|
+
const s3Hit = {
|
|
55
|
+
send: async () => ({
|
|
56
|
+
Body: [Buffer.from("upstream-bytes")],
|
|
57
|
+
ContentType: "image/png",
|
|
58
|
+
ETag: '"upstream"',
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
/** An optimizer over {@link MapCacheHandler}, as the adapter configures one. */
|
|
62
|
+
function optimizerFor(options = {}) {
|
|
63
|
+
const via = new image_1.RuntimeImageOptimizer({
|
|
64
|
+
deploymentRoot: stage({
|
|
65
|
+
cacheHandler: "../node_modules/cdk-nextjs/lib/adapter/cache-handler.mjs",
|
|
66
|
+
cacheMaxMemorySize: 0,
|
|
67
|
+
...(options.images
|
|
68
|
+
? {
|
|
69
|
+
images: {
|
|
70
|
+
...image_config_js_1.imageConfigDefault,
|
|
71
|
+
localPatterns: undefined,
|
|
72
|
+
...options.images,
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
: {}),
|
|
76
|
+
}),
|
|
77
|
+
manifest: {
|
|
78
|
+
relativeProjectDir: "",
|
|
79
|
+
config: { distDir: ".next" },
|
|
80
|
+
},
|
|
81
|
+
bucket: options.bucket ?? "assets",
|
|
82
|
+
bucketKeyPrefix: "",
|
|
83
|
+
fetchInternal: options.fetchInternal ??
|
|
84
|
+
(async () => {
|
|
85
|
+
throw new Error("Unexpected fetchInternal");
|
|
86
|
+
}),
|
|
87
|
+
importModule: options.importModule ??
|
|
88
|
+
(async (url) => {
|
|
89
|
+
imported = url;
|
|
90
|
+
return { default: MapCacheHandler };
|
|
91
|
+
}),
|
|
92
|
+
});
|
|
93
|
+
via.s3 = options.s3 ?? s3Hit;
|
|
94
|
+
return via;
|
|
95
|
+
}
|
|
96
|
+
let optimizer;
|
|
97
|
+
beforeAll(() => {
|
|
98
|
+
(0, next_modules_1.useNextFrom)((0, node_path_1.join)(__dirname, "../.."));
|
|
99
|
+
optimizer = optimizerFor();
|
|
100
|
+
});
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
MapCacheHandler.entries.clear();
|
|
103
|
+
imported = undefined;
|
|
104
|
+
image_optimizer_js_1.imageOptimizer.mockClear();
|
|
105
|
+
image_optimizer_js_1.imageOptimizer.mockResolvedValue({
|
|
106
|
+
buffer: PNG,
|
|
107
|
+
contentType: "image/webp",
|
|
108
|
+
maxAge: 60,
|
|
109
|
+
etag: ETAG,
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
async function request(src, init = {}) {
|
|
113
|
+
const url = new URL(`https://shop.example.test/_next/image?url=${encodeURIComponent(src)}&w=640&q=75`);
|
|
114
|
+
const req = new request_1.ShimIncomingMessage({
|
|
115
|
+
method: init.method ?? "GET",
|
|
116
|
+
url: `${url.pathname}${url.search}`,
|
|
117
|
+
headers: { accept: "image/webp", ...init.headers },
|
|
118
|
+
});
|
|
119
|
+
const res = new response_1.ShimServerResponse();
|
|
120
|
+
let head;
|
|
121
|
+
const chunks = [];
|
|
122
|
+
const done = (0, sink_1.pipeToSink)(req, res, {
|
|
123
|
+
begin(responseHead) {
|
|
124
|
+
head = responseHead;
|
|
125
|
+
return new node_stream_1.Writable({
|
|
126
|
+
write(chunk, _encoding, callback) {
|
|
127
|
+
chunks.push(Buffer.from(chunk));
|
|
128
|
+
callback();
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
}, { compress: false });
|
|
133
|
+
const pending = [];
|
|
134
|
+
await (init.via ?? optimizer).handle(req, res, url, init.waitUntil ?? ((promise) => pending.push(promise)));
|
|
135
|
+
await done;
|
|
136
|
+
// Settled, not awaited: the runtime logs a rejection rather than failing on it.
|
|
137
|
+
await Promise.allSettled(pending);
|
|
138
|
+
return { head: head, body: Buffer.concat(chunks).toString() };
|
|
139
|
+
}
|
|
140
|
+
describe("RuntimeImageOptimizer.isEnabled", () => {
|
|
141
|
+
const withImages = (images) => optimizerFor({ images });
|
|
142
|
+
// Where `next start` answers 404 rather than optimize.
|
|
143
|
+
it("is off for images.unoptimized and for a non-default loader", () => {
|
|
144
|
+
expect(withImages({}).isEnabled()).toBe(true);
|
|
145
|
+
expect(withImages({ unoptimized: true }).isEnabled()).toBe(false);
|
|
146
|
+
expect(withImages({ loader: "custom", loaderFile: "./loader.js" }).isEnabled()).toBe(false);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe("RuntimeImageOptimizer response", () => {
|
|
150
|
+
it("answers with the headers next start sends", async () => {
|
|
151
|
+
const { head, body } = await request("/photos/logo.png");
|
|
152
|
+
expect(head.statusCode).toBe(200);
|
|
153
|
+
expect(head.headers).toMatchObject({
|
|
154
|
+
"cache-control": "public, max-age=60, must-revalidate",
|
|
155
|
+
"content-type": "image/webp",
|
|
156
|
+
"content-length": String(PNG.length),
|
|
157
|
+
"content-disposition": 'attachment; filename="logo.webp"',
|
|
158
|
+
"content-security-policy": image_config_js_1.imageConfigDefault.contentSecurityPolicy,
|
|
159
|
+
etag: ETAG,
|
|
160
|
+
vary: "Accept",
|
|
161
|
+
"x-nextjs-cache": "MISS",
|
|
162
|
+
});
|
|
163
|
+
expect(body).toBe(PNG.toString());
|
|
164
|
+
});
|
|
165
|
+
// Content-hashed, so the name changes whenever the bytes do.
|
|
166
|
+
it("caches a statically imported image for a year, immutable", async () => {
|
|
167
|
+
const { head } = await request("/_next/static/media/logo.3f2a1c.png");
|
|
168
|
+
expect(head.headers["cache-control"]).toBe("public, max-age=315360000, immutable");
|
|
169
|
+
});
|
|
170
|
+
// `writeHead` rejects a header value outside latin1 with ERR_INVALID_CHAR,
|
|
171
|
+
// and the Lambda sink writes the head through it.
|
|
172
|
+
it("encodes a non-latin1 filename rather than sending it raw", async () => {
|
|
173
|
+
const { head } = await request("/ümlaut-写真.png");
|
|
174
|
+
const disposition = head.headers["content-disposition"];
|
|
175
|
+
expect(disposition).toMatch(/^attachment; filename="[^"]*"; filename\*=/);
|
|
176
|
+
expect(disposition).toContain(`filename*=UTF-8''${encodeURIComponent("ümlaut-写真.webp")}`);
|
|
177
|
+
expect(() => (0, node_http_1.validateHeaderValue)("Content-Disposition", disposition)).not.toThrow();
|
|
178
|
+
});
|
|
179
|
+
it.each([
|
|
180
|
+
["the exact tag", ETAG],
|
|
181
|
+
["a weak form of it", `W/${ETAG}`],
|
|
182
|
+
["a list containing it", `"other", ${ETAG}`],
|
|
183
|
+
["a wildcard", "*"],
|
|
184
|
+
])("answers 304 to If-None-Match with %s", async (_name, ifNoneMatch) => {
|
|
185
|
+
const { head, body } = await request("/logo.png", {
|
|
186
|
+
headers: { "if-none-match": ifNoneMatch },
|
|
187
|
+
});
|
|
188
|
+
expect(head.statusCode).toBe(304);
|
|
189
|
+
expect(head.headers.etag).toBe(ETAG);
|
|
190
|
+
expect(head.headers["cache-control"]).toBe("public, max-age=60, must-revalidate");
|
|
191
|
+
expect(body).toBe("");
|
|
192
|
+
});
|
|
193
|
+
it("answers 200 to an If-None-Match that does not match", async () => {
|
|
194
|
+
const { head } = await request("/logo.png", {
|
|
195
|
+
headers: { "if-none-match": '"other"' },
|
|
196
|
+
});
|
|
197
|
+
expect(head.statusCode).toBe(200);
|
|
198
|
+
});
|
|
199
|
+
it("sends the headers but no body to HEAD", async () => {
|
|
200
|
+
const { head, body } = await request("/logo.png", { method: "HEAD" });
|
|
201
|
+
expect(head.statusCode).toBe(200);
|
|
202
|
+
expect(head.headers["content-length"]).toBe(String(PNG.length));
|
|
203
|
+
expect(body).toBe("");
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
describe("RuntimeImageOptimizer sources", () => {
|
|
207
|
+
// `next start` fetches a remote source only when `remotePatterns` or `domains`
|
|
208
|
+
// allow it; the stage's config allows none. Anything else would make the
|
|
209
|
+
// optimizer an open proxy into whatever it can reach.
|
|
210
|
+
it.each([
|
|
211
|
+
["another origin", "https://evil.example.test/x.png"],
|
|
212
|
+
["instance metadata", "http://169.254.169.254/latest/meta-data/"],
|
|
213
|
+
["a protocol-relative url", "//evil.example.test/x.png"],
|
|
214
|
+
])("rejects a remote source that is not allowed: %s", async (_name, src) => {
|
|
215
|
+
const { head, body } = await request(src);
|
|
216
|
+
expect(head.statusCode).toBe(400);
|
|
217
|
+
expect(body).toMatch(/"url" parameter/);
|
|
218
|
+
expect(image_optimizer_js_1.imageOptimizer).not.toHaveBeenCalled();
|
|
219
|
+
});
|
|
220
|
+
function withS3Miss(fetchInternal) {
|
|
221
|
+
return optimizerFor({
|
|
222
|
+
fetchInternal,
|
|
223
|
+
s3: {
|
|
224
|
+
send: async () => {
|
|
225
|
+
throw Object.assign(new Error("missing"), { name: "NoSuchKey" });
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
it("falls back to the app's routes for a source S3 has no file for", async () => {
|
|
231
|
+
const fetchInternal = jest.fn(async () => ({
|
|
232
|
+
statusCode: 200,
|
|
233
|
+
headers: {
|
|
234
|
+
"content-type": "image/png",
|
|
235
|
+
"cache-control": "public, max-age=120",
|
|
236
|
+
},
|
|
237
|
+
body: Buffer.from("route-bytes"),
|
|
238
|
+
}));
|
|
239
|
+
const { head } = await request("/api/avatar?id=42", {
|
|
240
|
+
via: withS3Miss(fetchInternal),
|
|
241
|
+
});
|
|
242
|
+
expect(head.statusCode).toBe(200);
|
|
243
|
+
expect(fetchInternal).toHaveBeenCalledWith("/api/avatar?id=42", expect.anything(), image_config_js_1.imageConfigDefault.maximumResponseBody);
|
|
244
|
+
expect(image_optimizer_js_1.imageOptimizer.mock.lastCall[0]).toMatchObject({
|
|
245
|
+
buffer: Buffer.from("route-bytes"),
|
|
246
|
+
contentType: "image/png",
|
|
247
|
+
cacheControl: "public, max-age=120",
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
// `NextjsRegionalContainers`: the file is on disk, and a GetObject for it is
|
|
251
|
+
// a wasted round trip.
|
|
252
|
+
it("goes straight to the app's routes when there is no bucket", async () => {
|
|
253
|
+
const send = jest.fn();
|
|
254
|
+
const fetchInternal = jest.fn(async () => ({
|
|
255
|
+
statusCode: 200,
|
|
256
|
+
headers: { "content-type": "image/png" },
|
|
257
|
+
body: Buffer.from("disk-bytes"),
|
|
258
|
+
}));
|
|
259
|
+
const { head } = await request("/logo.png", {
|
|
260
|
+
via: optimizerFor({
|
|
261
|
+
bucket: "",
|
|
262
|
+
fetchInternal,
|
|
263
|
+
s3: { send },
|
|
264
|
+
}),
|
|
265
|
+
});
|
|
266
|
+
expect(head.statusCode).toBe(200);
|
|
267
|
+
expect(send).not.toHaveBeenCalled();
|
|
268
|
+
expect(fetchInternal).toHaveBeenCalledWith("/logo.png", expect.anything(), image_config_js_1.imageConfigDefault.maximumResponseBody);
|
|
269
|
+
});
|
|
270
|
+
it("answers 400 when the route sends no body", async () => {
|
|
271
|
+
const { head } = await request("/api/avatar?id=42", {
|
|
272
|
+
via: withS3Miss(async () => ({
|
|
273
|
+
statusCode: 404,
|
|
274
|
+
headers: {},
|
|
275
|
+
body: Buffer.alloc(0),
|
|
276
|
+
})),
|
|
277
|
+
});
|
|
278
|
+
expect(head.statusCode).toBe(400);
|
|
279
|
+
});
|
|
280
|
+
it("answers an explicit 502 for a source served by another functionGroups group", async () => {
|
|
281
|
+
const error = jest.spyOn(console, "error").mockImplementation(() => { });
|
|
282
|
+
try {
|
|
283
|
+
const { head, body } = await request("/api/avatar?id=42", {
|
|
284
|
+
via: withS3Miss(async () => ({
|
|
285
|
+
statusCode: 0,
|
|
286
|
+
headers: {},
|
|
287
|
+
body: Buffer.alloc(0),
|
|
288
|
+
otherGroup: "avatars",
|
|
289
|
+
})),
|
|
290
|
+
});
|
|
291
|
+
expect(head.statusCode).toBe(502);
|
|
292
|
+
expect(body).toMatch(/another functionGroups group/);
|
|
293
|
+
expect(image_optimizer_js_1.imageOptimizer).not.toHaveBeenCalled();
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
error.mockRestore();
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
// `images.maximumResponseBody`, which `next start` enforces on local
|
|
300
|
+
// sources too: past it, the source is not read into memory.
|
|
301
|
+
it("answers 413 for a route response over maximumResponseBody", async () => {
|
|
302
|
+
const { head } = await request("/api/export", {
|
|
303
|
+
via: withS3Miss(async () => ({
|
|
304
|
+
statusCode: 0,
|
|
305
|
+
headers: {},
|
|
306
|
+
body: Buffer.alloc(0),
|
|
307
|
+
tooLarge: true,
|
|
308
|
+
})),
|
|
309
|
+
});
|
|
310
|
+
expect(head.statusCode).toBe(413);
|
|
311
|
+
expect(image_optimizer_js_1.imageOptimizer).not.toHaveBeenCalled();
|
|
312
|
+
});
|
|
313
|
+
it("answers 413 for an S3 object over maximumResponseBody", async () => {
|
|
314
|
+
const { head } = await request("/video.mp4", {
|
|
315
|
+
via: optimizerFor({
|
|
316
|
+
images: { maximumResponseBody: 10 },
|
|
317
|
+
s3: {
|
|
318
|
+
send: async () => ({
|
|
319
|
+
Body: [Buffer.from("never read")],
|
|
320
|
+
ContentLength: 11,
|
|
321
|
+
}),
|
|
322
|
+
},
|
|
323
|
+
}),
|
|
324
|
+
});
|
|
325
|
+
expect(head.statusCode).toBe(413);
|
|
326
|
+
expect(image_optimizer_js_1.imageOptimizer).not.toHaveBeenCalled();
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
describe("RuntimeImageOptimizer cache", () => {
|
|
330
|
+
it("optimizes once, then answers from the cache handler", async () => {
|
|
331
|
+
const via = optimizerFor();
|
|
332
|
+
const first = await request("/photos/cached.png", { via });
|
|
333
|
+
expect(first.head.headers["x-nextjs-cache"]).toBe("MISS");
|
|
334
|
+
expect(first.body).toBe(PNG.toString());
|
|
335
|
+
const second = await request("/photos/cached.png", { via });
|
|
336
|
+
expect(second.head.statusCode).toBe(200);
|
|
337
|
+
expect(second.head.headers["x-nextjs-cache"]).toBe("HIT");
|
|
338
|
+
expect(second.body).toBe(PNG.toString());
|
|
339
|
+
expect(second.head.headers.etag).toBe(ETAG);
|
|
340
|
+
expect(image_optimizer_js_1.imageOptimizer).toHaveBeenCalledTimes(1);
|
|
341
|
+
// The entry `next start` would have written.
|
|
342
|
+
const [entry] = [...MapCacheHandler.entries.values()];
|
|
343
|
+
expect(entry.value).toMatchObject({ kind: "IMAGE", extension: "webp" });
|
|
344
|
+
});
|
|
345
|
+
// Another instance: nothing in memory, so the hit is the cache handler's.
|
|
346
|
+
it("shares the optimized image across instances", async () => {
|
|
347
|
+
await request("/photos/shared.png", { via: optimizerFor() });
|
|
348
|
+
const other = await request("/photos/shared.png", { via: optimizerFor() });
|
|
349
|
+
expect(other.head.headers["x-nextjs-cache"]).toBe("HIT");
|
|
350
|
+
expect(image_optimizer_js_1.imageOptimizer).toHaveBeenCalledTimes(1);
|
|
351
|
+
});
|
|
352
|
+
// `required-server-files.json` names it relative to the dist dir.
|
|
353
|
+
it("loads the app's cacheHandler from where next start would", async () => {
|
|
354
|
+
await request("/photos/cached.png", { via: optimizerFor() });
|
|
355
|
+
expect(imported).toMatch(/^file:\/\/.*\/node_modules\/cdk-nextjs\/lib\/adapter\/cache-handler\.mjs$/);
|
|
356
|
+
expect(MapCacheHandler.options).toMatchObject({ dev: false });
|
|
357
|
+
});
|
|
358
|
+
// A transient failure loading the cacheHandler (EMFILE in a cold-start
|
|
359
|
+
// burst) must not fail every later image request on the instance.
|
|
360
|
+
it("retries loading the cacheHandler after a failed load", async () => {
|
|
361
|
+
const error = jest.spyOn(console, "error").mockImplementation(() => { });
|
|
362
|
+
try {
|
|
363
|
+
const importModule = jest
|
|
364
|
+
.fn()
|
|
365
|
+
.mockRejectedValueOnce(new Error("EMFILE"))
|
|
366
|
+
.mockResolvedValue({ default: MapCacheHandler });
|
|
367
|
+
const via = optimizerFor({ importModule });
|
|
368
|
+
expect((await request("/photos/retry.png", { via })).head.statusCode).toBe(500);
|
|
369
|
+
expect((await request("/photos/retry.png", { via })).head.statusCode).toBe(200);
|
|
370
|
+
expect(importModule).toHaveBeenCalledTimes(2);
|
|
371
|
+
}
|
|
372
|
+
finally {
|
|
373
|
+
error.mockRestore();
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
// The write of a fresh image goes to `waitUntil`, not in front of the
|
|
377
|
+
// response: the image is sent before the cache handler has it.
|
|
378
|
+
it("writes a miss to the cache after answering, through waitUntil", async () => {
|
|
379
|
+
// A write that can't finish until released: if the response waited on it,
|
|
380
|
+
// `request` would never return.
|
|
381
|
+
let release;
|
|
382
|
+
const gate = new Promise((resolve) => (release = resolve));
|
|
383
|
+
const set = MapCacheHandler.prototype.set;
|
|
384
|
+
MapCacheHandler.prototype.set = async function (key, value) {
|
|
385
|
+
await gate;
|
|
386
|
+
return set.call(this, key, value);
|
|
387
|
+
};
|
|
388
|
+
try {
|
|
389
|
+
const pending = [];
|
|
390
|
+
const first = await request("/photos/deferred.png", {
|
|
391
|
+
via: optimizerFor(),
|
|
392
|
+
waitUntil: (promise) => pending.push(promise),
|
|
393
|
+
});
|
|
394
|
+
expect(first.head.headers["x-nextjs-cache"]).toBe("MISS");
|
|
395
|
+
expect(MapCacheHandler.entries.size).toBe(0);
|
|
396
|
+
release();
|
|
397
|
+
await Promise.all(pending);
|
|
398
|
+
expect(MapCacheHandler.entries.size).toBe(1);
|
|
399
|
+
}
|
|
400
|
+
finally {
|
|
401
|
+
MapCacheHandler.prototype.set = set;
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2ltYWdlLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxzREFBc0Q7QUFDdEQsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBQ2hDLGlGQUFpRjtBQUNqRix5RUFBeUU7QUFDekUsSUFBSSxDQUFDLElBQUksQ0FBQyxxQ0FBcUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3RELEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxxQ0FBcUMsQ0FBQztJQUM1RCxjQUFjLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtDQUMxQixDQUFDLENBQUMsQ0FBQztBQUVKLHFDQUFnRTtBQUNoRSx5Q0FBZ0Q7QUFDaEQscUNBQWlDO0FBQ2pDLHlDQUFpQztBQUNqQyw2Q0FBdUM7QUFFdkMsNEVBQXFFO0FBQ3JFLDBFQUEwRTtBQUMxRSw0Q0FBcUQ7QUFDckQsOENBQW1FO0FBQ25FLHNDQUF5QztBQUN6QyxtQ0FBdUU7QUFFdkUsaURBQTZDO0FBRTdDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUMzQyxNQUFNLElBQUksR0FBRyxRQUFRLENBQUM7QUFFdEIsaUZBQWlGO0FBQ2pGLFNBQVMsS0FBSyxDQUFDLGNBQXVDLEVBQUU7SUFDdEQsTUFBTSxJQUFJLEdBQUcsSUFBQSxxQkFBVyxFQUFDLElBQUEsZ0JBQUksRUFBQyxJQUFBLGdCQUFNLEdBQUUsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7SUFDOUQsSUFBQSxtQkFBUyxFQUFDLElBQUEsZ0JBQUksRUFBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMvQixJQUFBLHVCQUFhLEVBQ1gsSUFBQSxnQkFBSSxFQUFDLElBQUksRUFBRSxrQ0FBa0MsQ0FBQyxFQUM5QyxJQUFJLENBQUMsU0FBUyxDQUFD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R0FBRyxDQUFDO1FBQzFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsR0FBRyxHQUFHLEtBQUssV0FBVyxHQUFHLEVBQUUsS0FBSztZQUN4RCxNQUFNLElBQUksQ0FBQztZQUNYLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQztRQUNGLElBQUksQ0FBQztZQUNILE1BQU0sT0FBTyxHQUE0QixFQUFFLENBQUM7WUFDNUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsc0JBQXNCLEVBQUU7Z0JBQ2xELEdBQUcsRUFBRSxZQUFZLEVBQUU7Z0JBQ25CLFNBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7YUFDOUMsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDMUQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTdDLE9BQU8sRUFBRSxDQUFDO1lBQ1YsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQyxDQUFDO2dCQUFTLENBQUM7WUFDVCxlQUFlLENBQUMsU0FBUyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDdEMsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmplc3QubW9jayhcIkBhd3Mtc2RrL2NsaWVudC1zM1wiKTtcbi8vIFRoZSByZWFsIG1vZHVsZSwgd2l0aCB0aGUgb25lIHN0ZXAgdGhhdCBuZWVkcyBgc2hhcnBgIHN0dWJiZWQgb3V0OiB0aGVzZSB0ZXN0c1xuLy8gYXJlIGFib3V0IHRoZSByZXNwb25zZSBgaGFuZGxlYCB3cml0ZXMsIG5vdCBhYm91dCBvcHRpbWl6aW5nIGFuIGltYWdlLlxuamVzdC5tb2NrKFwibmV4dC9kaXN0L3NlcnZlci9pbWFnZS1vcHRpbWl6ZXIuanNcIiwgKCkgPT4gKHtcbiAgLi4uamVzdC5yZXF1aXJlQWN0dWFsKFwibmV4dC9kaXN0L3NlcnZlci9pbWFnZS1vcHRpbWl6ZXIuanNcIiksXG4gIGltYWdlT3B0aW1pemVyOiBqZXN0LmZuKCksXG59KSk7XG5cbmltcG9ydCB7IG1rZGlyU3luYywgbWtkdGVtcFN5bmMsIHdyaXRlRmlsZVN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgdmFsaWRhdGVIZWFkZXJWYWx1ZSB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgV3JpdGFibGUgfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB7IFMzQ2xpZW50IH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1zM1wiO1xuaW1wb3J0IHsgaW1hZ2VPcHRpbWl6ZXIgfSBmcm9tIFwibmV4dC9kaXN0L3NlcnZlci9pbWFnZS1vcHRpbWl6ZXIuanNcIjtcbmltcG9ydCB7IGltYWdlQ29uZmlnRGVmYXVsdCB9IGZyb20gXCJuZXh0L2Rpc3Qvc2hhcmVkL2xpYi9pbWFnZS1jb25maWcuanNcIjtcbmltcG9ydCB7IFNoaW1JbmNvbWluZ01lc3NhZ2UgfSBmcm9tIFwiLi9odHRwL3JlcXVlc3RcIjtcbmltcG9ydCB7IFJlc3BvbnNlSGVhZCwgU2hpbVNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIi4vaHR0cC9yZXNwb25zZVwiO1xuaW1wb3J0IHsgcGlwZVRvU2luayB9IGZyb20gXCIuL2h0dHAvc2lua1wiO1xuaW1wb3J0IHsgSW1hZ2VPcHRpbWl6ZXJPcHRpb25zLCBSdW50aW1lSW1hZ2VPcHRpbWl6ZXIgfSBmcm9tIFwiLi9pbWFnZVwiO1xuaW1wb3J0IHsgQWRhcHRlck1hbmlmZXN0IH0gZnJvbSBcIi4vbWFuaWZlc3RcIjtcbmltcG9ydCB7IHVzZU5leHRGcm9tIH0gZnJvbSBcIi4vbmV4dC1tb2R1bGVzXCI7XG5cbmNvbnN0IFBORyA9IEJ1ZmZlci5mcm9tKFwib3B0aW1pemVkLWJ5dGVzXCIpO1xuY29uc3QgRVRBRyA9IFwiYWJjMTIzXCI7XG5cbi8qKiBKdXN0IHdoYXQgYGxvYWRJbWFnZVJ1bnRpbWVgIHJlYWRzOiB3aGVyZSBgcmVxdWlyZWQtc2VydmVyLWZpbGVzLmpzb25gIGlzLiAqL1xuZnVuY3Rpb24gc3RhZ2UoZXh0cmFDb25maWc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge30pOiBzdHJpbmcge1xuICBjb25zdCByb290ID0gbWtkdGVtcFN5bmMoam9pbih0bXBkaXIoKSwgXCJjZGstbmV4dGpzLWltYWdlLVwiKSk7XG4gIG1rZGlyU3luYyhqb2luKHJvb3QsIFwiLm5leHRcIikpO1xuICB3cml0ZUZpbGVTeW5jKFxuICAgIGpvaW4ocm9vdCwgXCIubmV4dC9yZXF1aXJlZC1zZXJ2ZXItZmlsZXMuanNvblwiKSxcbiAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBjb25maWc6IHtcbiAgICAgICAgYmFzZVBhdGg6IFwiXCIsXG4gICAgICAgIGV4cGVyaW1lbnRhbDoge30sXG4gICAgICAgIGltYWdlczogeyAuLi5pbWFnZUNvbmZpZ0RlZmF1bHQsIGxvY2FsUGF0dGVybnM6IHVuZGVmaW5lZCB9LFxuICAgICAgICAuLi5leHRyYUNvbmZpZyxcbiAgICAgIH0sXG4gICAgfSksXG4gICk7XG4gIHJldHVybiByb290O1xufVxuXG4vKiogVGhlIGFwcCdzIGBjYWNoZUhhbmRsZXJgLCByZWR1Y2VkIHRvIGEgbWFwOiB3aGF0IHRoZSBTMyBoYW5kbGVyIGlzIHRvIGl0LiAqL1xuY2xhc3MgTWFwQ2FjaGVIYW5kbGVyIHtcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBlbnRyaWVzID0gbmV3IE1hcDxzdHJpbmcsIHVua25vd24+KCk7XG4gIHB1YmxpYyBzdGF0aWMgb3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIE1hcENhY2hlSGFuZGxlci5vcHRpb25zID0gb3B0aW9ucztcbiAgfVxuICBwdWJsaWMgYXN5bmMgZ2V0KGtleTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIE1hcENhY2hlSGFuZGxlci5lbnRyaWVzLmdldChrZXkpID8/IG51bGw7XG4gIH1cbiAgcHVibGljIGFzeW5jIHNldChrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pIHtcbiAgICBNYXBDYWNoZUhhbmRsZXIuZW50cmllcy5zZXQoa2V5LCB7IHZhbHVlLCBsYXN0TW9kaWZpZWQ6IERhdGUubm93KCkgfSk7XG4gIH1cbn1cblxubGV0IGltcG9ydGVkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbmNvbnN0IHMzSGl0ID0ge1xuICBzZW5kOiBhc3luYyAoKSA9PiAoe1xuICAgIEJvZHk6IFtCdWZmZXIuZnJvbShcInVwc3RyZWFtLWJ5dGVzXCIpXSxcbiAgICBDb250ZW50VHlwZTogXCJpbWFnZS9wbmdcIixcbiAgICBFVGFnOiAnXCJ1cHN0cmVhbVwiJyxcbiAgfSksXG59IGFzIHVua25vd24gYXMgUzNDbGllbnQ7XG5cbi8qKiBBbiBvcHRpbWl6ZXIgb3ZlciB7QGxpbmsgTWFwQ2FjaGVIYW5kbGVyfSwgYXMgdGhlIGFkYXB0ZXIgY29uZmlndXJlcyBvbmUuICovXG5mdW5jdGlvbiBvcHRpbWl6ZXJGb3IoXG4gIG9wdGlvbnM6IHtcbiAgICBpbWFnZXM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBmZXRjaEludGVybmFsPzogSW1hZ2VPcHRpbWl6ZXJPcHRpb25zW1wiZmV0Y2hJbnRlcm5hbFwiXTtcbiAgICBpbXBvcnRNb2R1bGU/OiBJbWFnZU9wdGltaXplck9wdGlvbnNbXCJpbXBvcnRNb2R1bGVcIl07XG4gICAgczM/OiBTM0NsaWVudDtcbiAgICBidWNrZXQ/OiBzdHJpbmc7XG4gIH0gPSB7fSxcbik6IFJ1bnRpbWVJbWFnZU9wdGltaXplciB7XG4gIGNvbnN0IHZpYSA9IG5ldyBSdW50aW1lSW1hZ2VPcHRpbWl6ZXIoe1xuICAgIGRlcGxveW1lbnRSb290OiBzdGFnZSh7XG4gICAgICBjYWNoZUhhbmRsZXI6IFwiLi4vbm9kZV9tb2R1bGVzL2Nkay1uZXh0anMvbGliL2FkYXB0ZXIvY2FjaGUtaGFuZGxlci5tanNcIixcbiAgICAgIGNhY2hlTWF4TWVtb3J5U2l6ZTogMCxcbiAgICAgIC4uLihvcHRpb25zLmltYWdlc1xuICAgICAgICA/IHtcbiAgICAgICAgICAgIGltYWdlczoge1xuICAgICAgICAgICAgICAuLi5pbWFnZUNvbmZpZ0RlZmF1bHQsXG4gICAgICAgICAgICAgIGxvY2FsUGF0dGVybnM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgLi4ub3B0aW9ucy5pbWFnZXMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgfSksXG4gICAgbWFuaWZlc3Q6IHtcbiAgICAgIHJlbGF0aXZlUHJvamVjdERpcjogXCJcIixcbiAgICAgIGNvbmZpZzogeyBkaXN0RGlyOiBcIi5uZXh0XCIgfSxcbiAgICB9IGFzIHVua25vd24gYXMgQWRhcHRlck1hbmlmZXN0LFxuICAgIGJ1Y2tldDogb3B0aW9ucy5idWNrZXQgPz8gXCJhc3NldHNcIixcbiAgICBidWNrZXRLZXlQcmVmaXg6IFwiXCIsXG4gICAgZmV0Y2hJbnRlcm5hbDpcbiAgICAgIG9wdGlvbnMuZmV0Y2hJbnRlcm5hbCA/P1xuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5leHBlY3RlZCBmZXRjaEludGVybmFsXCIpO1xuICAgICAgfSksXG4gICAgaW1wb3J0TW9kdWxlOlxuICAgICAgb3B0aW9ucy5pbXBvcnRNb2R1bGUgPz9cbiAgICAgIChhc3luYyAodXJsKSA9PiB7XG4gICAgICAgIGltcG9ydGVkID0gdXJsO1xuICAgICAgICByZXR1cm4geyBkZWZhdWx0OiBNYXBDYWNoZUhhbmRsZXIgfTtcbiAgICAgIH0pLFxuICB9KTtcbiAgKHZpYSBhcyB1bmtub3duIGFzIHsgczM6IFMzQ2xpZW50IH0pLnMzID0gb3B0aW9ucy5zMyA/PyBzM0hpdDtcbiAgcmV0dXJuIHZpYTtcbn1cblxubGV0IG9wdGltaXplcjogUnVudGltZUltYWdlT3B0aW1pemVyO1xuXG5iZWZvcmVBbGwoKCkgPT4ge1xuICB1c2VOZXh0RnJvbShqb2luKF9fZGlybmFtZSwgXCIuLi8uLlwiKSk7XG4gIG9wdGltaXplciA9IG9wdGltaXplckZvcigpO1xufSk7XG5cbmJlZm9yZUVhY2goKCkgPT4ge1xuICBNYXBDYWNoZUhhbmRsZXIuZW50cmllcy5jbGVhcigpO1xuICBpbXBvcnRlZCA9IHVuZGVmaW5lZDtcbiAgKGltYWdlT3B0aW1pemVyIGFzIGplc3QuTW9jaykubW9ja0NsZWFyKCk7XG4gIChpbWFnZU9wdGltaXplciBhcyBqZXN0Lk1vY2spLm1vY2tSZXNvbHZlZFZhbHVlKHtcbiAgICBidWZmZXI6IFBORyxcbiAgICBjb250ZW50VHlwZTogXCJpbWFnZS93ZWJwXCIsXG4gICAgbWF4QWdlOiA2MCxcbiAgICBldGFnOiBFVEFHLFxuICB9KTtcbn0pO1xuXG5pbnRlcmZhY2UgQW5zd2VyIHtcbiAgcmVhZG9ubHkgaGVhZDogUmVzcG9uc2VIZWFkO1xuICByZWFkb25seSBib2R5OiBzdHJpbmc7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlcXVlc3QoXG4gIHNyYzogc3RyaW5nLFxuICBpbml0OiB7XG4gICAgbWV0aG9kPzogc3RyaW5nO1xuICAgIGhlYWRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgIHZpYT86IFJ1bnRpbWVJbWFnZU9wdGltaXplcjtcbiAgICB3YWl0VW50aWw/OiAocHJvbWlzZTogUHJvbWlzZTx1bmtub3duPikgPT4gdm9pZDtcbiAgfSA9IHt9LFxuKTogUHJvbWlzZTxBbnN3ZXI+IHtcbiAgY29uc3QgdXJsID0gbmV3IFVSTChcbiAgICBgaHR0cHM6Ly9zaG9wLmV4YW1wbGUudGVzdC9fbmV4dC9pbWFnZT91cmw9JHtlbmNvZGVVUklDb21wb25lbnQoc3JjKX0mdz02NDAmcT03NWAsXG4gICk7XG4gIGNvbnN0IHJlcSA9IG5ldyBTaGltSW5jb21pbmdNZXNzYWdlKHtcbiAgICBtZXRob2Q6IGluaXQubWV0aG9kID8/IFwiR0VUXCIsXG4gICAgdXJsOiBgJHt1cmwucGF0aG5hbWV9JHt1cmwuc2VhcmNofWAsXG4gICAgaGVhZGVyczogeyBhY2NlcHQ6IFwiaW1hZ2Uvd2VicFwiLCAuLi5pbml0LmhlYWRlcnMgfSxcbiAgfSk7XG4gIGNvbnN0IHJlcyA9IG5ldyBTaGltU2VydmVyUmVzcG9uc2UoKTtcbiAgbGV0IGhlYWQ6IFJlc3BvbnNlSGVhZCB8IHVuZGVmaW5lZDtcbiAgY29uc3QgY2h1bmtzOiBCdWZmZXJbXSA9IFtdO1xuICBjb25zdCBkb25lID0gcGlwZVRvU2luayhcbiAgICByZXEsXG4gICAgcmVzLFxuICAgIHtcbiAgICAgIGJlZ2luKHJlc3BvbnNlSGVhZCkge1xuICAgICAgICBoZWFkID0gcmVzcG9uc2VIZWFkO1xuICAgICAgICByZXR1cm4gbmV3IFdyaXRhYmxlKHtcbiAgICAgICAgICB3cml0ZShjaHVuaywgX2VuY29kaW5nLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgY2h1bmtzLnB1c2goQnVmZmVyLmZyb20oY2h1bmspKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH0sXG4gICAgeyBjb21wcmVzczogZmFsc2UgfSxcbiAgKTtcbiAgY29uc3QgcGVuZGluZzogQXJyYXk8UHJvbWlzZTx1bmtub3duPj4gPSBbXTtcbiAgYXdhaXQgKGluaXQudmlhID8/IG9wdGltaXplcikuaGFuZGxlKFxuICAgIHJlcSxcbiAgICByZXMsXG4gICAgdXJsLFxuICAgIGluaXQud2FpdFVudGlsID8/ICgocHJvbWlzZSkgPT4gcGVuZGluZy5wdXNoKHByb21pc2UpKSxcbiAgKTtcbiAgYXdhaXQgZG9uZTtcbiAgLy8gU2V0dGxlZCwgbm90IGF3YWl0ZWQ6IHRoZSBydW50aW1lIGxvZ3MgYSByZWplY3Rpb24gcmF0aGVyIHRoYW4gZmFpbGluZyBvbiBpdC5cbiAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKHBlbmRpbmcpO1xuICByZXR1cm4geyBoZWFkOiBoZWFkISwgYm9keTogQnVmZmVyLmNvbmNhdChjaHVua3MpLnRvU3RyaW5nKCkgfTtcbn1cblxuZGVzY3JpYmUoXCJSdW50aW1lSW1hZ2VPcHRpbWl6ZXIuaXNFbmFibGVkXCIsICgpID0+IHtcbiAgY29uc3Qgd2l0aEltYWdlcyA9IChpbWFnZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PlxuICAgIG9wdGltaXplckZvcih7IGltYWdlcyB9KTtcblxuICAvLyBXaGVyZSBgbmV4dCBzdGFydGAgYW5zd2VycyA0MDQgcmF0aGVyIHRoYW4gb3B0aW1pemUuXG4gIGl0KFwiaXMgb2ZmIGZvciBpbWFnZXMudW5vcHRpbWl6ZWQgYW5kIGZvciBhIG5vbi1kZWZhdWx0IGxvYWRlclwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHdpdGhJbWFnZXMoe30pLmlzRW5hYmxlZCgpKS50b0JlKHRydWUpO1xuICAgIGV4cGVjdCh3aXRoSW1hZ2VzKHsgdW5vcHRpbWl6ZWQ6IHRydWUgfSkuaXNFbmFibGVkKCkpLnRvQmUoZmFsc2UpO1xuICAgIGV4cGVjdChcbiAgICAgIHdpdGhJbWFnZXMoeyBsb2FkZXI6IFwiY3VzdG9tXCIsIGxvYWRlckZpbGU6IFwiLi9sb2FkZXIuanNcIiB9KS5pc0VuYWJsZWQoKSxcbiAgICApLnRvQmUoZmFsc2UpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcIlJ1bnRpbWVJbWFnZU9wdGltaXplciByZXNwb25zZVwiLCAoKSA9PiB7XG4gIGl0KFwiYW5zd2VycyB3aXRoIHRoZSBoZWFkZXJzIG5leHQgc3RhcnQgc2VuZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgaGVhZCwgYm9keSB9ID0gYXdhaXQgcmVxdWVzdChcIi9waG90b3MvbG9nby5wbmdcIik7XG4gICAgZXhwZWN0KGhlYWQuc3RhdHVzQ29kZSkudG9CZSgyMDApO1xuICAgIGV4cGVjdChoZWFkLmhlYWRlcnMpLnRvTWF0Y2hPYmplY3Qoe1xuICAgICAgXCJjYWNoZS1jb250cm9sXCI6IFwicHVibGljLCBtYXgtYWdlPTYwLCBtdXN0LXJldmFsaWRhdGVcIixcbiAgICAgIFwiY29udGVudC10eXBlXCI6IFwiaW1hZ2Uvd2VicFwiLFxuICAgICAgXCJjb250ZW50LWxlbmd0aFwiOiBTdHJpbmcoUE5HLmxlbmd0aCksXG4gICAgICBcImNvbnRlbnQtZGlzcG9zaXRpb25cIjogJ2F0dGFjaG1lbnQ7IGZpbGVuYW1lPVwibG9nby53ZWJwXCInLFxuICAgICAgXCJjb250ZW50LXNlY3VyaXR5LXBvbGljeVwiOiBpbWFnZUNvbmZpZ0RlZmF1bHQuY29udGVudFNlY3VyaXR5UG9saWN5LFxuICAgICAgZXRhZzogRVRBRyxcbiAgICAgIHZhcnk6IFwiQWNjZXB0XCIsXG4gICAgICBcIngtbmV4dGpzLWNhY2hlXCI6IFwiTUlTU1wiLFxuICAgIH0pO1xuICAgIGV4cGVjdChib2R5KS50b0JlKFBORy50b1N0cmluZygpKTtcbiAgfSk7XG5cbiAgLy8gQ29udGVudC1oYXNoZWQsIHNvIHRoZSBuYW1lIGNoYW5nZXMgd2hlbmV2ZXIgdGhlIGJ5dGVzIGRvLlxuICBpdChcImNhY2hlcyBhIHN0YXRpY2FsbHkgaW1wb3J0ZWQgaW1hZ2UgZm9yIGEgeWVhciwgaW1tdXRhYmxlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7IGhlYWQgfSA9IGF3YWl0IHJlcXVlc3QoXCIvX25leHQvc3RhdGljL21lZGlhL2xvZ28uM2YyYTFjLnBuZ1wiKTtcbiAgICBleHBlY3QoaGVhZC5oZWFkZXJzW1wiY2FjaGUtY29udHJvbFwiXSkudG9CZShcbiAgICAgIFwicHVibGljLCBtYXgtYWdlPTMxNTM2MDAwMCwgaW1tdXRhYmxlXCIsXG4gICAgKTtcbiAgfSk7XG5cbiAgLy8gYHdyaXRlSGVhZGAgcmVqZWN0cyBhIGhlYWRlciB2YWx1ZSBvdXRzaWRlIGxhdGluMSB3aXRoIEVSUl9JTlZBTElEX0NIQVIsXG4gIC8vIGFuZCB0aGUgTGFtYmRhIHNpbmsgd3JpdGVzIHRoZSBoZWFkIHRocm91Z2ggaXQuXG4gIGl0KFwiZW5jb2RlcyBhIG5vbi1sYXRpbjEgZmlsZW5hbWUgcmF0aGVyIHRoYW4gc2VuZGluZyBpdCByYXdcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgaGVhZCB9ID0gYXdhaXQgcmVxdWVzdChcIi/DvG1sYXV0LeWGmeecny5wbmdcIik7XG4gICAgY29uc3QgZGlzcG9zaXRpb24gPSBoZWFkLmhlYWRlcnNbXCJjb250ZW50LWRpc3Bvc2l0aW9uXCJdO1xuICAgIGV4cGVjdChkaXNwb3NpdGlvbikudG9NYXRjaCgvXmF0dGFjaG1lbnQ7IGZpbGVuYW1lPVwiW15cIl0qXCI7IGZpbGVuYW1lXFwqPS8pO1xuICAgIGV4cGVjdChkaXNwb3NpdGlvbikudG9Db250YWluKFxuICAgICAgYGZpbGVuYW1lKj1VVEYtOCcnJHtlbmNvZGVVUklDb21wb25lbnQoXCLDvG1sYXV0LeWGmeecny53ZWJwXCIpfWAsXG4gICAgKTtcbiAgICBleHBlY3QoKCkgPT5cbiAgICAgIHZhbGlkYXRlSGVhZGVyVmFsdWUoXCJDb250ZW50LURpc3Bvc2l0aW9uXCIsIGRpc3Bvc2l0aW9uKSxcbiAgICApLm5vdC50b1Rocm93KCk7XG4gIH0pO1xuXG4gIGl0LmVhY2goW1xuICAgIFtcInRoZSBleGFjdCB0YWdcIiwgRVRBR10sXG4gICAgW1wiYSB3ZWFrIGZvcm0gb2YgaXRcIiwgYFcvJHtFVEFHfWBdLFxuICAgIFtcImEgbGlzdCBjb250YWluaW5nIGl0XCIsIGBcIm90aGVyXCIsICR7RVRBR31gXSxcbiAgICBbXCJhIHdpbGRjYXJkXCIsIFwiKlwiXSxcbiAgXSkoXCJhbnN3ZXJzIDMwNCB0byBJZi1Ob25lLU1hdGNoIHdpdGggJXNcIiwgYXN5bmMgKF9uYW1lLCBpZk5vbmVNYXRjaCkgPT4ge1xuICAgIGNvbnN0IHsgaGVhZCwgYm9keSB9ID0gYXdhaXQgcmVxdWVzdChcIi9sb2dvLnBuZ1wiLCB7XG4gICAgICBoZWFkZXJzOiB7IFwiaWYtbm9uZS1tYXRjaFwiOiBpZk5vbmVNYXRjaCB9LFxuICAgIH0pO1xuICAgIGV4cGVjdChoZWFkLnN0YXR1c0NvZGUpLnRvQmUoMzA0KTtcbiAgICBleHBlY3QoaGVhZC5oZWFkZXJzLmV0YWcpLnRvQmUoRVRBRyk7XG4gICAgZXhwZWN0KGhlYWQuaGVhZGVyc1tcImNhY2hlLWNvbnRyb2xcIl0pLnRvQmUoXG4gICAgICBcInB1YmxpYywgbWF4LWFnZT02MCwgbXVzdC1yZXZhbGlkYXRlXCIsXG4gICAgKTtcbiAgICBleHBlY3QoYm9keSkudG9CZShcIlwiKTtcbiAgfSk7XG5cbiAgaXQoXCJhbnN3ZXJzIDIwMCB0byBhbiBJZi1Ob25lLU1hdGNoIHRoYXQgZG9lcyBub3QgbWF0Y2hcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgaGVhZCB9ID0gYXdhaXQgcmVxdWVzdChcIi9sb2dvLnBuZ1wiLCB7XG4gICAgICBoZWFkZXJzOiB7IFwiaWYtbm9uZS1tYXRjaFwiOiAnXCJvdGhlclwiJyB9LFxuICAgIH0pO1xuICAgIGV4cGVjdChoZWFkLnN0YXR1c0NvZGUpLnRvQmUoMjAwKTtcbiAgfSk7XG5cbiAgaXQoXCJzZW5kcyB0aGUgaGVhZGVycyBidXQgbm8gYm9keSB0byBIRUFEXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7IGhlYWQsIGJvZHkgfSA9IGF3YWl0IHJlcXVlc3QoXCIvbG9nby5wbmdcIiwgeyBtZXRob2Q6IFwiSEVBRFwiIH0pO1xuICAgIGV4cGVjdChoZWFkLnN0YXR1c0NvZGUpLnRvQmUoMjAwKTtcbiAgICBleHBlY3QoaGVhZC5oZWFkZXJzW1wiY29udGVudC1sZW5ndGhcIl0pLnRvQmUoU3RyaW5nKFBORy5sZW5ndGgpKTtcbiAgICBleHBlY3QoYm9keSkudG9CZShcIlwiKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJSdW50aW1lSW1hZ2VPcHRpbWl6ZXIgc291cmNlc1wiLCAoKSA9PiB7XG4gIC8vIGBuZXh0IHN0YXJ0YCBmZXRjaGVzIGEgcmVtb3RlIHNvdXJjZSBvbmx5IHdoZW4gYHJlbW90ZVBhdHRlcm5zYCBvciBgZG9tYWluc2BcbiAgLy8gYWxsb3cgaXQ7IHRoZSBzdGFnZSdzIGNvbmZpZyBhbGxvd3Mgbm9uZS4gQW55dGhpbmcgZWxzZSB3b3VsZCBtYWtlIHRoZVxuICAvLyBvcHRpbWl6ZXIgYW4gb3BlbiBwcm94eSBpbnRvIHdoYXRldmVyIGl0IGNhbiByZWFjaC5cbiAgaXQuZWFjaChbXG4gICAgW1wiYW5vdGhlciBvcmlnaW5cIiwgXCJodHRwczovL2V2aWwuZXhhbXBsZS50ZXN0L3gucG5nXCJdLFxuICAgIFtcImluc3RhbmNlIG1ldGFkYXRhXCIsIFwiaHR0cDovLzE2OS4yNTQuMTY5LjI1NC9sYXRlc3QvbWV0YS1kYXRhL1wiXSxcbiAgICBbXCJhIHByb3RvY29sLXJlbGF0aXZlIHVybFwiLCBcIi8vZXZpbC5leGFtcGxlLnRlc3QveC5wbmdcIl0sXG4gIF0pKFwicmVqZWN0cyBhIHJlbW90ZSBzb3VyY2UgdGhhdCBpcyBub3QgYWxsb3dlZDogJXNcIiwgYXN5bmMgKF9uYW1lLCBzcmMpID0+IHtcbiAgICBjb25zdCB7IGhlYWQsIGJvZHkgfSA9IGF3YWl0IHJlcXVlc3Qoc3JjKTtcbiAgICBleHBlY3QoaGVhZC5zdGF0dXNDb2RlKS50b0JlKDQwMCk7XG4gICAgZXhwZWN0KGJvZHkpLnRvTWF0Y2goL1widXJsXCIgcGFyYW1ldGVyLyk7XG4gICAgZXhwZWN0KGltYWdlT3B0aW1pemVyKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICB9KTtcblxuICBmdW5jdGlvbiB3aXRoUzNNaXNzKFxuICAgIGZldGNoSW50ZXJuYWw/OiBJbWFnZU9wdGltaXplck9wdGlvbnNbXCJmZXRjaEludGVybmFsXCJdLFxuICApOiBSdW50aW1lSW1hZ2VPcHRpbWl6ZXIge1xuICAgIHJldHVybiBvcHRpbWl6ZXJGb3Ioe1xuICAgICAgZmV0Y2hJbnRlcm5hbCxcbiAgICAgIHMzOiB7XG4gICAgICAgIHNlbmQ6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihcIm1pc3NpbmdcIiksIHsgbmFtZTogXCJOb1N1Y2hLZXlcIiB9KTtcbiAgICAgICAgfSxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBTM0NsaWVudCxcbiAgICB9KTtcbiAgfVxuXG4gIGl0KFwiZmFsbHMgYmFjayB0byB0aGUgYXBwJ3Mgcm91dGVzIGZvciBhIHNvdXJjZSBTMyBoYXMgbm8gZmlsZSBmb3JcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGZldGNoSW50ZXJuYWwgPSBqZXN0LmZuKGFzeW5jICgpID0+ICh7XG4gICAgICBzdGF0dXNDb2RlOiAyMDAsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIFwiY29udGVudC10eXBlXCI6IFwiaW1hZ2UvcG5nXCIsXG4gICAgICAgIFwiY2FjaGUtY29udHJvbFwiOiBcInB1YmxpYywgbWF4LWFnZT0xMjBcIixcbiAgICAgIH0sXG4gICAgICBib2R5OiBCdWZmZXIuZnJvbShcInJvdXRlLWJ5dGVzXCIpLFxuICAgIH0pKTtcbiAgICBjb25zdCB7IGhlYWQgfSA9IGF3YWl0IHJlcXVlc3QoXCIvYXBpL2F2YXRhcj9pZD00MlwiLCB7XG4gICAgICB2aWE6IHdpdGhTM01pc3MoZmV0Y2hJbnRlcm5hbCksXG4gICAgfSk7XG4gICAgZXhwZWN0KGhlYWQuc3RhdHVzQ29kZSkudG9CZSgyMDApO1xuICAgIGV4cGVjdChmZXRjaEludGVybmFsKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChcbiAgICAgIFwiL2FwaS9hdmF0YXI/aWQ9NDJcIixcbiAgICAgIGV4cGVjdC5hbnl0aGluZygpLFxuICAgICAgaW1hZ2VDb25maWdEZWZhdWx0Lm1heGltdW1SZXNwb25zZUJvZHksXG4gICAgKTtcbiAgICBleHBlY3QoKGltYWdlT3B0aW1pemVyIGFzIGplc3QuTW9jaykubW9jay5sYXN0Q2FsbFswXSkudG9NYXRjaE9iamVjdCh7XG4gICAgICBidWZmZXI6IEJ1ZmZlci5mcm9tKFwicm91dGUtYnl0ZXNcIiksXG4gICAgICBjb250ZW50VHlwZTogXCJpbWFnZS9wbmdcIixcbiAgICAgIGNhY2hlQ29udHJvbDogXCJwdWJsaWMsIG1heC1hZ2U9MTIwXCIsXG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIGBOZXh0anNSZWdpb25hbENvbnRhaW5lcnNgOiB0aGUgZmlsZSBpcyBvbiBkaXNrLCBhbmQgYSBHZXRPYmplY3QgZm9yIGl0IGlzXG4gIC8vIGEgd2FzdGVkIHJvdW5kIHRyaXAuXG4gIGl0KFwiZ29lcyBzdHJhaWdodCB0byB0aGUgYXBwJ3Mgcm91dGVzIHdoZW4gdGhlcmUgaXMgbm8gYnVja2V0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzZW5kID0gamVzdC5mbigpO1xuICAgIGNvbnN0IGZldGNoSW50ZXJuYWwgPSBqZXN0LmZuKGFzeW5jICgpID0+ICh7XG4gICAgICBzdGF0dXNDb2RlOiAyMDAsXG4gICAgICBoZWFkZXJzOiB7IFwiY29udGVudC10eXBlXCI6IFwiaW1hZ2UvcG5nXCIgfSxcbiAgICAgIGJvZHk6IEJ1ZmZlci5mcm9tKFwiZGlzay1ieXRlc1wiKSxcbiAgICB9KSk7XG4gICAgY29uc3QgeyBoZWFkIH0gPSBhd2FpdCByZXF1ZXN0KFwiL2xvZ28ucG5nXCIsIHtcbiAgICAgIHZpYTogb3B0aW1pemVyRm9yKHtcbiAgICAgICAgYnVja2V0OiBcIlwiLFxuICAgICAgICBmZXRjaEludGVybmFsLFxuICAgICAgICBzMzogeyBzZW5kIH0gYXMgdW5rbm93biBhcyBTM0NsaWVudCxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIGV4cGVjdChoZWFkLnN0YXR1c0NvZGUpLnRvQmUoMjAwKTtcbiAgICBleHBlY3Qoc2VuZCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICBleHBlY3QoZmV0Y2hJbnRlcm5hbCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICBcIi9sb2dvLnBuZ1wiLFxuICAgICAgZXhwZWN0LmFueXRoaW5nKCksXG4gICAgICBpbWFnZUNvbmZpZ0RlZmF1bHQubWF4aW11bVJlc3BvbnNlQm9keSxcbiAgICApO1xuICB9KTtcblxuICBpdChcImFuc3dlcnMgNDAwIHdoZW4gdGhlIHJvdXRlIHNlbmRzIG5vIGJvZHlcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgaGVhZCB9ID0gYXdhaXQgcmVxdWVzdChcIi9hcGkvYXZhdGFyP2lkPTQyXCIsIHtcbiAgICAgIHZpYTogd2l0aFMzTWlzcyhhc3luYyAoKSA9PiAoe1xuICAgICAgICBzdGF0dXNDb2RlOiA0MDQsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBib2R5OiBCdWZmZXIuYWxsb2MoMCksXG4gICAgICB9KSksXG4gICAgfSk7XG4gICAgZXhwZWN0KGhlYWQuc3RhdHVzQ29kZSkudG9CZSg0MDApO1xuICB9KTtcblxuICBpdChcImFuc3dlcnMgYW4gZXhwbGljaXQgNTAyIGZvciBhIHNvdXJjZSBzZXJ2ZWQgYnkgYW5vdGhlciBmdW5jdGlvbkdyb3VwcyBncm91cFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXJyb3IgPSBqZXN0LnNweU9uKGNvbnNvbGUsIFwiZXJyb3JcIikubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHt9KTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBoZWFkLCBib2R5IH0gPSBhd2FpdCByZXF1ZXN0KFwiL2FwaS9hdmF0YXI/aWQ9NDJcIiwge1xuICAgICAgICB2aWE6IHdpdGhTM01pc3MoYXN5bmMgKCkgPT4gKHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiAwLFxuICAgICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICAgIGJvZHk6IEJ1ZmZlci5hbGxvYygwKSxcbiAgICAgICAgICBvdGhlckdyb3VwOiBcImF2YXRhcnNcIixcbiAgICAgICAgfSkpLFxuICAgICAgfSk7XG4gICAgICBleHBlY3QoaGVhZC5zdGF0dXNDb2RlKS50b0JlKDUwMik7XG4gICAgICBleHBlY3QoYm9keSkudG9NYXRjaCgvYW5vdGhlciBmdW5jdGlvbkdyb3VwcyBncm91cC8pO1xuICAgICAgZXhwZWN0KGltYWdlT3B0aW1pemVyKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBlcnJvci5tb2NrUmVzdG9yZSgpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gYGltYWdlcy5tYXhpbXVtUmVzcG9uc2VCb2R5YCwgd2hpY2ggYG5leHQgc3RhcnRgIGVuZm9yY2VzIG9uIGxvY2FsXG4gIC8vIHNvdXJjZXMgdG9vOiBwYXN0IGl0LCB0aGUgc291cmNlIGlzIG5vdCByZWFkIGludG8gbWVtb3J5LlxuICBpdChcImFuc3dlcnMgNDEzIGZvciBhIHJvdXRlIHJlc3BvbnNlIG92ZXIgbWF4aW11bVJlc3BvbnNlQm9keVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgeyBoZWFkIH0gPSBhd2FpdCByZXF1ZXN0KFwiL2FwaS9leHBvcnRcIiwge1xuICAgICAgdmlhOiB3aXRoUzNNaXNzKGFzeW5jICgpID0+ICh7XG4gICAgICAgIHN0YXR1c0NvZGU6IDAsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBib2R5OiBCdWZmZXIuYWxsb2MoMCksXG4gICAgICAgIHRvb0xhcmdlOiB0cnVlLFxuICAgICAgfSkpLFxuICAgIH0pO1xuICAgIGV4cGVjdChoZWFkLnN0YXR1c0NvZGUpLnRvQmUoNDEzKTtcbiAgICBleHBlY3QoaW1hZ2VPcHRpbWl6ZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gIH0pO1xuXG4gIGl0KFwiYW5zd2VycyA0MTMgZm9yIGFuIFMzIG9iamVjdCBvdmVyIG1heGltdW1SZXNwb25zZUJvZHlcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgaGVhZCB9ID0gYXdhaXQgcmVxdWVzdChcIi92aWRlby5tcDRcIiwge1xuICAgICAgdmlhOiBvcHRpbWl6ZXJGb3Ioe1xuICAgICAgICBpbWFnZXM6IHsgbWF4aW11bVJlc3BvbnNlQm9keTogMTAgfSxcbiAgICAgICAgczM6IHtcbiAgICAgICAgICBzZW5kOiBhc3luYyAoKSA9PiAoe1xuICAgICAgICAgICAgQm9keTogW0J1ZmZlci5mcm9tKFwibmV2ZXIgcmVhZFwiKV0sXG4gICAgICAgICAgICBDb250ZW50TGVuZ3RoOiAxMSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSBhcyB1bmtub3duIGFzIFMzQ2xpZW50LFxuICAgICAgfSksXG4gICAgfSk7XG4gICAgZXhwZWN0KGhlYWQuc3RhdHVzQ29kZSkudG9CZSg0MTMpO1xuICAgIGV4cGVjdChpbWFnZU9wdGltaXplcikubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJSdW50aW1lSW1hZ2VPcHRpbWl6ZXIgY2FjaGVcIiwgKCkgPT4ge1xuICBpdChcIm9wdGltaXplcyBvbmNlLCB0aGVuIGFuc3dlcnMgZnJvbSB0aGUgY2FjaGUgaGFuZGxlclwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdmlhID0gb3B0aW1pemVyRm9yKCk7XG4gICAgY29uc3QgZmlyc3QgPSBhd2FpdCByZXF1ZXN0KFwiL3Bob3Rvcy9jYWNoZWQucG5nXCIsIHsgdmlhIH0pO1xuICAgIGV4cGVjdChmaXJzdC5oZWFkLmhlYWRlcnNbXCJ4LW5leHRqcy1jYWNoZVwiXSkudG9CZShcIk1JU1NcIik7XG4gICAgZXhwZWN0KGZpcnN0LmJvZHkpLnRvQmUoUE5HLnRvU3RyaW5nKCkpO1xuXG4gICAgY29uc3Qgc2Vjb25kID0gYXdhaXQgcmVxdWVzdChcIi9waG90b3MvY2FjaGVkLnBuZ1wiLCB7IHZpYSB9KTtcbiAgICBleHBlY3Qoc2Vjb25kLmhlYWQuc3RhdHVzQ29kZSkudG9CZSgyMDApO1xuICAgIGV4cGVjdChzZWNvbmQuaGVhZC5oZWFkZXJzW1wieC1uZXh0anMtY2FjaGVcIl0pLnRvQmUoXCJISVRcIik7XG4gICAgZXhwZWN0KHNlY29uZC5ib2R5KS50b0JlKFBORy50b1N0cmluZygpKTtcbiAgICBleHBlY3Qoc2Vjb25kLmhlYWQuaGVhZGVycy5ldGFnKS50b0JlKEVUQUcpO1xuICAgIGV4cGVjdChpbWFnZU9wdGltaXplcikudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuXG4gICAgLy8gVGhlIGVudHJ5IGBuZXh0IHN0YXJ0YCB3b3VsZCBoYXZlIHdyaXR0ZW4uXG4gICAgY29uc3QgW2VudHJ5XSA9IFsuLi5NYXBDYWNoZUhhbmRsZXIuZW50cmllcy52YWx1ZXMoKV0gYXMgQXJyYXk8e1xuICAgICAgdmFsdWU6IHsga2luZDogc3RyaW5nOyBleHRlbnNpb246IHN0cmluZyB9O1xuICAgIH0+O1xuICAgIGV4cGVjdChlbnRyeS52YWx1ZSkudG9NYXRjaE9iamVjdCh7IGtpbmQ6IFwiSU1BR0VcIiwgZXh0ZW5zaW9uOiBcIndlYnBcIiB9KTtcbiAgfSk7XG5cbiAgLy8gQW5vdGhlciBpbnN0YW5jZTogbm90aGluZyBpbiBtZW1vcnksIHNvIHRoZSBoaXQgaXMgdGhlIGNhY2hlIGhhbmRsZXIncy5cbiAgaXQoXCJzaGFyZXMgdGhlIG9wdGltaXplZCBpbWFnZSBhY3Jvc3MgaW5zdGFuY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCByZXF1ZXN0KFwiL3Bob3Rvcy9zaGFyZWQucG5nXCIsIHsgdmlhOiBvcHRpbWl6ZXJGb3IoKSB9KTtcbiAgICBjb25zdCBvdGhlciA9IGF3YWl0IHJlcXVlc3QoXCIvcGhvdG9zL3NoYXJlZC5wbmdcIiwgeyB2aWE6IG9wdGltaXplckZvcigpIH0pO1xuICAgIGV4cGVjdChvdGhlci5oZWFkLmhlYWRlcnNbXCJ4LW5leHRqcy1jYWNoZVwiXSkudG9CZShcIkhJVFwiKTtcbiAgICBleHBlY3QoaW1hZ2VPcHRpbWl6ZXIpLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygxKTtcbiAgfSk7XG5cbiAgLy8gYHJlcXVpcmVkLXNlcnZlci1maWxlcy5qc29uYCBuYW1lcyBpdCByZWxhdGl2ZSB0byB0aGUgZGlzdCBkaXIuXG4gIGl0KFwibG9hZHMgdGhlIGFwcCdzIGNhY2hlSGFuZGxlciBmcm9tIHdoZXJlIG5leHQgc3RhcnQgd291bGRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IHJlcXVlc3QoXCIvcGhvdG9zL2NhY2hlZC5wbmdcIiwgeyB2aWE6IG9wdGltaXplckZvcigpIH0pO1xuICAgIGV4cGVjdChpbXBvcnRlZCkudG9NYXRjaChcbiAgICAgIC9eZmlsZTpcXC9cXC8uKlxcL25vZGVfbW9kdWxlc1xcL2Nkay1uZXh0anNcXC9saWJcXC9hZGFwdGVyXFwvY2FjaGUtaGFuZGxlclxcLm1qcyQvLFxuICAgICk7XG4gICAgZXhwZWN0KE1hcENhY2hlSGFuZGxlci5vcHRpb25zKS50b01hdGNoT2JqZWN0KHsgZGV2OiBmYWxzZSB9KTtcbiAgfSk7XG5cbiAgLy8gQSB0cmFuc2llbnQgZmFpbHVyZSBsb2FkaW5nIHRoZSBjYWNoZUhhbmRsZXIgKEVNRklMRSBpbiBhIGNvbGQtc3RhcnRcbiAgLy8gYnVyc3QpIG11c3Qgbm90IGZhaWwgZXZlcnkgbGF0ZXIgaW1hZ2UgcmVxdWVzdCBvbiB0aGUgaW5zdGFuY2UuXG4gIGl0KFwicmV0cmllcyBsb2FkaW5nIHRoZSBjYWNoZUhhbmRsZXIgYWZ0ZXIgYSBmYWlsZWQgbG9hZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXJyb3IgPSBqZXN0LnNweU9uKGNvbnNvbGUsIFwiZXJyb3JcIikubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHt9KTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgaW1wb3J0TW9kdWxlID0gamVzdFxuICAgICAgICAuZm4oKVxuICAgICAgICAubW9ja1JlamVjdGVkVmFsdWVPbmNlKG5ldyBFcnJvcihcIkVNRklMRVwiKSlcbiAgICAgICAgLm1vY2tSZXNvbHZlZFZhbHVlKHsgZGVmYXVsdDogTWFwQ2FjaGVIYW5kbGVyIH0pO1xuICAgICAgY29uc3QgdmlhID0gb3B0aW1pemVyRm9yKHsgaW1wb3J0TW9kdWxlIH0pO1xuICAgICAgZXhwZWN0KFxuICAgICAgICAoYXdhaXQgcmVxdWVzdChcIi9waG90b3MvcmV0cnkucG5nXCIsIHsgdmlhIH0pKS5oZWFkLnN0YXR1c0NvZGUsXG4gICAgICApLnRvQmUoNTAwKTtcbiAgICAgIGV4cGVjdChcbiAgICAgICAgKGF3YWl0IHJlcXVlc3QoXCIvcGhvdG9zL3JldHJ5LnBuZ1wiLCB7IHZpYSB9KSkuaGVhZC5zdGF0dXNDb2RlLFxuICAgICAgKS50b0JlKDIwMCk7XG4gICAgICBleHBlY3QoaW1wb3J0TW9kdWxlKS50b0hhdmVCZWVuQ2FsbGVkVGltZXMoMik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGVycm9yLm1vY2tSZXN0b3JlKCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBUaGUgd3JpdGUgb2YgYSBmcmVzaCBpbWFnZSBnb2VzIHRvIGB3YWl0VW50aWxgLCBub3QgaW4gZnJvbnQgb2YgdGhlXG4gIC8vIHJlc3BvbnNlOiB0aGUgaW1hZ2UgaXMgc2VudCBiZWZvcmUgdGhlIGNhY2hlIGhhbmRsZXIgaGFzIGl0LlxuICBpdChcIndyaXRlcyBhIG1pc3MgdG8gdGhlIGNhY2hlIGFmdGVyIGFuc3dlcmluZywgdGhyb3VnaCB3YWl0VW50aWxcIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEEgd3JpdGUgdGhhdCBjYW4ndCBmaW5pc2ggdW50aWwgcmVsZWFzZWQ6IGlmIHRoZSByZXNwb25zZSB3YWl0ZWQgb24gaXQsXG4gICAgLy8gYHJlcXVlc3RgIHdvdWxkIG5ldmVyIHJldHVybi5cbiAgICBsZXQgcmVsZWFzZSE6ICgpID0+IHZvaWQ7XG4gICAgY29uc3QgZ2F0ZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiAocmVsZWFzZSA9IHJlc29sdmUpKTtcbiAgICBjb25zdCBzZXQgPSBNYXBDYWNoZUhhbmRsZXIucHJvdG90eXBlLnNldDtcbiAgICBNYXBDYWNoZUhhbmRsZXIucHJvdG90eXBlLnNldCA9IGFzeW5jIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICBhd2FpdCBnYXRlO1xuICAgICAgcmV0dXJuIHNldC5jYWxsKHRoaXMsIGtleSwgdmFsdWUpO1xuICAgIH07XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBlbmRpbmc6IEFycmF5PFByb21pc2U8dW5rbm93bj4+ID0gW107XG4gICAgICBjb25zdCBmaXJzdCA9IGF3YWl0IHJlcXVlc3QoXCIvcGhvdG9zL2RlZmVycmVkLnBuZ1wiLCB7XG4gICAgICAgIHZpYTogb3B0aW1pemVyRm9yKCksXG4gICAgICAgIHdhaXRVbnRpbDogKHByb21pc2UpID0+IHBlbmRpbmcucHVzaChwcm9taXNlKSxcbiAgICAgIH0pO1xuICAgICAgZXhwZWN0KGZpcnN0LmhlYWQuaGVhZGVyc1tcIngtbmV4dGpzLWNhY2hlXCJdKS50b0JlKFwiTUlTU1wiKTtcbiAgICAgIGV4cGVjdChNYXBDYWNoZUhhbmRsZXIuZW50cmllcy5zaXplKS50b0JlKDApO1xuXG4gICAgICByZWxlYXNlKCk7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChwZW5kaW5nKTtcbiAgICAgIGV4cGVjdChNYXBDYWNoZUhhbmRsZXIuZW50cmllcy5zaXplKS50b0JlKDEpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBNYXBDYWNoZUhhbmRsZXIucHJvdG90eXBlLnNldCA9IHNldDtcbiAgICB9XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { APIGatewayProxyEvent, LambdaFunctionURLEvent } from "aws-lambda";
|
|
2
|
+
import type { RuntimeRequest } from "./core";
|
|
3
|
+
export type LambdaEvent = LambdaFunctionURLEvent | APIGatewayProxyEvent;
|
|
4
|
+
export declare function toRuntimeRequest(event: LambdaEvent, basePath: string): RuntimeRequest;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toRuntimeRequest = toRuntimeRequest;
|
|
4
|
+
const api_gateway_path_1 = require("./api-gateway-path");
|
|
5
|
+
/** Only the REST API event carries `httpMethod`. */
|
|
6
|
+
function isApiGatewayEvent(event) {
|
|
7
|
+
return "httpMethod" in event;
|
|
8
|
+
}
|
|
9
|
+
function toRuntimeRequest(event, basePath) {
|
|
10
|
+
const body = decodeBody(event.body, event.isBase64Encoded);
|
|
11
|
+
if (isApiGatewayEvent(event)) {
|
|
12
|
+
return {
|
|
13
|
+
method: event.httpMethod,
|
|
14
|
+
// With the stage API Gateway stripped put back, but only for an app whose
|
|
15
|
+
// `basePath` expects it; see `apiGatewayRequestPath`.
|
|
16
|
+
url: (0, api_gateway_path_1.apiGatewayRequestPath)(event, basePath) + formatQuery(event),
|
|
17
|
+
headers: restHeaders(event),
|
|
18
|
+
body,
|
|
19
|
+
remoteAddress: event.requestContext.identity?.sourceIp,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const { http } = event.requestContext;
|
|
23
|
+
return {
|
|
24
|
+
method: http.method,
|
|
25
|
+
// Raw, still percent-encoded, which is what Next.js's own normalization
|
|
26
|
+
// expects.
|
|
27
|
+
url: event.rawPath + (event.rawQueryString ? `?${event.rawQueryString}` : ""),
|
|
28
|
+
headers: functionUrlHeaders(event),
|
|
29
|
+
body,
|
|
30
|
+
remoteAddress: http.sourceIp,
|
|
31
|
+
// Trusted for any IAM-authorized invoker: in practice CloudFront's Origin
|
|
32
|
+
// Access Control, whose viewer-request function overwrites
|
|
33
|
+
// `x-forwarded-host` with the viewer's `Host` (see
|
|
34
|
+
// `RuntimeRequest.trustForwardedHost`; `NextjsDistribution` refuses an
|
|
35
|
+
// override that would replace that function,
|
|
36
|
+
// `withDynamicFunctionAssociations`), plus principals granted
|
|
37
|
+
// `lambda:InvokeFunctionUrl`, which are already trusted with the function.
|
|
38
|
+
// Gated on the signature Lambda verified, not assumed: a URL overridden to
|
|
39
|
+
// `authType: NONE` can be called by anyone, with any header.
|
|
40
|
+
trustForwardedHost: isIamAuthenticated(event),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Lambda sets `authorizer.iam` only for a request it verified the SigV4 of — by
|
|
45
|
+
* any principal allowed to invoke the URL, not only CloudFront.
|
|
46
|
+
*/
|
|
47
|
+
function isIamAuthenticated(event) {
|
|
48
|
+
const { authorizer } = event.requestContext;
|
|
49
|
+
return authorizer?.iam !== undefined;
|
|
50
|
+
}
|
|
51
|
+
function decodeBody(body, isBase64Encoded) {
|
|
52
|
+
if (body === null || body === undefined) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return Buffer.from(body, isBase64Encoded ? "base64" : "utf-8");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Payload v2 lifts cookies out of the headers into their own array, so they have
|
|
59
|
+
* to be put back — Next.js reads `req.headers.cookie` for draft mode, the
|
|
60
|
+
* prerender bypass, and anything a route handler does with `cookies()`.
|
|
61
|
+
*/
|
|
62
|
+
function functionUrlHeaders(event) {
|
|
63
|
+
const headers = {};
|
|
64
|
+
for (const [name, value] of Object.entries(event.headers)) {
|
|
65
|
+
if (value !== undefined) {
|
|
66
|
+
headers[name.toLowerCase()] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (event.cookies?.length) {
|
|
70
|
+
headers.cookie = event.cookies.join("; ");
|
|
71
|
+
}
|
|
72
|
+
return headers;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `multiValueHeaders` only: API Gateway always sends it, as a superset of the
|
|
76
|
+
* single-valued map, which keeps only the last value of a repeated header.
|
|
77
|
+
*
|
|
78
|
+
* `cookie` is rejoined with `"; "` rather than the `", "` every other header uses,
|
|
79
|
+
* because that is the separator the field's own grammar uses (RFC 6265) and what
|
|
80
|
+
* every cookie parser splits on. Joining two `Cookie` fields with a comma produced
|
|
81
|
+
* `cookie: "a=1, b=2"`, which parses as the single cookie `a = "1, b=2"` — every
|
|
82
|
+
* cookie after the first is lost, including `__prerender_bypass` and
|
|
83
|
+
* `__next_preview_data`, so draft mode silently stopped working.
|
|
84
|
+
*/
|
|
85
|
+
function restHeaders(event) {
|
|
86
|
+
const headers = {};
|
|
87
|
+
for (const [name, values] of Object.entries(event.multiValueHeaders ?? {})) {
|
|
88
|
+
if (values?.length) {
|
|
89
|
+
const key = name.toLowerCase();
|
|
90
|
+
headers[key] =
|
|
91
|
+
values.length === 1
|
|
92
|
+
? values[0]
|
|
93
|
+
: values.join(key === "cookie" ? "; " : ", ");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return headers;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Rebuilds the query string API Gateway already parsed (and decoded) for us.
|
|
100
|
+
* Re-encoding is required, not cosmetic: `?q=a%20b` arrives as `a b`, and passing
|
|
101
|
+
* that through unescaped produces a URL that `new URL()` mangles.
|
|
102
|
+
*/
|
|
103
|
+
function formatQuery(event) {
|
|
104
|
+
const search = new URLSearchParams();
|
|
105
|
+
for (const [name, values] of Object.entries(event.multiValueQueryStringParameters ?? {})) {
|
|
106
|
+
for (const value of values ?? []) {
|
|
107
|
+
search.append(name, value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const query = search.toString();
|
|
111
|
+
return query ? `?${query}` : "";
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWV2ZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvbGFtYmRhLWV2ZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBbUJBLDRDQXFDQztBQS9DRCx5REFBMkQ7QUFLM0Qsb0RBQW9EO0FBQ3BELFNBQVMsaUJBQWlCLENBQUMsS0FBa0I7SUFDM0MsT0FBTyxZQUFZLElBQUksS0FBSyxDQUFDO0FBQy9CLENBQUM7QUFFRCxTQUFnQixnQkFBZ0IsQ0FDOUIsS0FBa0IsRUFDbEIsUUFBZ0I7SUFFaEIsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQzNELElBQUksaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM3QixPQUFPO1lBQ0wsTUFBTSxFQUFFLEtBQUssQ0FBQyxVQUFVO1lBQ3hCLDBFQUEwRTtZQUMxRSxzREFBc0Q7WUFDdEQsR0FBRyxFQUFFLElBQUEsd0NBQXFCLEVBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDaEUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDM0IsSUFBSTtZQUNKLGFBQWEsRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxRQUFRO1NBQ3ZELENBQUM7SUFDSixDQUFDO0lBQ0QsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7SUFDdEMsT0FBTztRQUNMLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtRQUNuQix3RUFBd0U7UUFDeEUsV0FBVztRQUNYLEdBQUcsRUFDRCxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMxRSxPQUFPLEVBQUUsa0JBQWtCLENBQUMsS0FBSyxDQUFDO1FBQ2xDLElBQUk7UUFDSixhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVE7UUFDNUIsMEVBQTBFO1FBQzFFLDJEQUEyRDtRQUMzRCxtREFBbUQ7UUFDbkQsdUVBQXVFO1FBQ3ZFLDZDQUE2QztRQUM3Qyw4REFBOEQ7UUFDOUQsMkVBQTJFO1FBQzNFLDJFQUEyRTtRQUMzRSw2REFBNkQ7UUFDN0Qsa0JBQWtCLEVBQUUsa0JBQWtCLENBQUMsS0FBSyxDQUFDO0tBQzlDLENBQUM7QUFDSixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxLQUE2QjtJQUN2RCxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsS0FBSyxDQUFDLGNBRTVCLENBQUM7SUFDRixPQUFPLFVBQVUsRUFBRSxHQUFHLEtBQUssU0FBUyxDQUFDO0FBQ3ZDLENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FDakIsSUFBK0IsRUFDL0IsZUFBd0I7SUFFeEIsSUFBSSxJQUFJLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN4QyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGtCQUFrQixDQUN6QixLQUE2QjtJQUU3QixNQUFNLE9BQU8sR0FBd0IsRUFBRSxDQUFDO0lBQ3hDLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQzFELElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUM7UUFDdEMsQ0FBQztJQUNILENBQUM7SUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDMUIsT0FBTyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFTLFdBQVcsQ0FBQyxLQUEyQjtJQUM5QyxNQUFNLE9BQU8sR0FBd0IsRUFBRSxDQUFDO0lBQ3hDLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQzNFLElBQUksTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQ25CLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMvQixPQUFPLENBQUMsR0FBRyxDQUFDO2dCQUNWLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztvQkFDakIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7b0JBQ1gsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwRCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxXQUFXLENBQUMsS0FBMkI7SUFDOUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztJQUNyQyxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FDekMsS0FBSyxDQUFDLCtCQUErQixJQUFJLEVBQUUsQ0FDNUMsRUFBRSxDQUFDO1FBQ0YsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLElBQUksRUFBRSxFQUFFLENBQUM7WUFDakMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDaEMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNsQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG4vKipcbiAqIExhbWJkYSBldmVudCDihpIge0BsaW5rIFJ1bnRpbWVSZXF1ZXN0fSwgZm9yIGJvdGggZXZlbnQgc2hhcGVzIHRoZSBGdW5jdGlvbnNcbiAqIHNoZWxsIChgbGFtYmRhLm10c2ApIGlzIHJlYWNoZWQgd2l0aC4gSXRzIG93biBtb2R1bGUgc28gaXQgY2FuIGJlIHRlc3RlZDpcbiAqIGBsYW1iZGEubXRzYCBzdGFydHMgbG9hZGluZyB0aGUgcnVudGltZSwgYW5kIG5lZWRzIHRoZSBgYXdzbGFtYmRhYCBnbG9iYWwsIHRoZVxuICogbW9tZW50IGl0IGlzIGltcG9ydGVkLlxuICovXG5pbXBvcnQgdHlwZSB7IEluY29taW5nSHR0cEhlYWRlcnMgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgdHlwZSB7IEFQSUdhdGV3YXlQcm94eUV2ZW50LCBMYW1iZGFGdW5jdGlvblVSTEV2ZW50IH0gZnJvbSBcImF3cy1sYW1iZGFcIjtcbmltcG9ydCB7IGFwaUdhdGV3YXlSZXF1ZXN0UGF0aCB9IGZyb20gXCIuL2FwaS1nYXRld2F5LXBhdGhcIjtcbmltcG9ydCB0eXBlIHsgUnVudGltZVJlcXVlc3QgfSBmcm9tIFwiLi9jb3JlXCI7XG5cbmV4cG9ydCB0eXBlIExhbWJkYUV2ZW50ID0gTGFtYmRhRnVuY3Rpb25VUkxFdmVudCB8IEFQSUdhdGV3YXlQcm94eUV2ZW50O1xuXG4vKiogT25seSB0aGUgUkVTVCBBUEkgZXZlbnQgY2FycmllcyBgaHR0cE1ldGhvZGAuICovXG5mdW5jdGlvbiBpc0FwaUdhdGV3YXlFdmVudChldmVudDogTGFtYmRhRXZlbnQpOiBldmVudCBpcyBBUElHYXRld2F5UHJveHlFdmVudCB7XG4gIHJldHVybiBcImh0dHBNZXRob2RcIiBpbiBldmVudDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUnVudGltZVJlcXVlc3QoXG4gIGV2ZW50OiBMYW1iZGFFdmVudCxcbiAgYmFzZVBhdGg6IHN0cmluZyxcbik6IFJ1bnRpbWVSZXF1ZXN0IHtcbiAgY29uc3QgYm9keSA9IGRlY29kZUJvZHkoZXZlbnQuYm9keSwgZXZlbnQuaXNCYXNlNjRFbmNvZGVkKTtcbiAgaWYgKGlzQXBpR2F0ZXdheUV2ZW50KGV2ZW50KSkge1xuICAgIHJldHVybiB7XG4gICAgICBtZXRob2Q6IGV2ZW50Lmh0dHBNZXRob2QsXG4gICAgICAvLyBXaXRoIHRoZSBzdGFnZSBBUEkgR2F0ZXdheSBzdHJpcHBlZCBwdXQgYmFjaywgYnV0IG9ubHkgZm9yIGFuIGFwcCB3aG9zZVxuICAgICAgLy8gYGJhc2VQYXRoYCBleHBlY3RzIGl0OyBzZWUgYGFwaUdhdGV3YXlSZXF1ZXN0UGF0aGAuXG4gICAgICB1cmw6IGFwaUdhdGV3YXlSZXF1ZXN0UGF0aChldmVudCwgYmFzZVBhdGgpICsgZm9ybWF0UXVlcnkoZXZlbnQpLFxuICAgICAgaGVhZGVyczogcmVzdEhlYWRlcnMoZXZlbnQpLFxuICAgICAgYm9keSxcbiAgICAgIHJlbW90ZUFkZHJlc3M6IGV2ZW50LnJlcXVlc3RDb250ZXh0LmlkZW50aXR5Py5zb3VyY2VJcCxcbiAgICB9O1xuICB9XG4gIGNvbnN0IHsgaHR0cCB9ID0gZXZlbnQucmVxdWVzdENvbnRleHQ7XG4gIHJldHVybiB7XG4gICAgbWV0aG9kOiBodHRwLm1ldGhvZCxcbiAgICAvLyBSYXcsIHN0aWxsIHBlcmNlbnQtZW5jb2RlZCwgd2hpY2ggaXMgd2hhdCBOZXh0LmpzJ3Mgb3duIG5vcm1hbGl6YXRpb25cbiAgICAvLyBleHBlY3RzLlxuICAgIHVybDpcbiAgICAgIGV2ZW50LnJhd1BhdGggKyAoZXZlbnQucmF3UXVlcnlTdHJpbmcgPyBgPyR7ZXZlbnQucmF3UXVlcnlTdHJpbmd9YCA6IFwiXCIpLFxuICAgIGhlYWRlcnM6IGZ1bmN0aW9uVXJsSGVhZGVycyhldmVudCksXG4gICAgYm9keSxcbiAgICByZW1vdGVBZGRyZXNzOiBodHRwLnNvdXJjZUlwLFxuICAgIC8vIFRydXN0ZWQgZm9yIGFueSBJQU0tYXV0aG9yaXplZCBpbnZva2VyOiBpbiBwcmFjdGljZSBDbG91ZEZyb250J3MgT3JpZ2luXG4gICAgLy8gQWNjZXNzIENvbnRyb2wsIHdob3NlIHZpZXdlci1yZXF1ZXN0IGZ1bmN0aW9uIG92ZXJ3cml0ZXNcbiAgICAvLyBgeC1mb3J3YXJkZWQtaG9zdGAgd2l0aCB0aGUgdmlld2VyJ3MgYEhvc3RgIChzZWVcbiAgICAvLyBgUnVudGltZVJlcXVlc3QudHJ1c3RGb3J3YXJkZWRIb3N0YDsgYE5leHRqc0Rpc3RyaWJ1dGlvbmAgcmVmdXNlcyBhblxuICAgIC8vIG92ZXJyaWRlIHRoYXQgd291bGQgcmVwbGFjZSB0aGF0IGZ1bmN0aW9uLFxuICAgIC8vIGB3aXRoRHluYW1pY0Z1bmN0aW9uQXNzb2NpYXRpb25zYCksIHBsdXMgcHJpbmNpcGFscyBncmFudGVkXG4gICAgLy8gYGxhbWJkYTpJbnZva2VGdW5jdGlvblVybGAsIHdoaWNoIGFyZSBhbHJlYWR5IHRydXN0ZWQgd2l0aCB0aGUgZnVuY3Rpb24uXG4gICAgLy8gR2F0ZWQgb24gdGhlIHNpZ25hdHVyZSBMYW1iZGEgdmVyaWZpZWQsIG5vdCBhc3N1bWVkOiBhIFVSTCBvdmVycmlkZGVuIHRvXG4gICAgLy8gYGF1dGhUeXBlOiBOT05FYCBjYW4gYmUgY2FsbGVkIGJ5IGFueW9uZSwgd2l0aCBhbnkgaGVhZGVyLlxuICAgIHRydXN0Rm9yd2FyZGVkSG9zdDogaXNJYW1BdXRoZW50aWNhdGVkKGV2ZW50KSxcbiAgfTtcbn1cblxuLyoqXG4gKiBMYW1iZGEgc2V0cyBgYXV0aG9yaXplci5pYW1gIG9ubHkgZm9yIGEgcmVxdWVzdCBpdCB2ZXJpZmllZCB0aGUgU2lnVjQgb2Yg4oCUIGJ5XG4gKiBhbnkgcHJpbmNpcGFsIGFsbG93ZWQgdG8gaW52b2tlIHRoZSBVUkwsIG5vdCBvbmx5IENsb3VkRnJvbnQuXG4gKi9cbmZ1bmN0aW9uIGlzSWFtQXV0aGVudGljYXRlZChldmVudDogTGFtYmRhRnVuY3Rpb25VUkxFdmVudCk6IGJvb2xlYW4ge1xuICBjb25zdCB7IGF1dGhvcml6ZXIgfSA9IGV2ZW50LnJlcXVlc3RDb250ZXh0IGFzIHtcbiAgICBhdXRob3JpemVyPzogeyBpYW0/OiB1bmtub3duIH07XG4gIH07XG4gIHJldHVybiBhdXRob3JpemVyPy5pYW0gIT09IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZGVjb2RlQm9keShcbiAgYm9keTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgaXNCYXNlNjRFbmNvZGVkOiBib29sZWFuLFxuKTogQnVmZmVyIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGJvZHkgPT09IG51bGwgfHwgYm9keSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gQnVmZmVyLmZyb20oYm9keSwgaXNCYXNlNjRFbmNvZGVkID8gXCJiYXNlNjRcIiA6IFwidXRmLThcIik7XG59XG5cbi8qKlxuICogUGF5bG9hZCB2MiBsaWZ0cyBjb29raWVzIG91dCBvZiB0aGUgaGVhZGVycyBpbnRvIHRoZWlyIG93biBhcnJheSwgc28gdGhleSBoYXZlXG4gKiB0byBiZSBwdXQgYmFjayDigJQgTmV4dC5qcyByZWFkcyBgcmVxLmhlYWRlcnMuY29va2llYCBmb3IgZHJhZnQgbW9kZSwgdGhlXG4gKiBwcmVyZW5kZXIgYnlwYXNzLCBhbmQgYW55dGhpbmcgYSByb3V0ZSBoYW5kbGVyIGRvZXMgd2l0aCBgY29va2llcygpYC5cbiAqL1xuZnVuY3Rpb24gZnVuY3Rpb25VcmxIZWFkZXJzKFxuICBldmVudDogTGFtYmRhRnVuY3Rpb25VUkxFdmVudCxcbik6IEluY29taW5nSHR0cEhlYWRlcnMge1xuICBjb25zdCBoZWFkZXJzOiBJbmNvbWluZ0h0dHBIZWFkZXJzID0ge307XG4gIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhldmVudC5oZWFkZXJzKSkge1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBoZWFkZXJzW25hbWUudG9Mb3dlckNhc2UoKV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cbiAgaWYgKGV2ZW50LmNvb2tpZXM/Lmxlbmd0aCkge1xuICAgIGhlYWRlcnMuY29va2llID0gZXZlbnQuY29va2llcy5qb2luKFwiOyBcIik7XG4gIH1cbiAgcmV0dXJuIGhlYWRlcnM7XG59XG5cbi8qKlxuICogYG11bHRpVmFsdWVIZWFkZXJzYCBvbmx5OiBBUEkgR2F0ZXdheSBhbHdheXMgc2VuZHMgaXQsIGFzIGEgc3VwZXJzZXQgb2YgdGhlXG4gKiBzaW5nbGUtdmFsdWVkIG1hcCwgd2hpY2gga2VlcHMgb25seSB0aGUgbGFzdCB2YWx1ZSBvZiBhIHJlcGVhdGVkIGhlYWRlci5cbiAqXG4gKiBgY29va2llYCBpcyByZWpvaW5lZCB3aXRoIGBcIjsgXCJgIHJhdGhlciB0aGFuIHRoZSBgXCIsIFwiYCBldmVyeSBvdGhlciBoZWFkZXIgdXNlcyxcbiAqIGJlY2F1c2UgdGhhdCBpcyB0aGUgc2VwYXJhdG9yIHRoZSBmaWVsZCdzIG93biBncmFtbWFyIHVzZXMgKFJGQyA2MjY1KSBhbmQgd2hhdFxuICogZXZlcnkgY29va2llIHBhcnNlciBzcGxpdHMgb24uIEpvaW5pbmcgdHdvIGBDb29raWVgIGZpZWxkcyB3aXRoIGEgY29tbWEgcHJvZHVjZWRcbiAqIGBjb29raWU6IFwiYT0xLCBiPTJcImAsIHdoaWNoIHBhcnNlcyBhcyB0aGUgc2luZ2xlIGNvb2tpZSBgYSA9IFwiMSwgYj0yXCJgIOKAlCBldmVyeVxuICogY29va2llIGFmdGVyIHRoZSBmaXJzdCBpcyBsb3N0LCBpbmNsdWRpbmcgYF9fcHJlcmVuZGVyX2J5cGFzc2AgYW5kXG4gKiBgX19uZXh0X3ByZXZpZXdfZGF0YWAsIHNvIGRyYWZ0IG1vZGUgc2lsZW50bHkgc3RvcHBlZCB3b3JraW5nLlxuICovXG5mdW5jdGlvbiByZXN0SGVhZGVycyhldmVudDogQVBJR2F0ZXdheVByb3h5RXZlbnQpOiBJbmNvbWluZ0h0dHBIZWFkZXJzIHtcbiAgY29uc3QgaGVhZGVyczogSW5jb21pbmdIdHRwSGVhZGVycyA9IHt9O1xuICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZXNdIG9mIE9iamVjdC5lbnRyaWVzKGV2ZW50Lm11bHRpVmFsdWVIZWFkZXJzID8/IHt9KSkge1xuICAgIGlmICh2YWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgY29uc3Qga2V5ID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaGVhZGVyc1trZXldID1cbiAgICAgICAgdmFsdWVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgID8gdmFsdWVzWzBdXG4gICAgICAgICAgOiB2YWx1ZXMuam9pbihrZXkgPT09IFwiY29va2llXCIgPyBcIjsgXCIgOiBcIiwgXCIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gaGVhZGVycztcbn1cblxuLyoqXG4gKiBSZWJ1aWxkcyB0aGUgcXVlcnkgc3RyaW5nIEFQSSBHYXRld2F5IGFscmVhZHkgcGFyc2VkIChhbmQgZGVjb2RlZCkgZm9yIHVzLlxuICogUmUtZW5jb2RpbmcgaXMgcmVxdWlyZWQsIG5vdCBjb3NtZXRpYzogYD9xPWElMjBiYCBhcnJpdmVzIGFzIGBhIGJgLCBhbmQgcGFzc2luZ1xuICogdGhhdCB0aHJvdWdoIHVuZXNjYXBlZCBwcm9kdWNlcyBhIFVSTCB0aGF0IGBuZXcgVVJMKClgIG1hbmdsZXMuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdFF1ZXJ5KGV2ZW50OiBBUElHYXRld2F5UHJveHlFdmVudCk6IHN0cmluZyB7XG4gIGNvbnN0IHNlYXJjaCA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVzXSBvZiBPYmplY3QuZW50cmllcyhcbiAgICBldmVudC5tdWx0aVZhbHVlUXVlcnlTdHJpbmdQYXJhbWV0ZXJzID8/IHt9LFxuICApKSB7XG4gICAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMgPz8gW10pIHtcbiAgICAgIHNlYXJjaC5hcHBlbmQobmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgfVxuICBjb25zdCBxdWVyeSA9IHNlYXJjaC50b1N0cmluZygpO1xuICByZXR1cm4gcXVlcnkgPyBgPyR7cXVlcnl9YCA6IFwiXCI7XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|