cdk-nextjs 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/.jsii +2404 -2723
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1681 -1930
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +667 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1551 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +857 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +863 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +8 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  88. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  92. package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
  93. package/lib/lambdas/post-deploy/prune-s3.js +41 -12
  94. package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
  95. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  96. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  103. package/lib/nextjs-api.d.ts +102 -18
  104. package/lib/nextjs-api.js +338 -38
  105. package/lib/nextjs-api.test.js +537 -1
  106. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  107. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  108. package/lib/nextjs-build/nextjs-build.js +684 -327
  109. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  110. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  111. package/lib/nextjs-build/patch-fetch.js +1 -1
  112. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  113. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  114. package/lib/nextjs-cache.d.ts +82 -4
  115. package/lib/nextjs-cache.js +186 -10
  116. package/lib/nextjs-cache.test.js +176 -1
  117. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  118. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  120. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  121. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  122. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  123. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  124. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  125. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  126. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  127. package/lib/nextjs-distribution.d.ts +194 -23
  128. package/lib/nextjs-distribution.js +535 -62
  129. package/lib/nextjs-distribution.test.d.ts +1 -0
  130. package/lib/nextjs-distribution.test.js +697 -0
  131. package/lib/nextjs-post-deploy.d.ts +13 -5
  132. package/lib/nextjs-post-deploy.js +13 -10
  133. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  134. package/lib/nextjs-post-deploy.test.js +34 -0
  135. package/lib/nextjs-static-assets.d.ts +17 -4
  136. package/lib/nextjs-static-assets.js +22 -5
  137. package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
  138. package/lib/root-constructs/nextjs-base-construct.js +139 -47
  139. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  140. package/lib/root-constructs/nextjs-global-containers.js +20 -71
  141. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  142. package/lib/root-constructs/nextjs-global-functions.js +52 -70
  143. package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
  144. package/lib/root-constructs/nextjs-regional-containers.js +8 -15
  145. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  146. package/lib/root-constructs/nextjs-regional-functions.js +8 -26
  147. package/lib/runtime/api-gateway-path.d.ts +34 -0
  148. package/lib/runtime/api-gateway-path.js +71 -0
  149. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  150. package/lib/runtime/api-gateway-path.test.js +65 -0
  151. package/lib/runtime/case-redirect.d.ts +22 -0
  152. package/lib/runtime/case-redirect.js +63 -0
  153. package/lib/runtime/case-redirect.test.d.ts +1 -0
  154. package/lib/runtime/case-redirect.test.js +32 -0
  155. package/lib/runtime/core.d.ts +234 -0
  156. package/lib/runtime/core.js +1216 -0
  157. package/lib/runtime/core.test.d.ts +1 -0
  158. package/lib/runtime/core.test.js +1686 -0
  159. package/lib/runtime/deployment-root.d.ts +13 -0
  160. package/lib/runtime/deployment-root.js +29 -0
  161. package/lib/runtime/dispatch.d.ts +331 -0
  162. package/lib/runtime/dispatch.js +751 -0
  163. package/lib/runtime/dispatch.test.d.ts +1 -0
  164. package/lib/runtime/dispatch.test.js +853 -0
  165. package/lib/runtime/entrypoints.d.ts +57 -0
  166. package/lib/runtime/entrypoints.js +115 -0
  167. package/lib/runtime/http/abort-signal.d.ts +6 -0
  168. package/lib/runtime/http/abort-signal.js +19 -0
  169. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  170. package/lib/runtime/http/abort-signal.test.js +49 -0
  171. package/lib/runtime/http/node-server.d.ts +38 -0
  172. package/lib/runtime/http/node-server.js +99 -0
  173. package/lib/runtime/http/node-server.test.d.ts +1 -0
  174. package/lib/runtime/http/node-server.test.js +96 -0
  175. package/lib/runtime/http/node-sink.d.ts +16 -0
  176. package/lib/runtime/http/node-sink.js +48 -0
  177. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  178. package/lib/runtime/http/node-sink.test.js +66 -0
  179. package/lib/runtime/http/request.d.ts +62 -0
  180. package/lib/runtime/http/request.js +134 -0
  181. package/lib/runtime/http/request.test.d.ts +1 -0
  182. package/lib/runtime/http/request.test.js +103 -0
  183. package/lib/runtime/http/response.d.ts +77 -0
  184. package/lib/runtime/http/response.js +229 -0
  185. package/lib/runtime/http/response.test.d.ts +1 -0
  186. package/lib/runtime/http/response.test.js +178 -0
  187. package/lib/runtime/http/sink.d.ts +73 -0
  188. package/lib/runtime/http/sink.js +188 -0
  189. package/lib/runtime/http/sink.test.d.ts +1 -0
  190. package/lib/runtime/http/sink.test.js +257 -0
  191. package/lib/runtime/image-utils.d.ts +78 -0
  192. package/lib/runtime/image-utils.js +129 -0
  193. package/lib/runtime/image-utils.test.d.ts +1 -0
  194. package/lib/runtime/image-utils.test.js +237 -0
  195. package/lib/runtime/image.d.ts +76 -0
  196. package/lib/runtime/image.js +296 -0
  197. package/lib/runtime/image.test.d.ts +1 -0
  198. package/lib/runtime/image.test.js +405 -0
  199. package/lib/runtime/lambda-event.d.ts +4 -0
  200. package/lib/runtime/lambda-event.js +113 -0
  201. package/lib/runtime/lambda-event.test.d.ts +1 -0
  202. package/lib/runtime/lambda-event.test.js +119 -0
  203. package/lib/runtime/lambda.mjs +41600 -0
  204. package/lib/runtime/load-module.d.ts +8 -0
  205. package/lib/runtime/load-module.js +35 -0
  206. package/lib/runtime/manifest.d.ts +215 -0
  207. package/lib/runtime/manifest.js +118 -0
  208. package/lib/runtime/middleware.d.ts +43 -0
  209. package/lib/runtime/middleware.js +113 -0
  210. package/lib/runtime/middleware.test.d.ts +1 -0
  211. package/lib/runtime/middleware.test.js +259 -0
  212. package/lib/runtime/next-modules.d.ts +71 -0
  213. package/lib/runtime/next-modules.js +144 -0
  214. package/lib/runtime/next-modules.test.d.ts +1 -0
  215. package/lib/runtime/next-modules.test.js +34 -0
  216. package/lib/runtime/public-files.d.ts +32 -0
  217. package/lib/runtime/public-files.js +117 -0
  218. package/lib/runtime/public-files.test.d.ts +1 -0
  219. package/lib/runtime/public-files.test.js +97 -0
  220. package/lib/runtime/server.mjs +41593 -0
  221. package/lib/runtime/static-files.d.ts +50 -0
  222. package/lib/runtime/static-files.js +266 -0
  223. package/lib/runtime/static-files.test.d.ts +1 -0
  224. package/lib/runtime/static-files.test.js +118 -0
  225. package/lib/runtime/util.d.ts +28 -0
  226. package/lib/runtime/util.js +79 -0
  227. package/lib/utils/base-path.d.ts +106 -13
  228. package/lib/utils/base-path.js +254 -41
  229. package/lib/utils/base-path.test.js +219 -51
  230. package/lib/utils/get-architecture.d.ts +7 -8
  231. package/lib/utils/get-architecture.js +12 -13
  232. package/lib/utils/zip-directory.d.ts +14 -0
  233. package/lib/utils/zip-directory.js +121 -0
  234. package/lib/utils/zip-directory.test.d.ts +1 -0
  235. package/lib/utils/zip-directory.test.js +99 -0
  236. package/package.json +22 -3
  237. package/scripts/capture-adapter-fixture.mjs +325 -0
  238. package/scripts/e2e-deploy.sh +398 -0
  239. package/scripts/e2e-harness/README.md +707 -0
  240. package/scripts/e2e-harness/app.js +370 -0
  241. package/scripts/e2e-harness/common.sh +249 -0
  242. package/scripts/e2e-harness/screen.mjs +302 -0
  243. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  244. package/scripts/e2e-harness/type-filters.mjs +47 -0
  245. package/scripts/e2e-logs.sh +75 -0
  246. package/scripts/e2e-offline.sh +91 -0
  247. package/scripts/e2e-sweep.sh +370 -0
  248. package/scripts/e2e-warm.sh +114 -0
  249. package/scripts/zero-config-build.mjs +418 -0
  250. package/docs/1k-concurrent-users-executions.png +0 -0
  251. package/docs/plans/adapter-runtime-release.md +0 -362
  252. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  253. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  254. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  255. package/lib/image-optimization/handler-utils.d.ts +0 -34
  256. package/lib/image-optimization/handler-utils.js +0 -83
  257. package/lib/image-optimization/handler-utils.test.js +0 -178
  258. package/lib/nextjs-build/functions.Dockerfile +0 -31
  259. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  260. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  261. package/lib/utils/experimental-flags.d.ts +0 -24
  262. package/lib/utils/experimental-flags.js +0 -30
  263. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
@@ -0,0 +1,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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWV2ZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvbGFtYmRhLWV2ZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBbUJBLDRDQXFDQztBQS9DRCx5REFBMkQ7QUFLM0Qsb0RBQW9EO0FBQ3BELFNBQVMsaUJBQWlCLENBQUMsS0FBa0I7SUFDM0MsT0FBTyxZQUFZLElBQUksS0FBSyxDQUFDO0FBQy9CLENBQUM7QUFFRCxTQUFnQixnQkFBZ0IsQ0FDOUIsS0FBa0IsRUFDbEIsUUFBZ0I7SUFFaEIsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQzNELElBQUksaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM3QixPQUFPO1lBQ0wsTUFBTSxFQUFFLEtBQUssQ0FBQyxVQUFVO1lBQ3hCLDBFQUEwRTtZQUMxRSxzREFBc0Q7WUFDdEQsR0FBRyxFQUFFLElBQUEsd0NBQXFCLEVBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDaEUsT0FBTyxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDM0IsSUFBSTtZQUNKLGFBQWEsRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxRQUFRO1NBQ3ZELENBQUM7SUFDSixDQUFDO0lBQ0QsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7SUFDdEMsT0FBTztRQUNMLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtRQUNuQix3RUFBd0U7UUFDeEUsV0FBVztRQUNYLEdBQUcsRUFDRCxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMx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QUFNLElBQUksRUFBRSxFQUFFLENBQUM7WUFDakMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDaEMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNsQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG4vKipcbiAqIExhbWJkYSBldmVudCDihpIge0BsaW5rIFJ1bnRpbWVSZXF1ZXN0fSwgZm9yIGJvdGggZXZlbnQgc2hhcGVzIHRoZSBGdW5jdGlvbnNcbiAqIHNoZWxsIChgbGFtYmRhLm10c2ApIGlzIHJlYWNoZWQgd2l0aC4gSXRzIG93biBtb2R1bGUgc28gaXQgY2FuIGJlIHRlc3RlZDpcbiAqIGBsYW1iZGEubXRzYCBzdGFydHMgbG9hZGluZyB0aGUgcnVudGltZSwgYW5kIG5lZWRzIHRoZSBgYXdzbGFtYmRhYCBnbG9iYWwsIHRoZVxuICogbW9tZW50IGl0IGlzIGltcG9ydGVkLlxuICovXG5pbXBvcnQgdHlwZSB7IEluY29taW5nSHR0cEhlYWRlcnMgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgdHlwZSB7IEFQSUdhdGV3YXlQcm94eUV2ZW50LCBMYW1iZGFGdW5jdGlvblVSTEV2ZW50IH0gZnJvbSBcImF3cy1sYW1iZGFcIjtcbmltcG9ydCB7IGFwaUdhdGV3YXlSZXF1ZXN0UGF0aCB9IGZyb20gXCIuL2FwaS1nYXRld2F5LXBhdGhcIjtcbmltcG9ydCB0eXBlIHsgUnVudGltZVJlcXVlc3QgfSBmcm9tIFwiLi9jb3JlXCI7XG5cbmV4cG9ydCB0eXBlIExhbWJkYUV2ZW50ID0gTGFtYmRhRnVuY3Rpb25VUkxFdmVudCB8IEFQSUdhdGV3YXlQcm94eUV2ZW50O1xuXG4vKiogT25seSB0aGUgUkVTVCBBUEkgZXZlbnQgY2FycmllcyBgaHR0cE1ldGhvZGAuICovXG5mdW5jdGlvbiBpc0FwaUdhdGV3YXlFdmVudChldmVudDogTGFtYmRhRXZlbnQpOiBldmVudCBpcyBBUElHYXRld2F5UHJveHlFdmVudCB7XG4gIHJldHVybiBcImh0dHBNZXRob2RcIiBpbiBldmVudDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUnVudGltZVJlcXVlc3QoXG4gIGV2ZW50OiBMYW1iZGFFdmVudCxcbiAgYmFzZVBhdGg6IHN0cmluZyxcbik6IFJ1bnRpbWVSZXF1ZXN0IHtcbiAgY29uc3QgYm9keSA9IGRlY29kZUJvZHkoZXZlbnQuYm9keSwgZXZlbnQuaXNCYXNlNjRFbmNvZGVkKTtcbiAgaWYgKGlzQXBpR2F0ZXdheUV2ZW50KGV2ZW50KSkge1xuICAgIHJldHVybiB7XG4gICAgICBtZXRob2Q6IGV2ZW50Lmh0dHBNZXRob2QsXG4gICAgICAvLyBXaXRoIHRoZSBzdGFnZSBBUEkgR2F0ZXdheSBzdHJpcHBlZCBwdXQgYmFjaywgYnV0IG9ubHkgZm9yIGFuIGFwcCB3aG9zZVxuICAgICAgLy8gYGJhc2VQYXRoYCBleHBlY3RzIGl0OyBzZWUgYGFwaUdhdGV3YXlSZXF1ZXN0UGF0aGAuXG4gICAgICB1cmw6IGFwaUdhdGV3YXlSZXF1ZXN0UGF0aChldmVudCwgYmFzZVBhdGgpICsgZm9ybWF0UXVlcnkoZXZlbnQpLFxuICAgICAgaGVhZGVyczogcmVzdEhlYWRlcnMoZXZlbnQpLFxuICAgICAgYm9keSxcbiAgICAgIHJlbW90ZUFkZHJlc3M6IGV2ZW50LnJlcXVlc3RDb250ZXh0LmlkZW50aXR5Py5zb3VyY2VJcCxcbiAgICB9O1xuICB9XG4gIGNvbnN0IHsgaHR0cCB9ID0gZXZlbnQucmVxdWVzdENvbnRleHQ7XG4gIHJldHVybiB7XG4gICAgbWV0aG9kOiBodHRwLm1ldGhvZCxcbiAgICAvLyBSYXcsIHN0aWxsIHBlcmNlbnQtZW5jb2RlZCwgd2hpY2ggaXMgd2hhdCBOZXh0LmpzJ3Mgb3duIG5vcm1hbGl6YXRpb25cbiAgICAvLyBleHBlY3RzLlxuICAgIHVybDpcbiAgICAgIGV2ZW50LnJhd1BhdGggKyAoZXZlbnQucmF3UXVlcnlTdHJpbmcgPyBgPyR7ZXZlbnQucmF3UXVlcnlTdHJpbmd9YCA6IFwiXCIpLFxuICAgIGhlYWRlcnM6IGZ1bmN0aW9uVXJsSGVhZGVycyhldmVudCksXG4gICAgYm9keSxcbiAgICByZW1vdGVBZGRyZXNzOiBodHRwLnNvdXJjZUlwLFxuICAgIC8vIFRydXN0ZWQgZm9yIGFueSBJQU0tYXV0aG9yaXplZCBpbnZva2VyOiBpbiBwcmFjdGljZSBDbG91ZEZyb250J3MgT3JpZ2luXG4gICAgLy8gQWNjZXNzIENvbnRyb2wsIHdob3NlIHZpZXdlci1yZXF1ZXN0IGZ1bmN0aW9uIG92ZXJ3cml0ZXNcbiAgICAvLyBgeC1mb3J3YXJkZWQtaG9zdGAgd2l0aCB0aGUgdmlld2VyJ3MgYEhvc3RgIChzZWVcbiAgICAvLyBgUnVudGltZVJlcXVlc3QudHJ1c3RGb3J3YXJkZWRIb3N0YDsgYE5leHRqc0Rpc3RyaWJ1dGlvbmAgcmVmdXNlcyBhblxuICAgIC8vIG92ZXJyaWRlIHRoYXQgd291bGQgcmVwbGFjZSB0aGF0IGZ1bmN0aW9uLFxuICAgIC8vIGB3aXRoRHluYW1pY0Z1bmN0aW9uQXNzb2NpYXRpb25zYCksIHBsdXMgcHJpbmNpcGFscyBncmFudGVkXG4gICAgLy8gYGxhbWJkYTpJbnZva2VGdW5jdGlvblVybGAsIHdoaWNoIGFyZSBhbHJlYWR5IHRydXN0ZWQgd2l0aCB0aGUgZnVuY3Rpb24uXG4gICAgLy8gR2F0ZWQgb24gdGhlIHNpZ25hdHVyZSBMYW1iZGEgdmVyaWZpZWQsIG5vdCBhc3N1bWVkOiBhIFVSTCBvdmVycmlkZGVuIHRvXG4gICAgLy8gYGF1dGhUeXBlOiBOT05FYCBjYW4gYmUgY2FsbGVkIGJ5IGFueW9uZSwgd2l0aCBhbnkgaGVhZGVyLlxuICAgIHRydXN0Rm9yd2FyZGVkSG9zdDogaXNJYW1BdXRoZW50aWNhdGVkKGV2ZW50KSxcbiAgfTtcbn1cblxuLyoqXG4gKiBMYW1iZGEgc2V0cyBgYXV0aG9yaXplci5pYW1gIG9ubHkgZm9yIGEgcmVxdWVzdCBpdCB2ZXJpZmllZCB0aGUgU2lnVjQgb2Yg4oCUIGJ5XG4gKiBhbnkgcHJpbmNpcGFsIGFsbG93ZWQgdG8gaW52b2tlIHRoZSBVUkwsIG5vdCBvbmx5IENsb3VkRnJvbnQuXG4gKi9cbmZ1bmN0aW9uIGlzSWFtQXV0aGVudGljYXRlZChldmVudDogTGFtYmRhRnVuY3Rpb25VUkxFdmVudCk6IGJvb2xlYW4ge1xuICBjb25zdCB7IGF1dGhvcml6ZXIgfSA9IGV2ZW50LnJlcXVlc3RDb250ZXh0IGFzIHtcbiAgICBhdXRob3JpemVyPzogeyBpYW0/OiB1bmtub3duIH07XG4gIH07XG4gIHJldHVybiBhdXRob3JpemVyPy5pYW0gIT09IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZGVjb2RlQm9keShcbiAgYm9keTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgaXNCYXNlNjRFbmNvZGVkOiBib29sZWFuLFxuKTogQnVmZmVyIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGJvZHkgPT09IG51bGwgfHwgYm9keSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gQnVmZmVyLmZyb20oYm9keSwgaXNCYXNlNjRFbmNvZGVkID8gXCJiYXNlNjRcIiA6IFwidXRmLThcIik7XG59XG5cbi8qKlxuICogUGF5bG9hZCB2MiBsaWZ0cyBjb29raWVzIG91dCBvZiB0aGUgaGVhZGVycyBpbnRvIHRoZWlyIG93biBhcnJheSwgc28gdGhleSBoYXZlXG4gKiB0byBiZSBwdXQgYmFjayDigJQgTmV4dC5qcyByZWFkcyBgcmVxLmhlYWRlcnMuY29va2llYCBmb3IgZHJhZnQgbW9kZSwgdGhlXG4gKiBwcmVyZW5kZXIgYnlwYXNzLCBhbmQgYW55dGhpbmcgYSByb3V0ZSBoYW5kbGVyIGRvZXMgd2l0aCBgY29va2llcygpYC5cbiAqL1xuZnVuY3Rpb24gZnVuY3Rpb25VcmxIZWFkZXJzKFxuICBldmVudDogTGFtYmRhRnVuY3Rpb25VUkxFdmVudCxcbik6IEluY29taW5nSHR0cEhlYWRlcnMge1xuICBjb25zdCBoZWFkZXJzOiBJbmNvbWluZ0h0dHBIZWFkZXJzID0ge307XG4gIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhldmVudC5oZWFkZXJzKSkge1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBoZWFkZXJzW25hbWUudG9Mb3dlckNhc2UoKV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cbiAgaWYgKGV2ZW50LmNvb2tpZXM/Lmxlbmd0aCkge1xuICAgIGhlYWRlcnMuY29va2llID0gZXZlbnQuY29va2llcy5qb2luKFwiOyBcIik7XG4gIH1cbiAgcmV0dXJuIGhlYWRlcnM7XG59XG5cbi8qKlxuICogYG11bHRpVmFsdWVIZWFkZXJzYCBvbmx5OiBBUEkgR2F0ZXdheSBhbHdheXMgc2VuZHMgaXQsIGFzIGEgc3VwZXJzZXQgb2YgdGhlXG4gKiBzaW5nbGUtdmFsdWVkIG1hcCwgd2hpY2gga2VlcHMgb25seSB0aGUgbGFzdCB2YWx1ZSBvZiBhIHJlcGVhdGVkIGhlYWRlci5cbiAqXG4gKiBgY29va2llYCBpcyByZWpvaW5lZCB3aXRoIGBcIjsgXCJgIHJhdGhlciB0aGFuIHRoZSBgXCIsIFwiYCBldmVyeSBvdGhlciBoZWFkZXIgdXNlcyxcbiAqIGJlY2F1c2UgdGhhdCBpcyB0aGUgc2VwYXJhdG9yIHRoZSBmaWVsZCdzIG93biBncmFtbWFyIHVzZXMgKFJGQyA2MjY1KSBhbmQgd2hhdFxuICogZXZlcnkgY29va2llIHBhcnNlciBzcGxpdHMgb24uIEpvaW5pbmcgdHdvIGBDb29raWVgIGZpZWxkcyB3aXRoIGEgY29tbWEgcHJvZHVjZWRcbiAqIGBjb29raWU6IFwiYT0xLCBiPTJcImAsIHdoaWNoIHBhcnNlcyBhcyB0aGUgc2luZ2xlIGNvb2tpZSBgYSA9IFwiMSwgYj0yXCJgIOKAlCBldmVyeVxuICogY29va2llIGFmdGVyIHRoZSBmaXJzdCBpcyBsb3N0LCBpbmNsdWRpbmcgYF9fcHJlcmVuZGVyX2J5cGFzc2AgYW5kXG4gKiBgX19uZXh0X3ByZXZpZXdfZGF0YWAsIHNvIGRyYWZ0IG1vZGUgc2lsZW50bHkgc3RvcHBlZCB3b3JraW5nLlxuICovXG5mdW5jdGlvbiByZXN0SGVhZGVycyhldmVudDogQVBJR2F0ZXdheVByb3h5RXZlbnQpOiBJbmNvbWluZ0h0dHBIZWFkZXJzIHtcbiAgY29uc3QgaGVhZGVyczogSW5jb21pbmdIdHRwSGVhZGVycyA9IHt9O1xuICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZXNdIG9mIE9iamVjdC5lbnRyaWVzKGV2ZW50Lm11bHRpVmFsdWVIZWFkZXJzID8/IHt9KSkge1xuICAgIGlmICh2YWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgY29uc3Qga2V5ID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaGVhZGVyc1trZXldID1cbiAgICAgICAgdmFsdWVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgID8gdmFsdWVzWzBdXG4gICAgICAgICAgOiB2YWx1ZXMuam9pbihrZXkgPT09IFwiY29va2llXCIgPyBcIjsgXCIgOiBcIiwgXCIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gaGVhZGVycztcbn1cblxuLyoqXG4gKiBSZWJ1aWxkcyB0aGUgcXVlcnkgc3RyaW5nIEFQSSBHYXRld2F5IGFscmVhZHkgcGFyc2VkIChhbmQgZGVjb2RlZCkgZm9yIHVzLlxuICogUmUtZW5jb2RpbmcgaXMgcmVxdWlyZWQsIG5vdCBjb3NtZXRpYzogYD9xPWElMjBiYCBhcnJpdmVzIGFzIGBhIGJgLCBhbmQgcGFzc2luZ1xuICogdGhhdCB0aHJvdWdoIHVuZXNjYXBlZCBwcm9kdWNlcyBhIFVSTCB0aGF0IGBuZXcgVVJMKClgIG1hbmdsZXMuXG4gKi9cbmZ1bmN0aW9uIGZvcm1hdFF1ZXJ5KGV2ZW50OiBBUElHYXRld2F5UHJveHlFdmVudCk6IHN0cmluZyB7XG4gIGNvbnN0IHNlYXJjaCA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVzXSBvZiBPYmplY3QuZW50cmllcyhcbiAgICBldmVudC5tdWx0aVZhbHVlUXVlcnlTdHJpbmdQYXJhbWV0ZXJzID8/IHt9LFxuICApKSB7XG4gICAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMgPz8gW10pIHtcbiAgICAgIHNlYXJjaC5hcHBlbmQobmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgfVxuICBjb25zdCBxdWVyeSA9IHNlYXJjaC50b1N0cmluZygpO1xuICByZXR1cm4gcXVlcnkgPyBgPyR7cXVlcnl9YCA6IFwiXCI7XG59XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};