cdk-nextjs 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/.jsii +2467 -2714
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1725 -1909
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
  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 +687 -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 +1548 -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 +852 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +861 -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 +13 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
  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/post-deploy.lambda.js +3 -2
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  88. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  92. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  93. package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
  94. package/lib/lambdas/post-deploy/prune-s3.js +54 -15
  95. package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
  96. package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  103. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  104. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  105. package/lib/nextjs-api.d.ts +107 -18
  106. package/lib/nextjs-api.js +349 -39
  107. package/lib/nextjs-api.test.js +582 -1
  108. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  109. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  110. package/lib/nextjs-build/nextjs-build.js +684 -327
  111. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  112. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  113. package/lib/nextjs-build/patch-fetch.js +1 -1
  114. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  115. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  116. package/lib/nextjs-cache.d.ts +82 -4
  117. package/lib/nextjs-cache.js +186 -10
  118. package/lib/nextjs-cache.test.js +176 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  120. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  121. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  122. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  123. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  124. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  125. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  126. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  127. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  128. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  129. package/lib/nextjs-distribution.d.ts +194 -23
  130. package/lib/nextjs-distribution.js +535 -62
  131. package/lib/nextjs-distribution.test.d.ts +1 -0
  132. package/lib/nextjs-distribution.test.js +697 -0
  133. package/lib/nextjs-post-deploy.d.ts +23 -3
  134. package/lib/nextjs-post-deploy.js +14 -10
  135. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  136. package/lib/nextjs-post-deploy.test.js +34 -0
  137. package/lib/nextjs-static-assets.d.ts +23 -4
  138. package/lib/nextjs-static-assets.js +29 -6
  139. package/lib/nextjs-static-assets.test.js +20 -1
  140. package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
  141. package/lib/root-constructs/nextjs-base-construct.js +144 -34
  142. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  143. package/lib/root-constructs/nextjs-global-containers.js +20 -70
  144. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  145. package/lib/root-constructs/nextjs-global-functions.js +52 -69
  146. package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
  147. package/lib/root-constructs/nextjs-regional-containers.js +17 -15
  148. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  149. package/lib/root-constructs/nextjs-regional-functions.js +8 -25
  150. package/lib/runtime/api-gateway-path.d.ts +34 -0
  151. package/lib/runtime/api-gateway-path.js +71 -0
  152. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  153. package/lib/runtime/api-gateway-path.test.js +65 -0
  154. package/lib/runtime/case-redirect.d.ts +22 -0
  155. package/lib/runtime/case-redirect.js +63 -0
  156. package/lib/runtime/case-redirect.test.d.ts +1 -0
  157. package/lib/runtime/case-redirect.test.js +32 -0
  158. package/lib/runtime/core.d.ts +234 -0
  159. package/lib/runtime/core.js +1213 -0
  160. package/lib/runtime/core.test.d.ts +1 -0
  161. package/lib/runtime/core.test.js +1678 -0
  162. package/lib/runtime/deployment-root.d.ts +13 -0
  163. package/lib/runtime/deployment-root.js +29 -0
  164. package/lib/runtime/dispatch.d.ts +331 -0
  165. package/lib/runtime/dispatch.js +751 -0
  166. package/lib/runtime/dispatch.test.d.ts +1 -0
  167. package/lib/runtime/dispatch.test.js +853 -0
  168. package/lib/runtime/entrypoints.d.ts +57 -0
  169. package/lib/runtime/entrypoints.js +115 -0
  170. package/lib/runtime/http/abort-signal.d.ts +6 -0
  171. package/lib/runtime/http/abort-signal.js +19 -0
  172. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  173. package/lib/runtime/http/abort-signal.test.js +49 -0
  174. package/lib/runtime/http/node-server.d.ts +38 -0
  175. package/lib/runtime/http/node-server.js +99 -0
  176. package/lib/runtime/http/node-server.test.d.ts +1 -0
  177. package/lib/runtime/http/node-server.test.js +96 -0
  178. package/lib/runtime/http/node-sink.d.ts +16 -0
  179. package/lib/runtime/http/node-sink.js +48 -0
  180. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  181. package/lib/runtime/http/node-sink.test.js +66 -0
  182. package/lib/runtime/http/request.d.ts +62 -0
  183. package/lib/runtime/http/request.js +134 -0
  184. package/lib/runtime/http/request.test.d.ts +1 -0
  185. package/lib/runtime/http/request.test.js +103 -0
  186. package/lib/runtime/http/response.d.ts +77 -0
  187. package/lib/runtime/http/response.js +229 -0
  188. package/lib/runtime/http/response.test.d.ts +1 -0
  189. package/lib/runtime/http/response.test.js +178 -0
  190. package/lib/runtime/http/sink.d.ts +73 -0
  191. package/lib/runtime/http/sink.js +188 -0
  192. package/lib/runtime/http/sink.test.d.ts +1 -0
  193. package/lib/runtime/http/sink.test.js +257 -0
  194. package/lib/runtime/image-utils.d.ts +78 -0
  195. package/lib/runtime/image-utils.js +129 -0
  196. package/lib/runtime/image-utils.test.d.ts +1 -0
  197. package/lib/runtime/image-utils.test.js +237 -0
  198. package/lib/runtime/image.d.ts +76 -0
  199. package/lib/runtime/image.js +296 -0
  200. package/lib/runtime/image.test.d.ts +1 -0
  201. package/lib/runtime/image.test.js +405 -0
  202. package/lib/runtime/lambda-event.d.ts +4 -0
  203. package/lib/runtime/lambda-event.js +113 -0
  204. package/lib/runtime/lambda-event.test.d.ts +1 -0
  205. package/lib/runtime/lambda-event.test.js +119 -0
  206. package/lib/runtime/lambda.mjs +41595 -0
  207. package/lib/runtime/load-module.d.ts +8 -0
  208. package/lib/runtime/load-module.js +35 -0
  209. package/lib/runtime/manifest.d.ts +215 -0
  210. package/lib/runtime/manifest.js +118 -0
  211. package/lib/runtime/middleware.d.ts +43 -0
  212. package/lib/runtime/middleware.js +113 -0
  213. package/lib/runtime/middleware.test.d.ts +1 -0
  214. package/lib/runtime/middleware.test.js +259 -0
  215. package/lib/runtime/next-modules.d.ts +55 -0
  216. package/lib/runtime/next-modules.js +124 -0
  217. package/lib/runtime/next-modules.test.d.ts +1 -0
  218. package/lib/runtime/next-modules.test.js +34 -0
  219. package/lib/runtime/public-files.d.ts +32 -0
  220. package/lib/runtime/public-files.js +117 -0
  221. package/lib/runtime/public-files.test.d.ts +1 -0
  222. package/lib/runtime/public-files.test.js +97 -0
  223. package/lib/runtime/server.mjs +41588 -0
  224. package/lib/runtime/static-files.d.ts +50 -0
  225. package/lib/runtime/static-files.js +266 -0
  226. package/lib/runtime/static-files.test.d.ts +1 -0
  227. package/lib/runtime/static-files.test.js +118 -0
  228. package/lib/runtime/util.d.ts +28 -0
  229. package/lib/runtime/util.js +79 -0
  230. package/lib/utils/base-path.d.ts +123 -11
  231. package/lib/utils/base-path.js +276 -39
  232. package/lib/utils/base-path.test.js +275 -50
  233. package/lib/utils/get-architecture.d.ts +7 -8
  234. package/lib/utils/get-architecture.js +12 -13
  235. package/lib/utils/zip-directory.d.ts +14 -0
  236. package/lib/utils/zip-directory.js +121 -0
  237. package/lib/utils/zip-directory.test.d.ts +1 -0
  238. package/lib/utils/zip-directory.test.js +99 -0
  239. package/package.json +22 -3
  240. package/scripts/capture-adapter-fixture.mjs +325 -0
  241. package/scripts/e2e-deploy.sh +398 -0
  242. package/scripts/e2e-harness/README.md +707 -0
  243. package/scripts/e2e-harness/app.js +370 -0
  244. package/scripts/e2e-harness/common.sh +249 -0
  245. package/scripts/e2e-harness/screen.mjs +302 -0
  246. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  247. package/scripts/e2e-harness/type-filters.mjs +47 -0
  248. package/scripts/e2e-logs.sh +75 -0
  249. package/scripts/e2e-offline.sh +91 -0
  250. package/scripts/e2e-sweep.sh +370 -0
  251. package/scripts/e2e-warm.sh +114 -0
  252. package/scripts/zero-config-build.mjs +418 -0
  253. package/docs/1k-concurrent-users-executions.png +0 -0
  254. package/docs/plans/adapter-runtime-release.md +0 -362
  255. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  256. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  257. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  258. package/lib/image-optimization/handler-utils.d.ts +0 -34
  259. package/lib/image-optimization/handler-utils.js +0 -83
  260. package/lib/image-optimization/handler-utils.test.js +0 -178
  261. package/lib/nextjs-build/functions.Dockerfile +0 -31
  262. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  263. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  264. package/lib/utils/experimental-flags.d.ts +0 -24
  265. package/lib/utils/experimental-flags.js +0 -30
  266. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pipeToSink = pipeToSink;
4
+ exports.acceptsGzip = acceptsGzip;
5
+ /**
6
+ * Connecting a {@link ShimServerResponse} to the bytes-out side of a shell, and
7
+ * the one thing that has to happen on the way: gzip.
8
+ *
9
+ * This lives in shared runtime code rather than in the Lambda shell on purpose.
10
+ * Neither managed layer can compress a *streamed* response:
11
+ *
12
+ * - API Gateway's `minCompressionSize` is set (`src/nextjs-api.ts`) but inert,
13
+ * because cdk-nextjs also sets `ResponseTransferMode.STREAM`, and STREAM drops
14
+ * content encoding outright — "If you want to compress your integration
15
+ * response, do this in your integration".
16
+ * - CloudFront requires the origin to send `Content-Length`, which a streamed
17
+ * response by definition does not. It still compresses non-streamed responses
18
+ * and S3 assets, so the gap is exactly streamed HTML and RSC payloads — the
19
+ * largest text responses we serve.
20
+ *
21
+ * Until the container path was dropped, Lambda Web Adapter did this for us, which
22
+ * is why nothing in the old code mentions it. **Don't "fix" the API Gateway or
23
+ * CloudFront settings expecting them to take over.**
24
+ *
25
+ * gzip rather than brotli: brotli's streaming throughput at default quality is
26
+ * poor, and CloudFront prefers `br` only when the origin didn't already encode —
27
+ * which stops applying the moment we set `content-encoding` ourselves.
28
+ */
29
+ const node_stream_1 = require("node:stream");
30
+ const promises_1 = require("node:stream/promises");
31
+ const node_zlib_1 = require("node:zlib");
32
+ /**
33
+ * Content types worth compressing. Everything Next streams as HTML or an RSC
34
+ * payload is `text/*`; images and fonts are already compressed, and gzipping an
35
+ * optimized AVIF just burns CPU.
36
+ */
37
+ const COMPRESSIBLE = /^(?:text\/|application\/(?:json|javascript|xml|manifest|rss\+xml|atom\+xml)|image\/svg\+xml)/;
38
+ /**
39
+ * Statuses whose body must not be compressed: 204 and 304 have none, and a 206's
40
+ * body is a byte range of the *uncompressed* representation.
41
+ *
42
+ * 206 is reachable — `serveStaticFile` is `send` underneath, which advertises
43
+ * `Accept-Ranges: bytes` and honors `Range` on the static HTML the runtime serves
44
+ * itself. Gzipping one produced a response whose `Content-Range` still described
45
+ * the uncompressed slice (`withGzipHeaders` drops `content-length` but cannot
46
+ * restate a range), so the client got bytes that did not match what it asked for.
47
+ */
48
+ const UNCOMPRESSABLE_STATUS = new Set([204, 206, 304]);
49
+ /** `compression`'s own test for the directive. */
50
+ const NO_TRANSFORM = /(?:^|,)\s*?no-transform\s*?(?:,|$)/i;
51
+ /**
52
+ * Pipe `res` into `sink`, gzipping when that is both allowed and useful.
53
+ *
54
+ * Resolves when the sink's stream has finished, which for Lambda is the point the
55
+ * client has the whole response. Must be called *before* anything writes to
56
+ * `res`, because it subscribes to the one-shot `"head"` event.
57
+ */
58
+ function pipeToSink(req, res, sink, options) {
59
+ return new Promise((resolve, reject) => {
60
+ let piping = false;
61
+ res.once("error", reject);
62
+ // Destroyed before the head went out, and without an error: a client that
63
+ // disconnected before the first byte, which `handle()` answers with
64
+ // `res.destroy()`. `Transform.destroy()` with no argument emits only
65
+ // `"close"`, and the pipeline below never started, so nothing else can ever
66
+ // settle this promise — leaving `handle()` awaiting it forever, its
67
+ // `waitUntil` work (ISR revalidation, cache writes) never flushed and the
68
+ // in-flight render's closure retained for the life of the process.
69
+ res.once("close", () => {
70
+ if (!piping) {
71
+ resolve();
72
+ }
73
+ });
74
+ res.once("head", (head) => {
75
+ piping = true;
76
+ const stages = [];
77
+ const gzip = shouldGzip(req, res, head, options);
78
+ if (gzip) {
79
+ const compressor = (0, node_zlib_1.createGzip)();
80
+ // Next.js calls `res.flush()` after each chunk it writes
81
+ // (`next/dist/server/pipe-readable.js`); without forwarding it, streamed
82
+ // HTML sits in zlib's buffer and the response arrives all at once.
83
+ res.flush = () => compressor.flush(node_zlib_1.constants.Z_SYNC_FLUSH);
84
+ stages.push(compressor);
85
+ }
86
+ if (sink.padEmptyBody) {
87
+ stages.push(padEmptyBody());
88
+ }
89
+ try {
90
+ stages.push(sink.begin(gzip ? withGzipHeaders(head) : head));
91
+ }
92
+ catch (error) {
93
+ // This runs inside whichever `res` call flushed the head — usually a
94
+ // `write()` from deep inside Next.js — so an escaping throw lands there,
95
+ // the pipeline below never starts, and nothing would settle this
96
+ // promise: `handle()` would hang. A sink's `writeHead` rejecting a
97
+ // header value is how it happens. Destroying `res` is what stops the
98
+ // writer; the `"error"` that emits is a no-op after the `reject`.
99
+ for (const stage of stages) {
100
+ stage.destroy();
101
+ }
102
+ reject(error);
103
+ res.destroy(error instanceof Error ? error : new Error(String(error)));
104
+ return;
105
+ }
106
+ (0, promises_1.pipeline)(res, ...stages).then(resolve, reject);
107
+ });
108
+ });
109
+ }
110
+ function shouldGzip(req, res, head, options) {
111
+ if (!options.compress) {
112
+ return false;
113
+ }
114
+ if (req.method === "HEAD" || UNCOMPRESSABLE_STATUS.has(head.statusCode)) {
115
+ return false;
116
+ }
117
+ // Next.js encodes some responses itself; double-encoding is not a thing.
118
+ if (res.hasHeader("content-encoding")) {
119
+ return false;
120
+ }
121
+ if (!COMPRESSIBLE.test(head.headers["content-type"] ?? "")) {
122
+ return false;
123
+ }
124
+ // The response's opt-out, which `next start`'s `compression` honors too: an
125
+ // SSE stream sets it so that nothing buffers its events.
126
+ if (NO_TRANSFORM.test(head.headers["cache-control"] ?? "")) {
127
+ return false;
128
+ }
129
+ return acceptsGzip(req.headers["accept-encoding"]);
130
+ }
131
+ /**
132
+ * A `q=0` on gzip is a refusal, and both `*` forms have to be honored, so this
133
+ * parses rather than substring-matching.
134
+ */
135
+ function acceptsGzip(header) {
136
+ const value = Array.isArray(header) ? header.join(",") : header;
137
+ if (!value) {
138
+ return false;
139
+ }
140
+ let wildcard;
141
+ for (const part of value.split(",")) {
142
+ const [rawName, ...params] = part.split(";");
143
+ const name = rawName.trim().toLowerCase();
144
+ if (name !== "gzip" && name !== "*") {
145
+ continue;
146
+ }
147
+ const q = params
148
+ .map((p) => p.trim().toLowerCase())
149
+ .find((p) => p.startsWith("q="));
150
+ const accepted = q === undefined || Number(q.slice(2)) > 0;
151
+ if (name === "gzip") {
152
+ return accepted;
153
+ }
154
+ wildcard = accepted;
155
+ }
156
+ return wildcard ?? false;
157
+ }
158
+ function withGzipHeaders(head) {
159
+ const headers = {
160
+ ...head.headers,
161
+ "content-encoding": "gzip",
162
+ };
163
+ // The length we were told is the uncompressed one, and we do not know the
164
+ // compressed one until the stream ends.
165
+ delete headers["content-length"];
166
+ const vary = headers.vary;
167
+ if (!vary) {
168
+ headers.vary = "Accept-Encoding";
169
+ }
170
+ else if (!/\baccept-encoding\b/i.test(vary)) {
171
+ headers.vary = `${vary}, Accept-Encoding`;
172
+ }
173
+ return { ...head, headers };
174
+ }
175
+ /** See {@link ResponseSink.padEmptyBody}. */
176
+ function padEmptyBody() {
177
+ let wroteSomething = false;
178
+ return new node_stream_1.Transform({
179
+ transform(chunk, _encoding, callback) {
180
+ wroteSomething = true;
181
+ callback(null, chunk);
182
+ },
183
+ flush(callback) {
184
+ callback(null, wroteSomething ? undefined : " ");
185
+ },
186
+ });
187
+ }
188
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2luay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ydW50aW1lL2h0dHAvc2luay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQStGQSxnQ0F5REM7QUFpQ0Qsa0NBc0JDO0FBL01EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVCRztBQUNILDZDQUFrRDtBQUNsRCxtREFBZ0Q7QUFDaEQseUNBQWtEO0FBa0NsRDs7OztHQUlHO0FBQ0gsTUFBTSxZQUFZLEdBQ2hCLDhGQUE4RixDQUFDO0FBRWpHOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFFdkQsa0RBQWtEO0FBQ2xELE1BQU0sWUFBWSxHQUFHLHFDQUFxQyxDQUFDO0FBTzNEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFVBQVUsQ0FDeEIsR0FBd0IsRUFDeEIsR0FBdUIsRUFDdkIsSUFBa0IsRUFDbEIsT0FBb0I7SUFFcEIsT0FBTyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUMzQyxJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDbkIsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDMUIsMEVBQTBFO1FBQzFFLG9FQUFvRTtRQUNwRSxxRUFBcUU7UUFDckUsNEVBQTRFO1FBQzVFLG9FQUFvRTtRQUNwRSwwRUFBMEU7UUFDMUUsbUVBQW1FO1FBQ25FLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUNyQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ1osT0FBTyxFQUFFLENBQUM7WUFDWixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQWtCLEVBQUUs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c0NvbnRlbnQiOlsiLyoqXG4gKiBDb25uZWN0aW5nIGEge0BsaW5rIFNoaW1TZXJ2ZXJSZXNwb25zZX0gdG8gdGhlIGJ5dGVzLW91dCBzaWRlIG9mIGEgc2hlbGwsIGFuZFxuICogdGhlIG9uZSB0aGluZyB0aGF0IGhhcyB0byBoYXBwZW4gb24gdGhlIHdheTogZ3ppcC5cbiAqXG4gKiBUaGlzIGxpdmVzIGluIHNoYXJlZCBydW50aW1lIGNvZGUgcmF0aGVyIHRoYW4gaW4gdGhlIExhbWJkYSBzaGVsbCBvbiBwdXJwb3NlLlxuICogTmVpdGhlciBtYW5hZ2VkIGxheWVyIGNhbiBjb21wcmVzcyBhICpzdHJlYW1lZCogcmVzcG9uc2U6XG4gKlxuICogLSBBUEkgR2F0ZXdheSdzIGBtaW5Db21wcmVzc2lvblNpemVgIGlzIHNldCAoYHNyYy9uZXh0anMtYXBpLnRzYCkgYnV0IGluZXJ0LFxuICogICBiZWNhdXNlIGNkay1uZXh0anMgYWxzbyBzZXRzIGBSZXNwb25zZVRyYW5zZmVyTW9kZS5TVFJFQU1gLCBhbmQgU1RSRUFNIGRyb3BzXG4gKiAgIGNvbnRlbnQgZW5jb2Rpbmcgb3V0cmlnaHQg4oCUIFwiSWYgeW91IHdhbnQgdG8gY29tcHJlc3MgeW91ciBpbnRlZ3JhdGlvblxuICogICByZXNwb25zZSwgZG8gdGhpcyBpbiB5b3VyIGludGVncmF0aW9uXCIuXG4gKiAtIENsb3VkRnJvbnQgcmVxdWlyZXMgdGhlIG9yaWdpbiB0byBzZW5kIGBDb250ZW50LUxlbmd0aGAsIHdoaWNoIGEgc3RyZWFtZWRcbiAqICAgcmVzcG9uc2UgYnkgZGVmaW5pdGlvbiBkb2VzIG5vdC4gSXQgc3RpbGwgY29tcHJlc3NlcyBub24tc3RyZWFtZWQgcmVzcG9uc2VzXG4gKiAgIGFuZCBTMyBhc3NldHMsIHNvIHRoZSBnYXAgaXMgZXhhY3RseSBzdHJlYW1lZCBIVE1MIGFuZCBSU0MgcGF5bG9hZHMg4oCUIHRoZVxuICogICBsYXJnZXN0IHRleHQgcmVzcG9uc2VzIHdlIHNlcnZlLlxuICpcbiAqIFVudGlsIHRoZSBjb250YWluZXIgcGF0aCB3YXMgZHJvcHBlZCwgTGFtYmRhIFdlYiBBZGFwdGVyIGRpZCB0aGlzIGZvciB1cywgd2hpY2hcbiAqIGlzIHdoeSBub3RoaW5nIGluIHRoZSBvbGQgY29kZSBtZW50aW9ucyBpdC4gKipEb24ndCBcImZpeFwiIHRoZSBBUEkgR2F0ZXdheSBvclxuICogQ2xvdWRGcm9udCBzZXR0aW5ncyBleHBlY3RpbmcgdGhlbSB0byB0YWtlIG92ZXIuKipcbiAqXG4gKiBnemlwIHJhdGhlciB0aGFuIGJyb3RsaTogYnJvdGxpJ3Mgc3RyZWFtaW5nIHRocm91Z2hwdXQgYXQgZGVmYXVsdCBxdWFsaXR5IGlzXG4gKiBwb29yLCBhbmQgQ2xvdWRGcm9udCBwcmVmZXJzIGBicmAgb25seSB3aGVuIHRoZSBvcmlnaW4gZGlkbid0IGFscmVhZHkgZW5jb2RlIOKAlFxuICogd2hpY2ggc3RvcHMgYXBwbHlpbmcgdGhlIG1vbWVudCB3ZSBzZXQgYGNvbnRlbnQtZW5jb2RpbmdgIG91cnNlbHZlcy5cbiAqL1xuaW1wb3J0IHsgVHJhbnNmb3JtLCBXcml0YWJsZSB9IGZyb20gXCJub2RlOnN0cmVhbVwiO1xuaW1wb3J0IHsgcGlwZWxpbmUgfSBmcm9tIFwibm9kZTpzdHJlYW0vcHJvbWlzZXNcIjtcbmltcG9ydCB7IGNvbnN0YW50cywgY3JlYXRlR3ppcCB9IGZyb20gXCJub2RlOnpsaWJcIjtcbmltcG9ydCB0eXBlIHsgU2hpbUluY29taW5nTWVzc2FnZSB9IGZyb20gXCIuL3JlcXVlc3RcIjtcbmltcG9ydCB7IFJlc3BvbnNlSGVhZCwgU2hpbVNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIi4vcmVzcG9uc2VcIjtcblxuZXhwb3J0IGludGVyZmFjZSBSZXNwb25zZVNpbmsge1xuICAvKipcbiAgICogU2V0IGJ5IHRoZSBMYW1iZGEgc2luaywgZm9yIGJvdGggaW50ZWdyYXRpb25zOiBhIHN0cmVhbWVkIExhbWJkYSByZXNwb25zZVxuICAgKiB3aXRoIHplcm8gcGF5bG9hZCBieXRlcyBhZnRlciB0aGUgbWV0YWRhdGEgZGVsaW1pdGVyIGlzIG5vdCByZWNvZ25pemVkIGFzIGFcbiAgICogbWV0YWRhdGEgcmVzcG9uc2UgYXQgYWxsLCBzbyBhIHNpbmdsZSBzcGFjZSBpcyB3cml0dGVuIGluc3RlYWQgb2Ygbm90aGluZy5cbiAgICpcbiAgICogQVBJIEdhdGV3YXkgYW5zd2VycyA1MDIuIEEgRnVuY3Rpb24gVVJMIGlzIHdvcnNlIGJlY2F1c2UgaXQgbG9va3MgbGlrZSBpdFxuICAgKiB3b3JrZWQ6IHRoZSBwcmVsdWRlIGlzIGRpc2NhcmRlZCBhbmQgdGhlIHJlc3BvbnNlIGFycml2ZXMgYXMgYSBiYXJlXG4gICAqIGAyMDAgYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtYCB3aXRoIGFuIGVtcHR5IGJvZHksIG5vbmUgb2YgdGhlIGFwcCdzIGhlYWRlcnMsXG4gICAqIGFuZCBhbiBIVFRQLzIgc3RyZWFtIHRoYXQgZG9lcyBub3QgY2xvc2UgY2xlYW5seSDigJQgd2hhdGV2ZXIgdGhlIHJlYWwgc3RhdHVzXG4gICAqIHdhcy4gTWVhc3VyZWQgYWdhaW5zdCBhIGBOZXh0anNHbG9iYWxGdW5jdGlvbnNgIGRlcGxveW1lbnQ6IGBIRUFEYCBvbiBhIDQwNFxuICAgKiBwYWdlIGFuc3dlcmVkIGAyMDBgLCBhbmQgYSBzZXJ2ZXIgYWN0aW9uIHdob3NlIHJlcGx5IGlzIGVtcHR5IChhbiBhY3Rpb24gdGhhdFxuICAgKiBvbmx5IGByZWRpcmVjdCgpYHMsIHdoaWNoIE5leHQuanMgYW5zd2VycyB3aXRoIGB4LWFjdGlvbi1yZWRpcmVjdGAgYW5kIG5vXG4gICAqIGJvZHkpIGxvc3QgdGhlIHJlZGlyZWN0IGhlYWRlciBhbmQgc28gbmV2ZXIgbmF2aWdhdGVkLlxuICAgKlxuICAgKiBUaGUgcHJlLWFkYXB0ZXIgaW1hZ2UgaGFuZGxlciBjYXJyaWVkIHRoZSBzYW1lIHdvcmthcm91bmQgZm9yIDMwNHMuIFJGQyA5MTEwXG4gICAqIGZvcmJpZHMgYSBib2R5IG9uIDIwNC8zMDQsIGFuZCBhIHNwYWNlIHRlY2huaWNhbGx5IHZpb2xhdGVzIHRoYXQsIGJ1dCBsb3NpbmdcbiAgICogdGhlIHN0YXR1cyBlbnRpcmVseSBpcyB0aGUgd29yc2UgZmFpbHVyZSDigJQgYW5kIG9uIHRoZSBDbG91ZEZyb250IHBhdGggYVxuICAgKiBjb25kaXRpb25hbCByZXF1ZXN0IGNhbm5vdCByZWFjaCB0aGUgb3JpZ2luIGFueXdheSwgYmVjYXVzZSBgaWYtbm9uZS1tYXRjaGBcbiAgICogaXMgbm90IGluIHRoZSBkeW5hbWljIGNhY2hlIHBvbGljeSdzIGhlYWRlciBhbGxvd2xpc3QuIFRoZSBjb250YWluZXIgc2lua1xuICAgKiB3cml0ZXMgdG8gYSByZWFsIGBTZXJ2ZXJSZXNwb25zZWAgYW5kIGRvZXMgbm90IHNldCB0aGlzLlxuICAgKi9cbiAgcmVhZG9ubHkgcGFkRW1wdHlCb2R5PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIENhbGxlZCBleGFjdGx5IG9uY2UsIGJlZm9yZSBhbnkgYm9keSBieXRlLCB3aXRoIHRoZSBmaW5hbCBoZWFkLiBSZXR1cm5zIHRoZVxuICAgKiBzdHJlYW0gdGhlIGJvZHkgaXMgd3JpdHRlbiB0bzsge0BsaW5rIHBpcGVUb1Npbmt9IGVuZHMgaXQuXG4gICAqL1xuICBiZWdpbihoZWFkOiBSZXNwb25zZUhlYWQpOiBXcml0YWJsZTtcbn1cblxuLyoqXG4gKiBDb250ZW50IHR5cGVzIHdvcnRoIGNvbXByZXNzaW5nLiBFdmVyeXRoaW5nIE5leHQgc3RyZWFtcyBhcyBIVE1MIG9yIGFuIFJTQ1xuICogcGF5bG9hZCBpcyBgdGV4dC8qYDsgaW1hZ2VzIGFuZCBmb250cyBhcmUgYWxyZWFkeSBjb21wcmVzc2VkLCBhbmQgZ3ppcHBpbmcgYW5cbiAqIG9wdGltaXplZCBBVklGIGp1c3QgYnVybnMgQ1BVLlxuICovXG5jb25zdCBDT01QUkVTU0lCTEUgPVxuICAvXig/OnRleHRcXC98YXBwbGljYXRpb25cXC8oPzpqc29ufGphdmFzY3JpcHR8eG1sfG1hbmlmZXN0fHJzc1xcK3htbHxhdG9tXFwreG1sKXxpbWFnZVxcL3N2Z1xcK3htbCkvO1xuXG4vKipcbiAqIFN0YXR1c2VzIHdob3NlIGJvZHkgbXVzdCBub3QgYmUgY29tcHJlc3NlZDogMjA0IGFuZCAzMDQgaGF2ZSBub25lLCBhbmQgYSAyMDYnc1xuICogYm9keSBpcyBhIGJ5dGUgcmFuZ2Ugb2YgdGhlICp1bmNvbXByZXNzZWQqIHJlcHJlc2VudGF0aW9uLlxuICpcbiAqIDIwNiBpcyByZWFjaGFibGUg4oCUIGBzZXJ2ZVN0YXRpY0ZpbGVgIGlzIGBzZW5kYCB1bmRlcm5lYXRoLCB3aGljaCBhZHZlcnRpc2VzXG4gKiBgQWNjZXB0LVJhbmdlczogYnl0ZXNgIGFuZCBob25vcnMgYFJhbmdlYCBvbiB0aGUgc3RhdGljIEhUTUwgdGhlIHJ1bnRpbWUgc2VydmVzXG4gKiBpdHNlbGYuIEd6aXBwaW5nIG9uZSBwcm9kdWNlZCBhIHJlc3BvbnNlIHdob3NlIGBDb250ZW50LVJhbmdlYCBzdGlsbCBkZXNjcmliZWRcbiAqIHRoZSB1bmNvbXByZXNzZWQgc2xpY2UgKGB3aXRoR3ppcEhlYWRlcnNgIGRyb3BzIGBjb250ZW50LWxlbmd0aGAgYnV0IGNhbm5vdFxuICogcmVzdGF0ZSBhIHJhbmdlKSwgc28gdGhlIGNsaWVudCBnb3QgYnl0ZXMgdGhhdCBkaWQgbm90IG1hdGNoIHdoYXQgaXQgYXNrZWQgZm9yLlxuICovXG5jb25zdCBVTkNPTVBSRVNTQUJMRV9TVEFUVVMgPSBuZXcgU2V0KFsyMDQsIDIwNiwgMzA0XSk7XG5cbi8qKiBgY29tcHJlc3Npb25gJ3Mgb3duIHRlc3QgZm9yIHRoZSBkaXJlY3RpdmUuICovXG5jb25zdCBOT19UUkFOU0ZPUk0gPSAvKD86XnwsKVxccyo/bm8tdHJhbnNmb3JtXFxzKj8oPzosfCQpL2k7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGlwZU9wdGlvbnMge1xuICAvKiogYG5leHQuY29uZmlnYCBgY29tcHJlc3NgLiAqL1xuICByZWFkb25seSBjb21wcmVzczogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBQaXBlIGByZXNgIGludG8gYHNpbmtgLCBnemlwcGluZyB3aGVuIHRoYXQgaXMgYm90aCBhbGxvd2VkIGFuZCB1c2VmdWwuXG4gKlxuICogUmVzb2x2ZXMgd2hlbiB0aGUgc2luaydzIHN0cmVhbSBoYXMgZmluaXNoZWQsIHdoaWNoIGZvciBMYW1iZGEgaXMgdGhlIHBvaW50IHRoZVxuICogY2xpZW50IGhhcyB0aGUgd2hvbGUgcmVzcG9uc2UuIE11c3QgYmUgY2FsbGVkICpiZWZvcmUqIGFueXRoaW5nIHdyaXRlcyB0b1xuICogYHJlc2AsIGJlY2F1c2UgaXQgc3Vic2NyaWJlcyB0byB0aGUgb25lLXNob3QgYFwiaGVhZFwiYCBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBpcGVUb1NpbmsoXG4gIHJlcTogU2hpbUluY29taW5nTWVzc2FnZSxcbiAgcmVzOiBTaGltU2VydmVyUmVzcG9uc2UsXG4gIHNpbms6IFJlc3BvbnNlU2luayxcbiAgb3B0aW9uczogUGlwZU9wdGlvbnMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgcGlwaW5nID0gZmFsc2U7XG4gICAgcmVzLm9uY2UoXCJlcnJvclwiLCByZWplY3QpO1xuICAgIC8vIERlc3Ryb3llZCBiZWZvcmUgdGhlIGhlYWQgd2VudCBvdXQsIGFuZCB3aXRob3V0IGFuIGVycm9yOiBhIGNsaWVudCB0aGF0XG4gICAgLy8gZGlzY29ubmVjdGVkIGJlZm9yZSB0aGUgZmlyc3QgYnl0ZSwgd2hpY2ggYGhhbmRsZSgpYCBhbnN3ZXJzIHdpdGhcbiAgICAvLyBgcmVzLmRlc3Ryb3koKWAuIGBUcmFuc2Zvcm0uZGVzdHJveSgpYCB3aXRoIG5vIGFyZ3VtZW50IGVtaXRzIG9ubHlcbiAgICAvLyBgXCJjbG9zZVwiYCwgYW5kIHRoZSBwaXBlbGluZSBiZWxvdyBuZXZlciBzdGFydGVkLCBzbyBub3RoaW5nIGVsc2UgY2FuIGV2ZXJcbiAgICAvLyBzZXR0bGUgdGhpcyBwcm9taXNlIOKAlCBsZWF2aW5nIGBoYW5kbGUoKWAgYXdhaXRpbmcgaXQgZm9yZXZlciwgaXRzXG4gICAgLy8gYHdhaXRVbnRpbGAgd29yayAoSVNSIHJldmFsaWRhdGlvbiwgY2FjaGUgd3JpdGVzKSBuZXZlciBmbHVzaGVkIGFuZCB0aGVcbiAgICAvLyBpbi1mbGlnaHQgcmVuZGVyJ3MgY2xvc3VyZSByZXRhaW5lZCBmb3IgdGhlIGxpZmUgb2YgdGhlIHByb2Nlc3MuXG4gICAgcmVzLm9uY2UoXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgICBpZiAoIXBpcGluZykge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmVzLm9uY2UoXCJoZWFkXCIsIChoZWFkOiBSZXNwb25zZUhlYWQpID0+IHtcbiAgICAgIHBpcGluZyA9IHRydWU7XG4gICAgICBjb25zdCBzdGFnZXM6IEFycmF5PFRyYW5zZm9ybSB8IFdyaXRhYmxlPiA9IFtdO1xuXG4gICAgICBjb25zdCBnemlwID0gc2hvdWxkR3ppcChyZXEsIHJlcywgaGVhZCwgb3B0aW9ucyk7XG4gICAgICBpZiAoZ3ppcCkge1xuICAgICAgICBjb25zdCBjb21wcmVzc29yID0gY3JlYXRlR3ppcCgpO1xuICAgICAgICAvLyBOZXh0LmpzIGNhbGxzIGByZXMuZmx1c2goKWAgYWZ0ZXIgZWFjaCBjaHVuayBpdCB3cml0ZXNcbiAgICAgICAgLy8gKGBuZXh0L2Rpc3Qvc2VydmVyL3BpcGUtcmVhZGFibGUuanNgKTsgd2l0aG91dCBmb3J3YXJkaW5nIGl0LCBzdHJlYW1lZFxuICAgICAgICAvLyBIVE1MIHNpdHMgaW4gemxpYidzIGJ1ZmZlciBhbmQgdGhlIHJlc3BvbnNlIGFycml2ZXMgYWxsIGF0IG9uY2UuXG4gICAgICAgIHJlcy5mbHVzaCA9ICgpID0+IGNvbXByZXNzb3IuZmx1c2goY29uc3RhbnRzLlpfU1lOQ19GTFVTSCk7XG4gICAgICAgIHN0YWdlcy5wdXNoKGNvbXByZXNzb3IpO1xuICAgICAgfVxuICAgICAgaWYgKHNpbmsucGFkRW1wdHlCb2R5KSB7XG4gICAgICAgIHN0YWdlcy5wdXNoKHBhZEVtcHR5Qm9keSgpKTtcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIHN0YWdlcy5wdXNoKHNpbmsuYmVnaW4oZ3ppcCA/IHdpdGhHemlwSGVhZGVycyhoZWFkKSA6IGhlYWQpKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIFRoaXMgcnVucyBpbnNpZGUgd2hpY2hldmVyIGByZXNgIGNhbGwgZmx1c2hlZCB0aGUgaGVhZCDigJQgdXN1YWxseSBhXG4gICAgICAgIC8vIGB3cml0ZSgpYCBmcm9tIGRlZXAgaW5zaWRlIE5leHQuanMg4oCUIHNvIGFuIGVzY2FwaW5nIHRocm93IGxhbmRzIHRoZXJlLFxuICAgICAgICAvLyB0aGUgcGlwZWxpbmUgYmVsb3cgbmV2ZXIgc3RhcnRzLCBhbmQgbm90aGluZyB3b3VsZCBzZXR0bGUgdGhpc1xuICAgICAgICAvLyBwcm9taXNlOiBgaGFuZGxlKClgIHdvdWxkIGhhbmcuIEEgc2luaydzIGB3cml0ZUhlYWRgIHJlamVjdGluZyBhXG4gICAgICAgIC8vIGhlYWRlciB2YWx1ZSBpcyBob3cgaXQgaGFwcGVucy4gRGVzdHJveWluZyBgcmVzYCBpcyB3aGF0IHN0b3BzIHRoZVxuICAgICAgICAvLyB3cml0ZXI7IHRoZSBgXCJlcnJvclwiYCB0aGF0IGVtaXRzIGlzIGEgbm8tb3AgYWZ0ZXIgdGhlIGByZWplY3RgLlxuICAgICAgICBmb3IgKGNvbnN0IHN0YWdlIG9mIHN0YWdlcykge1xuICAgICAgICAgIHN0YWdlLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICByZXMuZGVzdHJveShlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHBpcGVsaW5lKHJlcywgLi4uKHN0YWdlcyBhcyBbV3JpdGFibGVdKSkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc2hvdWxkR3ppcChcbiAgcmVxOiBTaGltSW5jb21pbmdNZXNzYWdlLFxuICByZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSxcbiAgaGVhZDogUmVzcG9uc2VIZWFkLFxuICBvcHRpb25zOiBQaXBlT3B0aW9ucyxcbik6IGJvb2xlYW4ge1xuICBpZiAoIW9wdGlvbnMuY29tcHJlc3MpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHJlcS5tZXRob2QgPT09IFwiSEVBRFwiIHx8IFVOQ09NUFJFU1NBQkxFX1NUQVRVUy5oYXMoaGVhZC5zdGF0dXNDb2RlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBOZXh0LmpzIGVuY29kZXMgc29tZSByZXNwb25zZXMgaXRzZWxmOyBkb3VibGUtZW5jb2RpbmcgaXMgbm90IGEgdGhpbmcuXG4gIGlmIChyZXMuaGFzSGVhZGVyKFwiY29udGVudC1lbmNvZGluZ1wiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoIUNPTVBSRVNTSUJMRS50ZXN0KGhlYWQuaGVhZGVyc1tcImNvbnRlbnQtdHlwZVwiXSA/PyBcIlwiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBUaGUgcmVzcG9uc2UncyBvcHQtb3V0LCB3aGljaCBgbmV4dCBzdGFydGAncyBgY29tcHJlc3Npb25gIGhvbm9ycyB0b286IGFuXG4gIC8vIFNTRSBzdHJlYW0gc2V0cyBpdCBzbyB0aGF0IG5vdGhpbmcgYnVmZmVycyBpdHMgZXZlbnRzLlxuICBpZiAoTk9fVFJBTlNGT1JNLnRlc3QoaGVhZC5oZWFkZXJzW1wiY2FjaGUtY29udHJvbFwiXSA/PyBcIlwiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gYWNjZXB0c0d6aXAocmVxLmhlYWRlcnNbXCJhY2NlcHQtZW5jb2RpbmdcIl0pO1xufVxuXG4vKipcbiAqIEEgYHE9MGAgb24gZ3ppcCBpcyBhIHJlZnVzYWwsIGFuZCBib3RoIGAqYCBmb3JtcyBoYXZlIHRvIGJlIGhvbm9yZWQsIHNvIHRoaXNcbiAqIHBhcnNlcyByYXRoZXIgdGhhbiBzdWJzdHJpbmctbWF0Y2hpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhY2NlcHRzR3ppcChoZWFkZXI6IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIGNvbnN0IHZhbHVlID0gQXJyYXkuaXNBcnJheShoZWFkZXIpID8gaGVhZGVyLmpvaW4oXCIsXCIpIDogaGVhZGVyO1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGxldCB3aWxkY2FyZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBwYXJ0IG9mIHZhbHVlLnNwbGl0KFwiLFwiKSkge1xuICAgIGNvbnN0IFtyYXdOYW1lLCAuLi5wYXJhbXNdID0gcGFydC5zcGxpdChcIjtcIik7XG4gICAgY29uc3QgbmFtZSA9IHJhd05hbWUudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKG5hbWUgIT09IFwiZ3ppcFwiICYmIG5hbWUgIT09IFwiKlwiKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgcSA9IHBhcmFtc1xuICAgICAgLm1hcCgocCkgPT4gcC50cmltKCkudG9Mb3dlckNhc2UoKSlcbiAgICAgIC5maW5kKChwKSA9PiBwLnN0YXJ0c1dpdGgoXCJxPVwiKSk7XG4gICAgY29uc3QgYWNjZXB0ZWQgPSBxID09PSB1bmRlZmluZWQgfHwgTnVtYmVyKHEuc2xpY2UoMikpID4gMDtcbiAgICBpZiAobmFtZSA9PT0gXCJnemlwXCIpIHtcbiAgICAgIHJldHVybiBhY2NlcHRlZDtcbiAgICB9XG4gICAgd2lsZGNhcmQgPSBhY2NlcHRlZDtcbiAgfVxuICByZXR1cm4gd2lsZGNhcmQgPz8gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHdpdGhHemlwSGVhZGVycyhoZWFkOiBSZXNwb25zZUhlYWQpOiBSZXNwb25zZUhlYWQge1xuICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgIC4uLmhlYWQuaGVhZGVycyxcbiAgICBcImNvbnRlbnQtZW5jb2RpbmdcIjogXCJnemlwXCIsXG4gIH07XG4gIC8vIFRoZSBsZW5ndGggd2Ugd2VyZSB0b2xkIGlzIHRoZSB1bmNvbXByZXNzZWQgb25lLCBhbmQgd2UgZG8gbm90IGtub3cgdGhlXG4gIC8vIGNvbXByZXNzZWQgb25lIHVudGlsIHRoZSBzdHJlYW0gZW5kcy5cbiAgZGVsZXRlIGhlYWRlcnNbXCJjb250ZW50LWxlbmd0aFwiXTtcbiAgY29uc3QgdmFyeSA9IGhlYWRlcnMudmFyeTtcbiAgaWYgKCF2YXJ5KSB7XG4gICAgaGVhZGVycy52YXJ5ID0gXCJBY2NlcHQtRW5jb2RpbmdcIjtcbiAgfSBlbHNlIGlmICghL1xcYmFjY2VwdC1lbmNvZGluZ1xcYi9pLnRlc3QodmFyeSkpIHtcbiAgICBoZWFkZXJzLnZhcnkgPSBgJHt2YXJ5fSwgQWNjZXB0LUVuY29kaW5nYDtcbiAgfVxuICByZXR1cm4geyAuLi5oZWFkLCBoZWFkZXJzIH07XG59XG5cbi8qKiBTZWUge0BsaW5rIFJlc3BvbnNlU2luay5wYWRFbXB0eUJvZHl9LiAqL1xuZnVuY3Rpb24gcGFkRW1wdHlCb2R5KCk6IFRyYW5zZm9ybSB7XG4gIGxldCB3cm90ZVNvbWV0aGluZyA9IGZhbHNlO1xuICByZXR1cm4gbmV3IFRyYW5zZm9ybSh7XG4gICAgdHJhbnNmb3JtKGNodW5rLCBfZW5jb2RpbmcsIGNhbGxiYWNrKSB7XG4gICAgICB3cm90ZVNvbWV0aGluZyA9IHRydWU7XG4gICAgICBjYWxsYmFjayhudWxsLCBjaHVuayk7XG4gICAgfSxcbiAgICBmbHVzaChjYWxsYmFjaykge1xuICAgICAgY2FsbGJhY2sobnVsbCwgd3JvdGVTb21ldGhpbmcgPyB1bmRlZmluZWQgOiBcIiBcIik7XG4gICAgfSxcbiAgfSk7XG59XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_stream_1 = require("node:stream");
4
+ const node_zlib_1 = require("node:zlib");
5
+ const request_1 = require("./request");
6
+ const response_1 = require("./response");
7
+ const sink_1 = require("./sink");
8
+ class CollectingSink {
9
+ padEmptyBody;
10
+ head;
11
+ chunks = [];
12
+ constructor(padEmptyBody = false) {
13
+ this.padEmptyBody = padEmptyBody;
14
+ }
15
+ begin(head) {
16
+ this.head = head;
17
+ const chunks = this.chunks;
18
+ return new node_stream_1.Writable({
19
+ write(chunk, _encoding, callback) {
20
+ chunks.push(Buffer.from(chunk));
21
+ callback();
22
+ },
23
+ });
24
+ }
25
+ get body() {
26
+ return Buffer.concat(this.chunks);
27
+ }
28
+ }
29
+ function requestWith(headers, method = "GET") {
30
+ return new request_1.ShimIncomingMessage({ method, url: "/", headers });
31
+ }
32
+ /** Runs one response through the sink and resolves once the sink is finished. */
33
+ async function run(write, options = {}) {
34
+ const req = options.req ?? requestWith({ "accept-encoding": "gzip" });
35
+ const res = new response_1.ShimServerResponse();
36
+ const sink = new CollectingSink(options.padEmptyBody);
37
+ const done = (0, sink_1.pipeToSink)(req, res, sink, {
38
+ compress: options.compress ?? true,
39
+ });
40
+ write(res);
41
+ await done;
42
+ return sink;
43
+ }
44
+ describe("pipeToSink compression", () => {
45
+ it("gzips compressible content when the client accepts it", async () => {
46
+ const sink = await run((res) => {
47
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
48
+ res.setHeader("Content-Length", "13");
49
+ res.end("<p>hello</p>");
50
+ });
51
+ expect(sink.head?.headers["content-encoding"]).toBe("gzip");
52
+ // The length we were told is the uncompressed one and the compressed one is
53
+ // not known until the stream ends.
54
+ expect(sink.head?.headers["content-length"]).toBeUndefined();
55
+ expect(sink.head?.headers.vary).toBe("Accept-Encoding");
56
+ expect((0, node_zlib_1.gunzipSync)(sink.body).toString("utf-8")).toBe("<p>hello</p>");
57
+ });
58
+ it("appends to an existing vary rather than replacing it", async () => {
59
+ const sink = await run((res) => {
60
+ res.setHeader("Content-Type", "text/html");
61
+ res.setHeader("Vary", "Cookie");
62
+ res.end("x");
63
+ });
64
+ expect(sink.head?.headers.vary).toBe("Cookie, Accept-Encoding");
65
+ });
66
+ it("forwards res.flush() to the compressor so streamed HTML is not buffered", async () => {
67
+ const seen = [];
68
+ const sink = await run((res) => {
69
+ res.setHeader("Content-Type", "text/html");
70
+ res.write("<html>");
71
+ // Next.js does exactly this after every chunk (`pipe-readable.js`).
72
+ res.flush?.();
73
+ seen.push(1);
74
+ res.end("</html>");
75
+ });
76
+ expect(seen).toEqual([1]);
77
+ expect((0, node_zlib_1.gunzipSync)(sink.body).toString("utf-8")).toBe("<html></html>");
78
+ });
79
+ it.each([
80
+ ["an incompressible content type", { "content-type": "image/avif" }],
81
+ ["an already-encoded body", { "content-encoding": "br" }],
82
+ [
83
+ "a response that opts out with no-transform",
84
+ {
85
+ "content-type": "text/event-stream",
86
+ "cache-control": "no-cache, no-transform",
87
+ },
88
+ ],
89
+ ])("does not gzip %s", async (_name, headers) => {
90
+ const sink = await run((res) => {
91
+ for (const [name, value] of Object.entries(headers)) {
92
+ res.setHeader(name, value);
93
+ }
94
+ res.end("body");
95
+ });
96
+ expect(sink.head?.headers["content-encoding"]).not.toBe("gzip");
97
+ expect(sink.body.toString("utf-8")).toBe("body");
98
+ });
99
+ it("does not gzip a 206, whose body is a range of the stored bytes", async () => {
100
+ // The one uncompressable status that carries a body. `content-range` counts
101
+ // bytes of the representation the client asked for, so gzipping the slice
102
+ // makes the range meaningless - and a client stitching ranges together
103
+ // (video, a resumed download) cannot use it.
104
+ const sink = await run((res) => {
105
+ res.statusCode = 206;
106
+ res.setHeader("Content-Type", "text/plain");
107
+ res.setHeader("Content-Range", "bytes 0-3/1000");
108
+ res.end("body");
109
+ });
110
+ expect(sink.head?.headers["content-encoding"]).toBeUndefined();
111
+ expect(sink.body.toString("utf-8")).toBe("body");
112
+ });
113
+ it("does not gzip when the client did not offer it", async () => {
114
+ const sink = await run((res) => {
115
+ res.setHeader("Content-Type", "text/html");
116
+ res.end("body");
117
+ }, { req: requestWith({}) });
118
+ expect(sink.head?.headers["content-encoding"]).toBeUndefined();
119
+ expect(sink.body.toString("utf-8")).toBe("body");
120
+ });
121
+ it("does not gzip when next.config sets compress: false", async () => {
122
+ const sink = await run((res) => {
123
+ res.setHeader("Content-Type", "text/html");
124
+ res.end("body");
125
+ }, { compress: false });
126
+ expect(sink.head?.headers["content-encoding"]).toBeUndefined();
127
+ });
128
+ it.each([
129
+ ["a HEAD request", { method: "HEAD", status: 200 }],
130
+ ["a 204", { method: "GET", status: 204 }],
131
+ ["a 304", { method: "GET", status: 304 }],
132
+ ])("does not gzip %s", async (_name, { method, status }) => {
133
+ const sink = await run((res) => {
134
+ res.statusCode = status;
135
+ res.setHeader("Content-Type", "text/html");
136
+ res.end();
137
+ }, { req: requestWith({ "accept-encoding": "gzip" }, method) });
138
+ expect(sink.head?.headers["content-encoding"]).toBeUndefined();
139
+ });
140
+ });
141
+ describe("pipeToSink empty-body padding", () => {
142
+ it("writes a single space when the sink asks for it", async () => {
143
+ const sink = await run((res) => {
144
+ res.statusCode = 304;
145
+ res.end();
146
+ }, { padEmptyBody: true });
147
+ // Zero payload bytes after the prelude makes API Gateway answer 502, and
148
+ // makes a Function URL drop the prelude and answer a bare
149
+ // `200 application/octet-stream`.
150
+ expect(sink.body.toString("utf-8")).toBe(" ");
151
+ });
152
+ it("pads a HEAD response, whose body is empty by definition", async () => {
153
+ const sink = await run((res) => {
154
+ res.setHeader("content-type", "text/html; charset=utf-8");
155
+ res.setHeader("content-length", "5798");
156
+ res.end();
157
+ }, {
158
+ padEmptyBody: true,
159
+ req: requestWith({ "accept-encoding": "gzip" }, "HEAD"),
160
+ });
161
+ expect(sink.body.toString("utf-8")).toBe(" ");
162
+ // The head still describes what a GET would return; the padding byte is not
163
+ // a body and the integration overwrites `content-length` with 0.
164
+ expect(sink.head?.headers["content-length"]).toBe("5798");
165
+ });
166
+ it("leaves a non-empty body alone", async () => {
167
+ const sink = await run((res) => res.end("real"), {
168
+ padEmptyBody: true,
169
+ compress: false,
170
+ });
171
+ expect(sink.body.toString("utf-8")).toBe("real");
172
+ });
173
+ it("sends nothing for an empty body when the sink does not ask", async () => {
174
+ const sink = await run((res) => {
175
+ res.statusCode = 304;
176
+ res.end();
177
+ });
178
+ expect(sink.body).toHaveLength(0);
179
+ });
180
+ });
181
+ describe("pipeToSink lifecycle", () => {
182
+ /**
183
+ * `handle()` awaits this promise before it flushes `waitUntil` work — ISR
184
+ * revalidation, cache writes — and before the request's closures can be
185
+ * collected. A client that disconnects before the first byte destroys the
186
+ * response without an error, which emits only `"close"`: the pipeline never
187
+ * started, so nothing else can settle the promise and the await never returned.
188
+ */
189
+ it("settles when the response is destroyed before the head goes out", async () => {
190
+ const req = requestWith({});
191
+ const res = new response_1.ShimServerResponse();
192
+ const done = (0, sink_1.pipeToSink)(req, res, new CollectingSink(), {
193
+ compress: true,
194
+ });
195
+ res.destroy();
196
+ await expect(done).resolves.toBeUndefined();
197
+ });
198
+ // The normal path has to keep settling on the pipeline, not on `"close"`: the
199
+ // body must be fully flushed into the sink by the time this resolves.
200
+ it("still settles on the pipeline once the head has gone out", async () => {
201
+ const sink = await run((res) => {
202
+ res.setHeader("content-type", "text/plain");
203
+ res.end("body");
204
+ }, { compress: false });
205
+ expect(sink.body.toString()).toBe("body");
206
+ });
207
+ it("rejects when the response errors", async () => {
208
+ const req = requestWith({});
209
+ const res = new response_1.ShimServerResponse();
210
+ const done = (0, sink_1.pipeToSink)(req, res, new CollectingSink(), {
211
+ compress: true,
212
+ });
213
+ res.destroy(new Error("boom"));
214
+ await expect(done).rejects.toThrow("boom");
215
+ });
216
+ // A sink that cannot take the head — `writeHead` rejecting a header value is
217
+ // the real case — throws from inside the `"head"` listener, where nothing
218
+ // else would catch it and the pipeline never starts.
219
+ it.each([
220
+ ["writes a body", (res) => res.end("body")],
221
+ ["ends empty", (res) => res.end()],
222
+ ["flushes its head first", (res) => res.writeHead(200)],
223
+ ])("rejects and destroys the response when begin() throws and the response %s", async (_name, write) => {
224
+ const req = requestWith({});
225
+ const res = new response_1.ShimServerResponse();
226
+ const done = (0, sink_1.pipeToSink)(req, res, {
227
+ begin() {
228
+ throw new Error("bad head");
229
+ },
230
+ }, { compress: false });
231
+ write(res);
232
+ await expect(done).rejects.toThrow("bad head");
233
+ expect(res.destroyed).toBe(true);
234
+ });
235
+ });
236
+ describe("acceptsGzip", () => {
237
+ it.each([
238
+ ["gzip", true],
239
+ ["gzip, deflate, br", true],
240
+ ["GZIP;q=0.5", true],
241
+ ["gzip;q=0", false],
242
+ ["*", true],
243
+ ["*;q=0", false],
244
+ // An explicit gzip preference wins over the wildcard, in either order.
245
+ ["*;q=0, gzip", true],
246
+ ["gzip;q=0, *", false],
247
+ ["br, deflate", false],
248
+ ["", false],
249
+ [undefined, false],
250
+ ])("%s → %s", (header, expected) => {
251
+ expect((0, sink_1.acceptsGzip)(header)).toBe(expected);
252
+ });
253
+ it("joins a repeated header before parsing", () => {
254
+ expect((0, sink_1.acceptsGzip)(["br", "gzip"])).toBe(true);
255
+ });
256
+ });
257
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2luay50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3J1bnRpbWUvaHR0cC9zaW5rLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2Q0FBdUM7QUFDdkMseUNBQXVDO0FBQ3ZDLHVDQUFnRDtBQUNoRCx5Q0FBOEQ7QUFDOUQsaUNBQStEO0FBRS9ELE1BQU0sY0FBYztJQUlpQjtJQUg1QixJQUFJLENBQWdCO0lBQ1gsTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUV0QyxZQUFtQyxlQUFlLEtBQUs7UUFBcEIsaUJBQVksR0FBWixZQUFZLENBQVE7SUFBRyxDQUFDO0lBRXBELEtBQUssQ0FBQyxJQUFrQjtRQUM3QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQzNCLE9BQU8sSUFBSSxzQkFBUSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLFFBQVE7Z0JBQzlCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNoQyxRQUFRLEVBQUUsQ0FBQztZQUNiLENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBVyxJQUFJO1FBQ2IsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUFFRCxTQUFTLFdBQVcsQ0FDbEIsT0FBK0IsRUFDL0IsTUFBTSxHQUFHLEtBQUs7SUFFZCxPQUFPLElBQUksNkJBQW1CLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFRRCxpRkFBaUY7QUFDakYsS0FBSyxVQUFVLEdBQUcsQ0FDaEIsS0FBd0MsRUFDeEMsVUFBb0IsRUFBRTtJQUV0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QUM7SUFDN0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsd0NBQXdDLEVBQUUsR0FBRyxFQUFFO1FBQ2hELE1BQU0sQ0FBQyxJQUFBLGtCQUFXLEVBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV3JpdGFibGUgfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB7IGd1bnppcFN5bmMgfSBmcm9tIFwibm9kZTp6bGliXCI7XG5pbXBvcnQgeyBTaGltSW5jb21pbmdNZXNzYWdlIH0gZnJvbSBcIi4vcmVxdWVzdFwiO1xuaW1wb3J0IHsgUmVzcG9uc2VIZWFkLCBTaGltU2VydmVyUmVzcG9uc2UgfSBmcm9tIFwiLi9yZXNwb25zZVwiO1xuaW1wb3J0IHsgYWNjZXB0c0d6aXAsIHBpcGVUb1NpbmssIFJlc3BvbnNlU2luayB9IGZyb20gXCIuL3NpbmtcIjtcblxuY2xhc3MgQ29sbGVjdGluZ1NpbmsgaW1wbGVtZW50cyBSZXNwb25zZVNpbmsge1xuICBwdWJsaWMgaGVhZD86IFJlc3BvbnNlSGVhZDtcbiAgcHVibGljIHJlYWRvbmx5IGNodW5rczogQnVmZmVyW10gPSBbXTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHBhZEVtcHR5Qm9keSA9IGZhbHNlKSB7fVxuXG4gIHB1YmxpYyBiZWdpbihoZWFkOiBSZXNwb25zZUhlYWQpOiBXcml0YWJsZSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICBjb25zdCBjaHVua3MgPSB0aGlzLmNodW5rcztcbiAgICByZXR1cm4gbmV3IFdyaXRhYmxlKHtcbiAgICAgIHdyaXRlKGNodW5rLCBfZW5jb2RpbmcsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNodW5rcy5wdXNoKEJ1ZmZlci5mcm9tKGNodW5rKSk7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldCBib2R5KCk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQodGhpcy5jaHVua3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RXaXRoKFxuICBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICBtZXRob2QgPSBcIkdFVFwiLFxuKTogU2hpbUluY29taW5nTWVzc2FnZSB7XG4gIHJldHVybiBuZXcgU2hpbUluY29taW5nTWVzc2FnZSh7IG1ldGhvZCwgdXJsOiBcIi9cIiwgaGVhZGVycyB9KTtcbn1cblxuaW50ZXJmYWNlIFBpcGVDYXNlIHtcbiAgcmVhZG9ubHkgcmVxPzogU2hpbUluY29taW5nTWVzc2FnZTtcbiAgcmVhZG9ubHkgY29tcHJlc3M/OiBib29sZWFuO1xuICByZWFkb25seSBwYWRFbXB0eUJvZHk/OiBib29sZWFuO1xufVxuXG4vKiogUnVucyBvbmUgcmVzcG9uc2UgdGhyb3VnaCB0aGUgc2luayBhbmQgcmVzb2x2ZXMgb25jZSB0aGUgc2luayBpcyBmaW5pc2hlZC4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bihcbiAgd3JpdGU6IChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSkgPT4gdm9pZCxcbiAgb3B0aW9uczogUGlwZUNhc2UgPSB7fSxcbik6IFByb21pc2U8Q29sbGVjdGluZ1Npbms+IHtcbiAgY29uc3QgcmVxID0gb3B0aW9ucy5yZXEgPz8gcmVxdWVzdFdpdGgoeyBcImFjY2VwdC1lbmNvZGluZ1wiOiBcImd6aXBcIiB9KTtcbiAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICBjb25zdCBzaW5rID0gbmV3IENvbGxlY3RpbmdTaW5rKG9wdGlvbnMucGFkRW1wdHlCb2R5KTtcbiAgY29uc3QgZG9uZSA9IHBpcGVUb1NpbmsocmVxLCByZXMsIHNpbmssIHtcbiAgICBjb21wcmVzczogb3B0aW9ucy5jb21wcmVzcyA/PyB0cnVlLFxuICB9KTtcbiAgd3JpdGUocmVzKTtcbiAgYXdhaXQgZG9uZTtcbiAgcmV0dXJuIHNpbms7XG59XG5cbmRlc2NyaWJlKFwicGlwZVRvU2luayBjb21wcmVzc2lvblwiLCAoKSA9PiB7XG4gIGl0KFwiZ3ppcHMgY29tcHJlc3NpYmxlIGNvbnRlbnQgd2hlbiB0aGUgY2xpZW50IGFjY2VwdHMgaXRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oKHJlcykgPT4ge1xuICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvaHRtbDsgY2hhcnNldD11dGYtOFwiKTtcbiAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LUxlbmd0aFwiLCBcIjEzXCIpO1xuICAgICAgcmVzLmVuZChcIjxwPmhlbGxvPC9wPlwiKTtcbiAgICB9KTtcbiAgICBleHBlY3Qoc2luay5oZWFkPy5oZWFkZXJzW1wiY29udGVudC1lbmNvZGluZ1wiXSkudG9CZShcImd6aXBcIik7XG4gICAgLy8gVGhlIGxlbmd0aCB3ZSB3ZXJlIHRvbGQgaXMgdGhlIHVuY29tcHJlc3NlZCBvbmUgYW5kIHRoZSBjb21wcmVzc2VkIG9uZSBpc1xuICAgIC8vIG5vdCBrbm93biB1bnRpbCB0aGUgc3RyZWFtIGVuZHMuXG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVycy52YXJ5KS50b0JlKFwiQWNjZXB0LUVuY29kaW5nXCIpO1xuICAgIGV4cGVjdChndW56aXBTeW5jKHNpbmsuYm9keSkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcIjxwPmhlbGxvPC9wPlwiKTtcbiAgfSk7XG5cbiAgaXQoXCJhcHBlbmRzIHRvIGFuIGV4aXN0aW5nIHZhcnkgcmF0aGVyIHRoYW4gcmVwbGFjaW5nIGl0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKChyZXMpID0+IHtcbiAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L2h0bWxcIik7XG4gICAgICByZXMuc2V0SGVhZGVyKFwiVmFyeVwiLCBcIkNvb2tpZVwiKTtcbiAgICAgIHJlcy5lbmQoXCJ4XCIpO1xuICAgIH0pO1xuICAgIGV4cGVjdChzaW5rLmhlYWQ/LmhlYWRlcnMudmFyeSkudG9CZShcIkNvb2tpZSwgQWNjZXB0LUVuY29kaW5nXCIpO1xuICB9KTtcblxuICBpdChcImZvcndhcmRzIHJlcy5mbHVzaCgpIHRvIHRoZSBjb21wcmVzc29yIHNvIHN0cmVhbWVkIEhUTUwgaXMgbm90IGJ1ZmZlcmVkXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzZWVuOiBudW1iZXJbXSA9IFtdO1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oKHJlcykgPT4ge1xuICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvaHRtbFwiKTtcbiAgICAgIHJlcy53cml0ZShcIjxodG1sPlwiKTtcbiAgICAgIC8vIE5leHQuanMgZG9lcyBleGFjdGx5IHRoaXMgYWZ0ZXIgZXZlcnkgY2h1bmsgKGBwaXBlLXJlYWRhYmxlLmpzYCkuXG4gICAgICByZXMuZmx1c2g/LigpO1xuICAgICAgc2Vlbi5wdXNoKDEpO1xuICAgICAgcmVzLmVuZChcIjwvaHRtbD5cIik7XG4gICAgfSk7XG4gICAgZXhwZWN0KHNlZW4pLnRvRXF1YWwoWzFdKTtcbiAgICBleHBlY3QoZ3VuemlwU3luYyhzaW5rLmJvZHkpLnRvU3RyaW5nKFwidXRmLThcIikpLnRvQmUoXCI8aHRtbD48L2h0bWw+XCIpO1xuICB9KTtcblxuICBpdC5lYWNoKFtcbiAgICBbXCJhbiBpbmNvbXByZXNzaWJsZSBjb250ZW50IHR5cGVcIiwgeyBcImNvbnRlbnQtdHlwZVwiOiBcImltYWdlL2F2aWZcIiB9XSxcbiAgICBbXCJhbiBhbHJlYWR5LWVuY29kZWQgYm9keVwiLCB7IFwiY29udGVudC1lbmNvZGluZ1wiOiBcImJyXCIgfV0sXG4gICAgW1xuICAgICAgXCJhIHJlc3BvbnNlIHRoYXQgb3B0cyBvdXQgd2l0aCBuby10cmFuc2Zvcm1cIixcbiAgICAgIHtcbiAgICAgICAgXCJjb250ZW50LXR5cGVcIjogXCJ0ZXh0L2V2ZW50LXN0cmVhbVwiLFxuICAgICAgICBcImNhY2hlLWNvbnRyb2xcIjogXCJuby1jYWNoZSwgbm8tdHJhbnNmb3JtXCIsXG4gICAgICB9LFxuICAgIF0sXG4gIF0pKFwiZG9lcyBub3QgZ3ppcCAlc1wiLCBhc3luYyAoX25hbWUsIGhlYWRlcnMpID0+IHtcbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKChyZXMpID0+IHtcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhoZWFkZXJzKSkge1xuICAgICAgICByZXMuc2V0SGVhZGVyKG5hbWUsIHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJlcy5lbmQoXCJib2R5XCIpO1xuICAgIH0pO1xuICAgIGV4cGVjdChzaW5rLmhlYWQ/LmhlYWRlcnNbXCJjb250ZW50LWVuY29kaW5nXCJdKS5ub3QudG9CZShcImd6aXBcIik7XG4gICAgZXhwZWN0KHNpbmsuYm9keS50b1N0cmluZyhcInV0Zi04XCIpKS50b0JlKFwiYm9keVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJkb2VzIG5vdCBnemlwIGEgMjA2LCB3aG9zZSBib2R5IGlzIGEgcmFuZ2Ugb2YgdGhlIHN0b3JlZCBieXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gVGhlIG9uZSB1bmNvbXByZXNzYWJsZSBzdGF0dXMgdGhhdCBjYXJyaWVzIGEgYm9keS4gYGNvbnRlbnQtcmFuZ2VgIGNvdW50c1xuICAgIC8vIGJ5dGVzIG9mIHRoZSByZXByZXNlbnRhdGlvbiB0aGUgY2xpZW50IGFza2VkIGZvciwgc28gZ3ppcHBpbmcgdGhlIHNsaWNlXG4gICAgLy8gbWFrZXMgdGhlIHJhbmdlIG1lYW5pbmdsZXNzIC0gYW5kIGEgY2xpZW50IHN0aXRjaGluZyByYW5nZXMgdG9nZXRoZXJcbiAgICAvLyAodmlkZW8sIGEgcmVzdW1lZCBkb3dubG9hZCkgY2Fubm90IHVzZSBpdC5cbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKChyZXMpID0+IHtcbiAgICAgIHJlcy5zdGF0dXNDb2RlID0gMjA2O1xuICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvcGxhaW5cIik7XG4gICAgICByZXMuc2V0SGVhZGVyKFwiQ29udGVudC1SYW5nZVwiLCBcImJ5dGVzIDAtMy8xMDAwXCIpO1xuICAgICAgcmVzLmVuZChcImJvZHlcIik7XG4gICAgfSk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtZW5jb2RpbmdcIl0pLnRvQmVVbmRlZmluZWQoKTtcbiAgICBleHBlY3Qoc2luay5ib2R5LnRvU3RyaW5nKFwidXRmLThcIikpLnRvQmUoXCJib2R5XCIpO1xuICB9KTtcblxuICBpdChcImRvZXMgbm90IGd6aXAgd2hlbiB0aGUgY2xpZW50IGRpZCBub3Qgb2ZmZXIgaXRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgIHJlcy5lbmQoXCJib2R5XCIpO1xuICAgICAgfSxcbiAgICAgIHsgcmVxOiByZXF1ZXN0V2l0aCh7fSkgfSxcbiAgICApO1xuICAgIGV4cGVjdChzaW5rLmhlYWQ/LmhlYWRlcnNbXCJjb250ZW50LWVuY29kaW5nXCJdKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KHNpbmsuYm9keS50b1N0cmluZyhcInV0Zi04XCIpKS50b0JlKFwiYm9keVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJkb2VzIG5vdCBnemlwIHdoZW4gbmV4dC5jb25maWcgc2V0cyBjb21wcmVzczogZmFsc2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L2h0bWxcIik7XG4gICAgICAgIHJlcy5lbmQoXCJib2R5XCIpO1xuICAgICAgfSxcbiAgICAgIHsgY29tcHJlc3M6IGZhbHNlIH0sXG4gICAgKTtcbiAgICBleHBlY3Qoc2luay5oZWFkPy5oZWFkZXJzW1wiY29udGVudC1lbmNvZGluZ1wiXSkudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcblxuICBpdC5lYWNoKFtcbiAgICBbXCJhIEhFQUQgcmVxdWVzdFwiLCB7IG1ldGhvZDogXCJIRUFEXCIsIHN0YXR1czogMjAwIH1dLFxuICAgIFtcImEgMjA0XCIsIHsgbWV0aG9kOiBcIkdFVFwiLCBzdGF0dXM6IDIwNCB9XSxcbiAgICBbXCJhIDMwNFwiLCB7IG1ldGhvZDogXCJHRVRcIiwgc3RhdHVzOiAzMDQgfV0sXG4gIF0pKFwiZG9lcyBub3QgZ3ppcCAlc1wiLCBhc3luYyAoX25hbWUsIHsgbWV0aG9kLCBzdGF0dXMgfSkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXNDb2RlID0gc3RhdHVzO1xuICAgICAgICByZXMuc2V0SGVhZGVyKFwiQ29udGVudC1UeXBlXCIsIFwidGV4dC9odG1sXCIpO1xuICAgICAgICByZXMuZW5kKCk7XG4gICAgICB9LFxuICAgICAgeyByZXE6IHJlcXVlc3RXaXRoKHsgXCJhY2NlcHQtZW5jb2RpbmdcIjogXCJnemlwXCIgfSwgbWV0aG9kKSB9LFxuICAgICk7XG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtZW5jb2RpbmdcIl0pLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJwaXBlVG9TaW5rIGVtcHR5LWJvZHkgcGFkZGluZ1wiLCAoKSA9PiB7XG4gIGl0KFwid3JpdGVzIGEgc2luZ2xlIHNwYWNlIHdoZW4gdGhlIHNpbmsgYXNrcyBmb3IgaXRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNpbmsgPSBhd2FpdCBydW4oXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXNDb2RlID0gMzA0O1xuICAgICAgICByZXMuZW5kKCk7XG4gICAgICB9LFxuICAgICAgeyBwYWRFbXB0eUJvZHk6IHRydWUgfSxcbiAgICApO1xuICAgIC8vIFplcm8gcGF5bG9hZCBieXRlcyBhZnRlciB0aGUgcHJlbHVkZSBtYWtlcyBBUEkgR2F0ZXdheSBhbnN3ZXIgNTAyLCBhbmRcbiAgICAvLyBtYWtlcyBhIEZ1bmN0aW9uIFVSTCBkcm9wIHRoZSBwcmVsdWRlIGFuZCBhbnN3ZXIgYSBiYXJlXG4gICAgLy8gYDIwMCBhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1gLlxuICAgIGV4cGVjdChzaW5rLmJvZHkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcIiBcIik7XG4gIH0pO1xuXG4gIGl0KFwicGFkcyBhIEhFQUQgcmVzcG9uc2UsIHdob3NlIGJvZHkgaXMgZW1wdHkgYnkgZGVmaW5pdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2luayA9IGF3YWl0IHJ1bihcbiAgICAgIChyZXMpID0+IHtcbiAgICAgICAgcmVzLnNldEhlYWRlcihcImNvbnRlbnQtdHlwZVwiLCBcInRleHQvaHRtbDsgY2hhcnNldD11dGYtOFwiKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcihcImNvbnRlbnQtbGVuZ3RoXCIsIFwiNTc5OFwiKTtcbiAgICAgICAgcmVzLmVuZCgpO1xuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgcGFkRW1wdHlCb2R5OiB0cnVlLFxuICAgICAgICByZXE6IHJlcXVlc3RXaXRoKHsgXCJhY2NlcHQtZW5jb2RpbmdcIjogXCJnemlwXCIgfSwgXCJIRUFEXCIpLFxuICAgICAgfSxcbiAgICApO1xuICAgIGV4cGVjdChzaW5rLmJvZHkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcIiBcIik7XG4gICAgLy8gVGhlIGhlYWQgc3RpbGwgZGVzY3JpYmVzIHdoYXQgYSBHRVQgd291bGQgcmV0dXJuOyB0aGUgcGFkZGluZyBieXRlIGlzIG5vdFxuICAgIC8vIGEgYm9keSBhbmQgdGhlIGludGVncmF0aW9uIG92ZXJ3cml0ZXMgYGNvbnRlbnQtbGVuZ3RoYCB3aXRoIDAuXG4gICAgZXhwZWN0KHNpbmsuaGVhZD8uaGVhZGVyc1tcImNvbnRlbnQtbGVuZ3RoXCJdKS50b0JlKFwiNTc5OFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJsZWF2ZXMgYSBub24tZW1wdHkgYm9keSBhbG9uZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2luayA9IGF3YWl0IHJ1bigocmVzKSA9PiByZXMuZW5kKFwicmVhbFwiKSwge1xuICAgICAgcGFkRW1wdHlCb2R5OiB0cnVlLFxuICAgICAgY29tcHJlc3M6IGZhbHNlLFxuICAgIH0pO1xuICAgIGV4cGVjdChzaW5rLmJvZHkudG9TdHJpbmcoXCJ1dGYtOFwiKSkudG9CZShcInJlYWxcIik7XG4gIH0pO1xuXG4gIGl0KFwic2VuZHMgbm90aGluZyBmb3IgYW4gZW1wdHkgYm9keSB3aGVuIHRoZSBzaW5rIGRvZXMgbm90IGFza1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2luayA9IGF3YWl0IHJ1bigocmVzKSA9PiB7XG4gICAgICByZXMuc3RhdHVzQ29kZSA9IDMwNDtcbiAgICAgIHJlcy5lbmQoKTtcbiAgICB9KTtcbiAgICBleHBlY3Qoc2luay5ib2R5KS50b0hhdmVMZW5ndGgoMCk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKFwicGlwZVRvU2luayBsaWZlY3ljbGVcIiwgKCkgPT4ge1xuICAvKipcbiAgICogYGhhbmRsZSgpYCBhd2FpdHMgdGhpcyBwcm9taXNlIGJlZm9yZSBpdCBmbHVzaGVzIGB3YWl0VW50aWxgIHdvcmsg4oCUIElTUlxuICAgKiByZXZhbGlkYXRpb24sIGNhY2hlIHdyaXRlcyDigJQgYW5kIGJlZm9yZSB0aGUgcmVxdWVzdCdzIGNsb3N1cmVzIGNhbiBiZVxuICAgKiBjb2xsZWN0ZWQuIEEgY2xpZW50IHRoYXQgZGlzY29ubmVjdHMgYmVmb3JlIHRoZSBmaXJzdCBieXRlIGRlc3Ryb3lzIHRoZVxuICAgKiByZXNwb25zZSB3aXRob3V0IGFuIGVycm9yLCB3aGljaCBlbWl0cyBvbmx5IGBcImNsb3NlXCJgOiB0aGUgcGlwZWxpbmUgbmV2ZXJcbiAgICogc3RhcnRlZCwgc28gbm90aGluZyBlbHNlIGNhbiBzZXR0bGUgdGhlIHByb21pc2UgYW5kIHRoZSBhd2FpdCBuZXZlciByZXR1cm5lZC5cbiAgICovXG4gIGl0KFwic2V0dGxlcyB3aGVuIHRoZSByZXNwb25zZSBpcyBkZXN0cm95ZWQgYmVmb3JlIHRoZSBoZWFkIGdvZXMgb3V0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXEgPSByZXF1ZXN0V2l0aCh7fSk7XG4gICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgIGNvbnN0IGRvbmUgPSBwaXBlVG9TaW5rKHJlcSwgcmVzLCBuZXcgQ29sbGVjdGluZ1NpbmsoKSwge1xuICAgICAgY29tcHJlc3M6IHRydWUsXG4gICAgfSk7XG5cbiAgICByZXMuZGVzdHJveSgpO1xuXG4gICAgYXdhaXQgZXhwZWN0KGRvbmUpLnJlc29sdmVzLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG5cbiAgLy8gVGhlIG5vcm1hbCBwYXRoIGhhcyB0byBrZWVwIHNldHRsaW5nIG9uIHRoZSBwaXBlbGluZSwgbm90IG9uIGBcImNsb3NlXCJgOiB0aGVcbiAgLy8gYm9keSBtdXN0IGJlIGZ1bGx5IGZsdXNoZWQgaW50byB0aGUgc2luayBieSB0aGUgdGltZSB0aGlzIHJlc29sdmVzLlxuICBpdChcInN0aWxsIHNldHRsZXMgb24gdGhlIHBpcGVsaW5lIG9uY2UgdGhlIGhlYWQgaGFzIGdvbmUgb3V0XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzaW5rID0gYXdhaXQgcnVuKFxuICAgICAgKHJlcykgPT4ge1xuICAgICAgICByZXMuc2V0SGVhZGVyKFwiY29udGVudC10eXBlXCIsIFwidGV4dC9wbGFpblwiKTtcbiAgICAgICAgcmVzLmVuZChcImJvZHlcIik7XG4gICAgICB9LFxuICAgICAgeyBjb21wcmVzczogZmFsc2UgfSxcbiAgICApO1xuXG4gICAgZXhwZWN0KHNpbmsuYm9keS50b1N0cmluZygpKS50b0JlKFwiYm9keVwiKTtcbiAgfSk7XG5cbiAgaXQoXCJyZWplY3RzIHdoZW4gdGhlIHJlc3BvbnNlIGVycm9yc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVxID0gcmVxdWVzdFdpdGgoe30pO1xuICAgIGNvbnN0IHJlcyA9IG5ldyBTaGltU2VydmVyUmVzcG9uc2UoKTtcbiAgICBjb25zdCBkb25lID0gcGlwZVRvU2luayhyZXEsIHJlcywgbmV3IENvbGxlY3RpbmdTaW5rKCksIHtcbiAgICAgIGNvbXByZXNzOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgcmVzLmRlc3Ryb3kobmV3IEVycm9yKFwiYm9vbVwiKSk7XG5cbiAgICBhd2FpdCBleHBlY3QoZG9uZSkucmVqZWN0cy50b1Rocm93KFwiYm9vbVwiKTtcbiAgfSk7XG5cbiAgLy8gQSBzaW5rIHRoYXQgY2Fubm90IHRha2UgdGhlIGhlYWQg4oCUIGB3cml0ZUhlYWRgIHJlamVjdGluZyBhIGhlYWRlciB2YWx1ZSBpc1xuICAvLyB0aGUgcmVhbCBjYXNlIOKAlCB0aHJvd3MgZnJvbSBpbnNpZGUgdGhlIGBcImhlYWRcImAgbGlzdGVuZXIsIHdoZXJlIG5vdGhpbmdcbiAgLy8gZWxzZSB3b3VsZCBjYXRjaCBpdCBhbmQgdGhlIHBpcGVsaW5lIG5ldmVyIHN0YXJ0cy5cbiAgaXQuZWFjaChbXG4gICAgW1wid3JpdGVzIGEgYm9keVwiLCAocmVzOiBTaGltU2VydmVyUmVzcG9uc2UpID0+IHJlcy5lbmQoXCJib2R5XCIpXSxcbiAgICBbXCJlbmRzIGVtcHR5XCIsIChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSkgPT4gcmVzLmVuZCgpXSxcbiAgICBbXCJmbHVzaGVzIGl0cyBoZWFkIGZpcnN0XCIsIChyZXM6IFNoaW1TZXJ2ZXJSZXNwb25zZSkgPT4gcmVzLndyaXRlSGVhZCgyMDApXSxcbiAgXSkoXG4gICAgXCJyZWplY3RzIGFuZCBkZXN0cm95cyB0aGUgcmVzcG9uc2Ugd2hlbiBiZWdpbigpIHRocm93cyBhbmQgdGhlIHJlc3BvbnNlICVzXCIsXG4gICAgYXN5bmMgKF9uYW1lLCB3cml0ZSkgPT4ge1xuICAgICAgY29uc3QgcmVxID0gcmVxdWVzdFdpdGgoe30pO1xuICAgICAgY29uc3QgcmVzID0gbmV3IFNoaW1TZXJ2ZXJSZXNwb25zZSgpO1xuICAgICAgY29uc3QgZG9uZSA9IHBpcGVUb1NpbmsoXG4gICAgICAgIHJlcSxcbiAgICAgICAgcmVzLFxuICAgICAgICB7XG4gICAgICAgICAgYmVnaW4oKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJiYWQgaGVhZFwiKTtcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7IGNvbXByZXNzOiBmYWxzZSB9LFxuICAgICAgKTtcblxuICAgICAgd3JpdGUocmVzKTtcblxuICAgICAgYXdhaXQgZXhwZWN0KGRvbmUpLnJlamVjdHMudG9UaHJvdyhcImJhZCBoZWFkXCIpO1xuICAgICAgZXhwZWN0KHJlcy5kZXN0cm95ZWQpLnRvQmUodHJ1ZSk7XG4gICAgfSxcbiAgKTtcbn0pO1xuXG5kZXNjcmliZShcImFjY2VwdHNHemlwXCIsICgpID0+IHtcbiAgaXQuZWFjaChbXG4gICAgW1wiZ3ppcFwiLCB0cnVlXSxcbiAgICBbXCJnemlwLCBkZWZsYXRlLCBiclwiLCB0cnVlXSxcbiAgICBbXCJHWklQO3E9MC41XCIsIHRydWVdLFxuICAgIFtcImd6aXA7cT0wXCIsIGZhbHNlXSxcbiAgICBbXCIqXCIsIHRydWVdLFxuICAgIFtcIio7cT0wXCIsIGZhbHNlXSxcbiAgICAvLyBBbiBleHBsaWNpdCBnemlwIHByZWZlcmVuY2Ugd2lucyBvdmVyIHRoZSB3aWxkY2FyZCwgaW4gZWl0aGVyIG9yZGVyLlxuICAgIFtcIio7cT0wLCBnemlwXCIsIHRydWVdLFxuICAgIFtcImd6aXA7cT0wLCAqXCIsIGZhbHNlXSxcbiAgICBbXCJiciwgZGVmbGF0ZVwiLCBmYWxzZV0sXG4gICAgW1wiXCIsIGZhbHNlXSxcbiAgICBbdW5kZWZpbmVkLCBmYWxzZV0sXG4gIF0pKFwiJXMg4oaSICVzXCIsIChoZWFkZXIsIGV4cGVjdGVkKSA9PiB7XG4gICAgZXhwZWN0KGFjY2VwdHNHemlwKGhlYWRlcikpLnRvQmUoZXhwZWN0ZWQpO1xuICB9KTtcblxuICBpdChcImpvaW5zIGEgcmVwZWF0ZWQgaGVhZGVyIGJlZm9yZSBwYXJzaW5nXCIsICgpID0+IHtcbiAgICBleHBlY3QoYWNjZXB0c0d6aXAoW1wiYnJcIiwgXCJnemlwXCJdKSkudG9CZSh0cnVlKTtcbiAgfSk7XG59KTtcbiJdfQ==
@@ -0,0 +1,78 @@
1
+ /**
2
+ * S3 fetching and error mapping for `/_next/image`, split out from
3
+ * {@link ./image.ts} so it is unit-testable without `next` present.
4
+ *
5
+ * The one value from `next` that this file needs is passed in rather than
6
+ * imported: `next` is external to the shell bundles, so a static `import` here
7
+ * would be hoisted into the bundle where it cannot resolve. `image.ts` requires
8
+ * it through `./next-modules` instead.
9
+ */
10
+ import { S3Client } from "@aws-sdk/client-s3";
11
+ /** Where the app is served versus where its assets were uploaded. */
12
+ export interface S3AssetLocation {
13
+ /**
14
+ * The app's own `basePath` — the prefix of the *URL* it is served at. Only
15
+ * stripped from the href, never used to build a key: on the API Gateway
16
+ * deployment types this is the stage name, which never appears in S3.
17
+ */
18
+ readonly urlBasePath: string;
19
+ /**
20
+ * `NextjsStaticAssets.keyPrefix`: the S3 key prefix the assets were uploaded
21
+ * under, without a leading slash. Empty for a bucket-root deployment.
22
+ */
23
+ readonly keyPrefix: string;
24
+ /**
25
+ * The app's `assetPrefix`, when it is a path (`/cdn`). Next.js puts it in
26
+ * front of `/_next/` in place of `basePath`, so a statically imported image's
27
+ * href is `/cdn/_next/static/media/…`, and `next start` strips it again when
28
+ * it serves the file. An absolute `assetPrefix` makes the href absolute, which
29
+ * never reaches here.
30
+ * @default - none
31
+ */
32
+ readonly assetPrefix?: string;
33
+ }
34
+ /**
35
+ * Fetches a non-absolute (local) image referenced by an `<Image>` from S3.
36
+ *
37
+ * `url` is inconsistent about the app's `basePath`: next-image-loader bakes it
38
+ * into the href for statically imported images, while plain string paths are
39
+ * passed through as literally written by the app. So it is stripped when present,
40
+ * leaving a path relative to the asset root, and the bucket's own key prefix is
41
+ * applied to that. Deriving the key from `basePath` instead is wrong whenever the
42
+ * two differ, which they do for every API Gateway deployment.
43
+ *
44
+ * The key is percent-decoded, because an S3 key is the file's real name while
45
+ * `url` is a URL path. `public/hello world.jpg` arrives here as
46
+ * `/hello%20world.jpg` — the `url` query value is double-encoded, so decoding the
47
+ * query string leaves one layer — and its object key is `hello world.jpg`.
48
+ * Next.js's own `fetchInternalImage` gets the decode for free, since it makes an
49
+ * HTTP subrequest and its static file server resolves the path against the
50
+ * filesystem; skipping it here 400'd that file
51
+ * (`next-image-legacy/unicode`). Unicode needs nothing: `äöüščří.png` survives
52
+ * the query decode as itself and is already the object's name.
53
+ *
54
+ * Throws {@link ImageTooLargeError} rather than read past `maximumBody`
55
+ * (`images.maximumResponseBody`), which `next start` enforces on local sources
56
+ * too: a large `public/` file would otherwise be read into memory whole.
57
+ */
58
+ export declare function fetchFromS3(s3: S3Client, bucket: string, url: string, location: S3AssetLocation, maximumBody: number): Promise<{
59
+ buffer: Buffer;
60
+ contentType: string | null;
61
+ etag: string;
62
+ }>;
63
+ /** A source over `images.maximumResponseBody`; see {@link fetchFromS3}. */
64
+ export declare class ImageTooLargeError extends Error {
65
+ constructor(key: string);
66
+ }
67
+ /** `ImageError` from `next/dist/server/image-optimizer.js`. */
68
+ export type ImageErrorClass = (typeof import("next/dist/server/image-optimizer.js"))["ImageError"];
69
+ /**
70
+ * Maps an error thrown while processing an image request to the HTTP
71
+ * status/message it should produce, preserving the status Next.js's own
72
+ * `ImageError`/`fetchExternalImage` attach. A source over
73
+ * `images.maximumResponseBody` is the 413 `fetchInternalImage` answers.
74
+ */
75
+ export declare function resolveErrorResponse(error: unknown, ImageError: ImageErrorClass): {
76
+ statusCode: number;
77
+ message: string;
78
+ };