cdk-nextjs 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +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 +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 +1213 -0
  157. package/lib/runtime/core.test.d.ts +1 -0
  158. package/lib/runtime/core.test.js +1678 -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 +41595 -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 +55 -0
  213. package/lib/runtime/next-modules.js +124 -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 +41588 -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
@@ -8,9 +8,32 @@ function sha256(input) {
8
8
  : Buffer.from(new Uint8Array(input));
9
9
  return (0, node_crypto_1.createHash)("sha256").update(buffer).digest("hex");
10
10
  }
11
+ class FakeXMLHttpRequest {
12
+ open(_method, _url) { }
13
+ send(_body) { }
14
+ setRequestHeader(_name, _value) { }
15
+ }
16
+ /**
17
+ * The patch runs in a browser *and* in a web worker, where `window` does not
18
+ * exist — so the stub goes on `globalThis`, which is what both scopes are. Tests
19
+ * that want the main-thread scope also set `globalThis.window`, since real
20
+ * browser code reaches the patched `fetch` through it and `window === globalThis`
21
+ * there.
22
+ */
23
+ function installScope({ withWindow = true, withXhr = true } = {}) {
24
+ global.location = {
25
+ href: "https://example.com/",
26
+ hostname: "example.com",
27
+ };
28
+ if (withXhr)
29
+ global.XMLHttpRequest = FakeXMLHttpRequest;
30
+ if (withWindow)
31
+ global.window = global;
32
+ }
11
33
  describe("patch-fetch", () => {
12
34
  let originalFetch;
13
35
  let capturedInit;
36
+ const realFetch = global.fetch;
14
37
  beforeEach(() => {
15
38
  jest.resetModules();
16
39
  capturedInit = undefined;
@@ -18,20 +41,16 @@ describe("patch-fetch", () => {
18
41
  capturedInit = init;
19
42
  return Promise.resolve(new Response("ok"));
20
43
  });
21
- global.window = {
22
- location: { href: "https://example.com/", hostname: "example.com" },
23
- fetch: originalFetch,
24
- XMLHttpRequest: class {
25
- open(_method, _url) { }
26
- send(_body) { }
27
- setRequestHeader(_name, _value) { }
28
- },
29
- };
30
- // eslint-disable-next-line @typescript-eslint/no-require-imports -- must re-execute against the fresh `window` stub each test
44
+ global.fetch = originalFetch;
45
+ installScope();
46
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- must re-execute against the fresh global stub each test
31
47
  require("./patch-fetch.js");
32
48
  });
33
49
  afterEach(() => {
34
50
  delete global.window;
51
+ delete global.location;
52
+ delete global.XMLHttpRequest;
53
+ global.fetch = realFetch;
35
54
  });
36
55
  describe("fetch", () => {
37
56
  test("hashes URLSearchParams via toString(), not JSON.stringify", async () => {
@@ -94,6 +113,37 @@ describe("patch-fetch", () => {
94
113
  const headers = capturedInit.headers;
95
114
  expect(headers.get("x-amz-content-sha256")).toBe(sha256(buffer));
96
115
  });
116
+ test("hashes a typed array body over the bytes it views", async () => {
117
+ const bytes = new TextEncoder().encode("xxtyped array contents");
118
+ const view = bytes.subarray(2);
119
+ await global.window.fetch("https://example.com/api", {
120
+ method: "POST",
121
+ body: view,
122
+ });
123
+ const headers = capturedInit.headers;
124
+ expect(headers.get("x-amz-content-sha256")).toBe(sha256("typed array contents"));
125
+ });
126
+ test("wraps fetch once when a second patched chunk loads in the same scope", async () => {
127
+ // Every entrypoint chunk carries a copy. Wrapped twice, the outer wrapper
128
+ // re-encoded a FormData body to bytes and the inner one overwrote the
129
+ // right hash with one of those bytes as JSON.
130
+ const patchedOnce = global.fetch;
131
+ const patchedXhr = global.XMLHttpRequest;
132
+ jest.resetModules();
133
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- the second chunk's copy
134
+ require("./patch-fetch.js");
135
+ expect(global.fetch).toBe(patchedOnce);
136
+ expect(global.XMLHttpRequest).toBe(patchedXhr);
137
+ const formData = new FormData();
138
+ formData.append("field", "value");
139
+ await global.window.fetch("https://example.com/api", {
140
+ method: "POST",
141
+ body: formData,
142
+ });
143
+ expect(originalFetch).toHaveBeenCalledTimes(1);
144
+ const headers = capturedInit.headers;
145
+ expect(headers.get("x-amz-content-sha256")).toBe(sha256(capturedInit.body));
146
+ });
97
147
  test("hashes an empty byte array when no body is present", async () => {
98
148
  await global.window.fetch("https://example.com/api", {
99
149
  method: "POST",
@@ -101,6 +151,36 @@ describe("patch-fetch", () => {
101
151
  const headers = capturedInit.headers;
102
152
  expect(headers.get("x-amz-content-sha256")).toBe(sha256(new Uint8Array(0)));
103
153
  });
154
+ test("hashes a Request's own body when init is omitted", async () => {
155
+ const request = new Request("https://example.com/api", {
156
+ method: "POST",
157
+ body: "request body",
158
+ headers: { "content-type": "text/plain" },
159
+ });
160
+ await global.window.fetch(request);
161
+ const [sentInput] = originalFetch.mock.calls[0];
162
+ expect(sentInput).toBe(request);
163
+ // The body was read from a clone, so the request still has it to send.
164
+ expect(await sentInput.text()).toBe("request body");
165
+ const headers = capturedInit.headers;
166
+ expect(headers.get("x-amz-content-sha256")).toBe(sha256("request body"));
167
+ // `init.headers` replaces the request's own, so they must carry over.
168
+ expect(headers.get("content-type")).toBe("text/plain");
169
+ });
170
+ test("hashes init's body over a Request's own when both are set", async () => {
171
+ const request = new Request("https://example.com/api", {
172
+ method: "POST",
173
+ body: "request body",
174
+ });
175
+ await global.window.fetch(request, { body: "init body" });
176
+ const headers = capturedInit.headers;
177
+ expect(headers.get("x-amz-content-sha256")).toBe(sha256("init body"));
178
+ });
179
+ test("passes a GET Request through without hashing", async () => {
180
+ const request = new Request("https://example.com/api");
181
+ await global.window.fetch(request);
182
+ expect(originalFetch).toHaveBeenCalledWith(request, undefined);
183
+ });
104
184
  test("passes through untouched when init is omitted", async () => {
105
185
  await global.window.fetch("https://example.com/api");
106
186
  expect(originalFetch).toHaveBeenCalledWith("https://example.com/api", undefined);
@@ -155,6 +235,35 @@ describe("patch-fetch", () => {
155
235
  await xhr.send("should not be hashed");
156
236
  expect(setRequestHeader).not.toHaveBeenCalled();
157
237
  });
238
+ test("hashes the bytes of a typed-array or Blob body, not their JSON", async () => {
239
+ const bytes = new Uint8Array([1, 2, 3, 250]);
240
+ for (const body of [bytes, new Blob([bytes])]) {
241
+ const setRequestHeader = jest.fn();
242
+ const xhr = new global.window.XMLHttpRequest();
243
+ xhr.setRequestHeader = setRequestHeader;
244
+ xhr.open("POST", "https://example.com/api");
245
+ await xhr.send(body);
246
+ expect(setRequestHeader).toHaveBeenCalledWith("x-amz-content-sha256", sha256(bytes));
247
+ }
248
+ });
249
+ test("sends a FormData body as the encoding it hashed, with its boundary", async () => {
250
+ const send = jest.spyOn(FakeXMLHttpRequest.prototype, "send");
251
+ const setRequestHeader = jest.fn();
252
+ const form = new FormData();
253
+ form.append("name", "value");
254
+ form.append("file", new Blob(["file-bytes"]), "a.txt");
255
+ const xhr = new global.window.XMLHttpRequest();
256
+ xhr.setRequestHeader = setRequestHeader;
257
+ xhr.open("POST", "https://example.com/api");
258
+ await xhr.send(form);
259
+ const sent = send.mock.calls[0][0];
260
+ expect(sent).toBeInstanceOf(Uint8Array);
261
+ expect(setRequestHeader).toHaveBeenCalledWith("x-amz-content-sha256", sha256(sent));
262
+ const contentType = setRequestHeader.mock.calls.find(([name]) => name === "content-type")?.[1];
263
+ expect(contentType).toMatch(/^multipart\/form-data; boundary=/);
264
+ expect(Buffer.from(sent).toString()).toContain(contentType.split("boundary=")[1]);
265
+ send.mockRestore();
266
+ });
158
267
  test("does not hash when there is no body", async () => {
159
268
  const setRequestHeader = jest.fn();
160
269
  const xhr = new global.window.XMLHttpRequest();
@@ -165,4 +274,50 @@ describe("patch-fetch", () => {
165
274
  });
166
275
  });
167
276
  });
168
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0Y2gtZmV0Y2gudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9uZXh0anMtYnVpbGQvcGF0Y2gtZmV0Y2gudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHNEQUFzRDtBQUN0RCw2Q0FBeUM7QUFFekMsU0FBUyxNQUFNLENBQUMsS0FBd0M7SUFDdEQsTUFBTSxNQUFNLEdBQ1YsT0FBTyxLQUFLLEtBQUssUUFBUTtRQUN2QixDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDcEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN6QyxPQUFPLElBQUEsd0JBQVUsRUFBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRCxRQUFRLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRTtJQUMzQixJQUFJLGFBQXdCLENBQUM7SUFDN0IsSUFBSSxZQUFxQyxDQUFDO0lBRTFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsWUFBWSxHQUFHLFNBQVMsQ0FBQztRQUV6QixhQUFhLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQWUsRUFBRSxJQUFrQixFQUFFLEVBQUU7WUFDOUQsWUFBWSxHQUFHLElBQUksQ0FBQztZQUNwQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQztRQUVGLE1BQWMsQ0FBQyxNQUFNLEdBQUc7WUFDdkIsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLHNCQUFzQixFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUU7WUFDbkUsS0FBSyxFQUFFLGFB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QyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llcyAqL1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuXG5mdW5jdGlvbiBzaGEyNTYoaW5wdXQ6IHN0cmluZyB8IEFycmF5QnVmZmVyIHwgVWludDhBcnJheSkge1xuICBjb25zdCBidWZmZXIgPVxuICAgIHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBCdWZmZXIuZnJvbShpbnB1dClcbiAgICAgIDogQnVmZmVyLmZyb20obmV3IFVpbnQ4QXJyYXkoaW5wdXQpKTtcbiAgcmV0dXJuIGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGJ1ZmZlcikuZGlnZXN0KFwiaGV4XCIpO1xufVxuXG5kZXNjcmliZShcInBhdGNoLWZldGNoXCIsICgpID0+IHtcbiAgbGV0IG9yaWdpbmFsRmV0Y2g6IGplc3QuTW9jaztcbiAgbGV0IGNhcHR1cmVkSW5pdDogUmVxdWVzdEluaXQgfCB1bmRlZmluZWQ7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgamVzdC5yZXNldE1vZHVsZXMoKTtcbiAgICBjYXB0dXJlZEluaXQgPSB1bmRlZmluZWQ7XG5cbiAgICBvcmlnaW5hbEZldGNoID0gamVzdC5mbigoX2lucHV0OiB1bmtub3duLCBpbml0PzogUmVxdWVzdEluaXQpID0+IHtcbiAgICAgIGNhcHR1cmVkSW5pdCA9IGluaXQ7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBSZXNwb25zZShcIm9rXCIpKTtcbiAgICB9KTtcblxuICAgIChnbG9iYWwgYXMgYW55KS53aW5kb3cgPSB7XG4gICAgICBsb2NhdGlvbjogeyBocmVmOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vXCIsIGhvc3RuYW1lOiBcImV4YW1wbGUuY29tXCIgfSxcbiAgICAgIGZldGNoOiBvcmlnaW5hbEZldGNoLFxuICAgICAgWE1MSHR0cFJlcXVlc3Q6IGNsYXNzIHtcbiAgICAgICAgb3BlbihfbWV0aG9kOiBzdHJpbmcsIF91cmw6IHN0cmluZykge31cbiAgICAgICAgc2VuZChfYm9keT86IHVua25vd24pIHt9XG4gICAgICAgIHNldFJlcXVlc3RIZWFkZXIoX25hbWU6IHN0cmluZywgX3ZhbHVlOiBzdHJpbmcpIHt9XG4gICAgICB9LFxuICAgIH07XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAtLSBtdXN0IHJlLWV4ZWN1dGUgYWdhaW5zdCB0aGUgZnJlc2ggYHdpbmRvd2Agc3R1YiBlYWNoIHRlc3RcbiAgICByZXF1aXJlKFwiLi9wYXRjaC1mZXRjaC5qc1wiKTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBkZWxldGUgKGdsb2JhbCBhcyBhbnkpLndpbmRvdztcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJmZXRjaFwiLCAoKSA9PiB7XG4gICAgdGVzdChcImhhc2hlcyBVUkxTZWFyY2hQYXJhbXMgdmlhIHRvU3RyaW5nKCksIG5vdCBKU09OLnN0cmluZ2lmeVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHsgYTogXCIxXCIsIGI6IFwiMlwiIH0pO1xuXG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBwYXJhbXMsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoXG4gICAgICAgIHNoYTI1NihwYXJhbXMudG9TdHJpbmcoKSksXG4gICAgICApO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLm5vdC50b0JlKHNoYTI1NihcInt9XCIpKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJoYXNoZXMgYSBwbGFpbiBzdHJpbmcgYm9keVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBcInJhdyB0ZXh0IGJvZHlcIixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShzaGEyNTYoXCJyYXcgdGV4dCBib2R5XCIpKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJoYXNoZXMgYSBGb3JtRGF0YSBib2R5IG92ZXIgaXRzIGV4YWN0IGVuY29kZWQgYnl0ZXMgYW5kIHNldHMgY29udGVudC10eXBlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICBmb3JtRGF0YS5hcHBlbmQoXCJmaWVsZFwiLCBcInZhbHVlXCIpO1xuICAgICAgZm9ybURhdGEuYXBwZW5kKFxuICAgICAgICBcImZpbGVcIixcbiAgICAgICAgbmV3IEJsb2IoW1wiZmlsZSBjb250ZW50c1wiXSwgeyB0eXBlOiBcInRleHQvcGxhaW5cIiB9KSxcbiAgICAgICAgXCJmaWxlLnR4dFwiLFxuICAgICAgKTtcblxuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgYm9keTogZm9ybURhdGEsXG4gICAgICB9KTtcblxuICAgICAgLy8gdGhlIGJvZHkgc2VudCB0byB0aGUgcmVhbCBmZXRjaCBtdXN0IGJlIHRoZSByZS1lbmNvZGVkIGJ5dGVzLCBub3QgdGhlIG9yaWdpbmFsIEZvcm1EYXRhXG4gICAgICBjb25zdCBzZW50Qnl0ZXMgPSBjYXB0dXJlZEluaXQhLmJvZHkgYXMgVWludDhBcnJheTtcbiAgICAgIGV4cGVjdChzZW50Qnl0ZXMpLnRvQmVJbnN0YW5jZU9mKFVpbnQ4QXJyYXkpO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBjb25zdCBjb250ZW50VHlwZSA9IGhlYWRlcnMuZ2V0KFwiY29udGVudC10eXBlXCIpITtcbiAgICAgIGV4cGVjdChjb250ZW50VHlwZSkudG9NYXRjaCgvXm11bHRpcGFydFxcL2Zvcm0tZGF0YTsgYm91bmRhcnk9Lyk7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShzaGEyNTYoc2VudEJ5dGVzKSk7XG5cbiAgICAgIC8vIHRoZSBoYXNoZWQvc2VudCBieXRlcyBtdXN0IHJvdW5kLXRyaXAgYmFjayB0byB0aGUgb3JpZ2luYWwgZmllbGRzXG4gICAgICBjb25zdCByb3VuZFRyaXBwZWQgPSBhd2FpdCBuZXcgUmVzcG9uc2Uoc2VudEJ5dGVzLCB7XG4gICAgICAgIGhlYWRlcnM6IHsgXCJjb250ZW50LXR5cGVcIjogY29udGVudFR5cGUgfSxcbiAgICAgIH0pLmZvcm1EYXRhKCk7XG4gICAgICBleHBlY3Qocm91bmRUcmlwcGVkLmdldChcImZpZWxkXCIpKS50b0JlKFwidmFsdWVcIik7XG4gICAgICBjb25zdCBmaWxlID0gcm91bmRUcmlwcGVkLmdldChcImZpbGVcIikgYXMgRmlsZTtcbiAgICAgIGV4cGVjdChmaWxlLm5hbWUpLnRvQmUoXCJmaWxlLnR4dFwiKTtcbiAgICAgIGV4cGVjdChhd2FpdCBmaWxlLnRleHQoKSkudG9CZShcImZpbGUgY29udGVudHNcIik7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFzaGVzIGEgQmxvYiBib2R5IG92ZXIgaXRzIHJhdyBieXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW1wiYmxvYiBjb250ZW50c1wiXSwgeyB0eXBlOiBcInRleHQvcGxhaW5cIiB9KTtcblxuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgYm9keTogYmxvYixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShcbiAgICAgICAgc2hhMjU2KGF3YWl0IGJsb2IuYXJyYXlCdWZmZXIoKSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImhhc2hlcyBhbiBBcnJheUJ1ZmZlciBib2R5IG92ZXIgaXRzIHJhdyBieXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWZmZXIgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoXCJhcnJheSBidWZmZXIgY29udGVudHNcIikuYnVmZmVyO1xuXG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUFVUXCIsXG4gICAgICAgIGJvZHk6IGJ1ZmZlcixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShzaGEyNTYoYnVmZmVyKSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFzaGVzIGFuIGVtcHR5IGJ5dGUgYXJyYXkgd2hlbiBubyBib2R5IGlzIHByZXNlbnRcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShcbiAgICAgICAgc2hhMjU2KG5ldyBVaW50OEFycmF5KDApKSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwicGFzc2VzIHRocm91Z2ggdW50b3VjaGVkIHdoZW4gaW5pdCBpcyBvbWl0dGVkXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IChnbG9iYWwgYXMgYW55KS53aW5kb3cuZmV0Y2goXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcblxuICAgICAgZXhwZWN0KG9yaWdpbmFsRmV0Y2gpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwicGFzc2VzIHRocm91Z2ggd2l0aG91dCBoYXNoaW5nIGZvciBub24tUFVUL1BPU1QgbWV0aG9kc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICAgIGJvZHk6IFwic2hvdWxkIG5vdCBiZSBoYXNoZWRcIixcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoY2FwdHVyZWRJbml0IS5oZWFkZXJzKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwicGFzc2VzIHRocm91Z2ggd2l0aG91dCBoYXNoaW5nIGZvciBjcm9zcy1vcmlnaW4gcmVxdWVzdHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vb3RoZXItb3JpZ2luLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBcInNob3VsZCBub3QgYmUgaGFzaGVkXCIsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KGNhcHR1cmVkSW5pdCEuaGVhZGVycykudG9CZVVuZGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIlhNTEh0dHBSZXF1ZXN0XCIsICgpID0+IHtcbiAgICB0ZXN0KFwiaGFzaGVzIFVSTFNlYXJjaFBhcmFtcyB2aWEgdG9TdHJpbmcoKSwgbm90IEpTT04uc3RyaW5naWZ5XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoeyBhOiBcIjFcIiwgYjogXCIyXCIgfSk7XG4gICAgICBjb25zdCBzZXRSZXF1ZXN0SGVhZGVyID0gamVzdC5mbigpO1xuXG4gICAgICBjb25zdCB4aHIgPSBuZXcgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIgPSBzZXRSZXF1ZXN0SGVhZGVyO1xuICAgICAgeGhyLm9wZW4oXCJQT1NUXCIsIFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIik7XG4gICAgICBhd2FpdCB4aHIuc2VuZChwYXJhbXMpO1xuXG4gICAgICBleHBlY3Qoc2V0UmVxdWVzdEhlYWRlcikudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIFwieC1hbXotY29udGVudC1zaGEyNTZcIixcbiAgICAgICAgc2hhMjU2KHBhcmFtcy50b1N0cmluZygpKSxcbiAgICAgICk7XG4gICAgICBleHBlY3Qoc2V0UmVxdWVzdEhlYWRlcikubm90LnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBcIngtYW16LWNvbnRlbnQtc2hhMjU2XCIsXG4gICAgICAgIHNoYTI1NihcInt9XCIpLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJoYXNoZXMgYSBwbGFpbiBzdHJpbmcgYm9keVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXRSZXF1ZXN0SGVhZGVyID0gamVzdC5mbigpO1xuXG4gICAgICBjb25zdCB4aHIgPSBuZXcgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIgPSBzZXRSZXF1ZXN0SGVhZGVyO1xuICAgICAgeGhyLm9wZW4oXCJQVVRcIiwgXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcbiAgICAgIGF3YWl0IHhoci5zZW5kKFwicmF3IHRleHQgYm9keVwiKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBcIngtYW16LWNvbnRlbnQtc2hhMjU2XCIsXG4gICAgICAgIHNoYTI1NihcInJhdyB0ZXh0IGJvZHlcIiksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImRvZXMgbm90IGhhc2ggZm9yIG5vbi1QVVQvUE9TVCBtZXRob2RzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNldFJlcXVlc3RIZWFkZXIgPSBqZXN0LmZuKCk7XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyAoZ2xvYmFsIGFzIGFueSkud2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlciA9IHNldFJlcXVlc3RIZWFkZXI7XG4gICAgICB4aHIub3BlbihcIkdFVFwiLCBcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIpO1xuICAgICAgYXdhaXQgeGhyLnNlbmQoXCJzaG91bGQgbm90IGJlIGhhc2hlZFwiKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiZG9lcyBub3QgaGFzaCBmb3IgY3Jvc3Mtb3JpZ2luIHJlcXVlc3RzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNldFJlcXVlc3RIZWFkZXIgPSBqZXN0LmZuKCk7XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyAoZ2xvYmFsIGFzIGFueSkud2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlciA9IHNldFJlcXVlc3RIZWFkZXI7XG4gICAgICB4aHIub3BlbihcIlBPU1RcIiwgXCJodHRwczovL290aGVyLW9yaWdpbi5jb20vYXBpXCIpO1xuICAgICAgYXdhaXQgeGhyLnNlbmQoXCJzaG91bGQgbm90IGJlIGhhc2hlZFwiKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiZG9lcyBub3QgaGFzaCB3aGVuIHRoZXJlIGlzIG5vIGJvZHlcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2V0UmVxdWVzdEhlYWRlciA9IGplc3QuZm4oKTtcblxuICAgICAgY29uc3QgeGhyID0gbmV3IChnbG9iYWwgYXMgYW55KS53aW5kb3cuWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyID0gc2V0UmVxdWVzdEhlYWRlcjtcbiAgICAgIHhoci5vcGVuKFwiUE9TVFwiLCBcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIpO1xuICAgICAgYXdhaXQgeGhyLnNlbmQoKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
277
+ /**
278
+ * Turbopack's web-worker bootstrap is `static/chunks/turbopack-worker-*.js`,
279
+ * which `patchFetchInClientJs`'s `turbopack-` selector matches — so this file is
280
+ * prepended to a script that runs off the main thread. Reading `window` there
281
+ * threw before the worker's own module could run, which took out every
282
+ * `new Worker(new URL(…))` app (`worker-module-url`, `worker-relay-compiler`).
283
+ */
284
+ describe("patch-fetch in a worker scope", () => {
285
+ let originalFetch;
286
+ let capturedInit;
287
+ const realFetch = global.fetch;
288
+ beforeEach(() => {
289
+ jest.resetModules();
290
+ capturedInit = undefined;
291
+ originalFetch = jest.fn((_input, init) => {
292
+ capturedInit = init;
293
+ return Promise.resolve(new Response("ok"));
294
+ });
295
+ global.fetch = originalFetch;
296
+ // No `window`, and no `XMLHttpRequest`: the narrowest scope the patch can
297
+ // land in.
298
+ installScope({ withWindow: false, withXhr: false });
299
+ });
300
+ afterEach(() => {
301
+ delete global.window;
302
+ delete global.location;
303
+ global.fetch = realFetch;
304
+ });
305
+ test("loads without a window and still signs a same-origin POST", async () => {
306
+ expect(() => {
307
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- the point of the test is that requiring it does not throw
308
+ require("./patch-fetch.js");
309
+ }).not.toThrow();
310
+ await global.fetch("https://example.com/api", {
311
+ method: "POST",
312
+ body: "worker body",
313
+ });
314
+ const headers = capturedInit.headers;
315
+ expect(headers.get("x-amz-content-sha256")).toBe(sha256("worker body"));
316
+ });
317
+ test("leaves XMLHttpRequest alone when the scope has none", () => {
318
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- re-executed against this scope
319
+ require("./patch-fetch.js");
320
+ expect(global.XMLHttpRequest).toBeUndefined();
321
+ });
322
+ });
323
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0Y2gtZmV0Y2gudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9uZXh0anMtYnVpbGQvcGF0Y2gtZmV0Y2gudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHNEQUFzRDtBQUN0RCw2Q0FBeUM7QUFFekMsU0FBUyxNQUFNLENBQUMsS0FBd0M7SUFDdEQsTUFBTSxNQUFNLEdBQ1YsT0FBTyxLQUFLLEtBQUssUUFBUTtRQUN2QixDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDcEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN6QyxPQUFPLElBQUEsd0JBQVUsRUFBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRCxNQUFNLGtCQUFrQjtJQUN0QixJQUFJLENBQUMsT0FBZSxFQUFFLElBQVksSUFBRyxDQUFDO0lBQ3RDLElBQUksQ0FBQyxLQUFlLElBQUcsQ0FBQztJQUN4QixnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsTUFBYyxJQUFHLENBQUM7Q0FDbkQ7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxFQUFFLFVBQVUsR0FBRyxJQUFJLEVBQUUsT0FBTyxHQUFHLElBQUksRUFBRSxHQUFHLEVBQUU7SUFDN0QsTUFBYyxDQUFDLFFBQVEsR0FBRztRQUN6QixJQUFJLEVBQUUsc0JBQXNCO1FBQzVCLFFBQVEsRUFBRSxhQUFhO0tBQ3hCLENBQUM7SUFDRixJQUFJLE9BQU87UUFBRyxNQUFjLENBQUMsY0FBYyxHQUFHLGtCQUFrQixDQUFDO0lBQ2pFLElBQUksVUFBVTtRQUFHLE1BQWMsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0FBQ2xELENBQUM7QUFFRCxRQUFRLENBQUMsYUFBYSxFQUFF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TUFBTSxDQUFDLEtBQUssR0FBRyxTQUFTLENBQUM7SUFDM0IsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsMkRBQTJELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDM0UsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUNWLDhIQUE4SDtZQUM5SCxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFakIsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5QixFQUFFO1lBQzVDLE1BQU0sRUFBRSxNQUFNO1lBQ2QsSUFBSSxFQUFFLGFBQWE7U0FDcEIsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQUcsWUFBYSxDQUFDLE9BQWtCLENBQUM7UUFDakQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUMxRSxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxxREFBcUQsRUFBRSxHQUFHLEVBQUU7UUFDL0QsbUdBQW1HO1FBQ25HLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBRTVCLE1BQU0sQ0FBRSxNQUFjLENBQUMsY0FBYyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDekQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llcyAqL1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuXG5mdW5jdGlvbiBzaGEyNTYoaW5wdXQ6IHN0cmluZyB8IEFycmF5QnVmZmVyIHwgVWludDhBcnJheSkge1xuICBjb25zdCBidWZmZXIgPVxuICAgIHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBCdWZmZXIuZnJvbShpbnB1dClcbiAgICAgIDogQnVmZmVyLmZyb20obmV3IFVpbnQ4QXJyYXkoaW5wdXQpKTtcbiAgcmV0dXJuIGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGJ1ZmZlcikuZGlnZXN0KFwiaGV4XCIpO1xufVxuXG5jbGFzcyBGYWtlWE1MSHR0cFJlcXVlc3Qge1xuICBvcGVuKF9tZXRob2Q6IHN0cmluZywgX3VybDogc3RyaW5nKSB7fVxuICBzZW5kKF9ib2R5PzogdW5rbm93bikge31cbiAgc2V0UmVxdWVzdEhlYWRlcihfbmFtZTogc3RyaW5nLCBfdmFsdWU6IHN0cmluZykge31cbn1cblxuLyoqXG4gKiBUaGUgcGF0Y2ggcnVucyBpbiBhIGJyb3dzZXIgKmFuZCogaW4gYSB3ZWIgd29ya2VyLCB3aGVyZSBgd2luZG93YCBkb2VzIG5vdFxuICogZXhpc3Qg4oCUIHNvIHRoZSBzdHViIGdvZXMgb24gYGdsb2JhbFRoaXNgLCB3aGljaCBpcyB3aGF0IGJvdGggc2NvcGVzIGFyZS4gVGVzdHNcbiAqIHRoYXQgd2FudCB0aGUgbWFpbi10aHJlYWQgc2NvcGUgYWxzbyBzZXQgYGdsb2JhbFRoaXMud2luZG93YCwgc2luY2UgcmVhbFxuICogYnJvd3NlciBjb2RlIHJlYWNoZXMgdGhlIHBhdGNoZWQgYGZldGNoYCB0aHJvdWdoIGl0IGFuZCBgd2luZG93ID09PSBnbG9iYWxUaGlzYFxuICogdGhlcmUuXG4gKi9cbmZ1bmN0aW9uIGluc3RhbGxTY29wZSh7IHdpdGhXaW5kb3cgPSB0cnVlLCB3aXRoWGhyID0gdHJ1ZSB9ID0ge30pIHtcbiAgKGdsb2JhbCBhcyBhbnkpLmxvY2F0aW9uID0ge1xuICAgIGhyZWY6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9cIixcbiAgICBob3N0bmFtZTogXCJleGFtcGxlLmNvbVwiLFxuICB9O1xuICBpZiAod2l0aFhocikgKGdsb2JhbCBhcyBhbnkpLlhNTEh0dHBSZXF1ZXN0ID0gRmFrZVhNTEh0dHBSZXF1ZXN0O1xuICBpZiAod2l0aFdpbmRvdykgKGdsb2JhbCBhcyBhbnkpLndpbmRvdyA9IGdsb2JhbDtcbn1cblxuZGVzY3JpYmUoXCJwYXRjaC1mZXRjaFwiLCAoKSA9PiB7XG4gIGxldCBvcmlnaW5hbEZldGNoOiBqZXN0Lk1vY2s7XG4gIGxldCBjYXB0dXJlZEluaXQ6IFJlcXVlc3RJbml0IHwgdW5kZWZpbmVkO1xuICBjb25zdCByZWFsRmV0Y2ggPSBnbG9iYWwuZmV0Y2g7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgamVzdC5yZXNldE1vZHVsZXMoKTtcbiAgICBjYXB0dXJlZEluaXQgPSB1bmRlZmluZWQ7XG5cbiAgICBvcmlnaW5hbEZldGNoID0gamVzdC5mbigoX2lucHV0OiB1bmtub3duLCBpbml0PzogUmVxdWVzdEluaXQpID0+IHtcbiAgICAgIGNhcHR1cmVkSW5pdCA9IGluaXQ7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBSZXNwb25zZShcIm9rXCIpKTtcbiAgICB9KTtcbiAgICAoZ2xvYmFsIGFzIGFueSkuZmV0Y2ggPSBvcmlnaW5hbEZldGNoO1xuXG4gICAgaW5zdGFsbFNjb3BlKCk7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAtLSBtdXN0IHJlLWV4ZWN1dGUgYWdhaW5zdCB0aGUgZnJlc2ggZ2xvYmFsIHN0dWIgZWFjaCB0ZXN0XG4gICAgcmVxdWlyZShcIi4vcGF0Y2gtZmV0Y2guanNcIik7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgZGVsZXRlIChnbG9iYWwgYXMgYW55KS53aW5kb3c7XG4gICAgZGVsZXRlIChnbG9iYWwgYXMgYW55KS5sb2NhdGlvbjtcbiAgICBkZWxldGUgKGdsb2JhbCBhcyBhbnkpLlhNTEh0dHBSZXF1ZXN0O1xuICAgIGdsb2JhbC5mZXRjaCA9IHJlYWxGZXRjaDtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJmZXRjaFwiLCAoKSA9PiB7XG4gICAgdGVzdChcImhhc2hlcyBVUkxTZWFyY2hQYXJhbXMgdmlhIHRvU3RyaW5nKCksIG5vdCBKU09OLnN0cmluZ2lmeVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHsgYTogXCIxXCIsIGI6IFwiMlwiIH0pO1xuXG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBwYXJhbXMsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoXG4gICAgICAgIHNoYTI1NihwYXJhbXMudG9TdHJpbmcoKSksXG4gICAgICApO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLm5vdC50b0JlKHNoYTI1NihcInt9XCIpKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJoYXNoZXMgYSBwbGFpbiBzdHJpbmcgYm9keVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBcInJhdyB0ZXh0IGJvZHlcIixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShzaGEyNTYoXCJyYXcgdGV4dCBib2R5XCIpKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJoYXNoZXMgYSBGb3JtRGF0YSBib2R5IG92ZXIgaXRzIGV4YWN0IGVuY29kZWQgYnl0ZXMgYW5kIHNldHMgY29udGVudC10eXBlXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICBmb3JtRGF0YS5hcHBlbmQoXCJmaWVsZFwiLCBcInZhbHVlXCIpO1xuICAgICAgZm9ybURhdGEuYXBwZW5kKFxuICAgICAgICBcImZpbGVcIixcbiAgICAgICAgbmV3IEJsb2IoW1wiZmlsZSBjb250ZW50c1wiXSwgeyB0eXBlOiBcInRleHQvcGxhaW5cIiB9KSxcbiAgICAgICAgXCJmaWxlLnR4dFwiLFxuICAgICAgKTtcblxuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgYm9keTogZm9ybURhdGEsXG4gICAgICB9KTtcblxuICAgICAgLy8gdGhlIGJvZHkgc2VudCB0byB0aGUgcmVhbCBmZXRjaCBtdXN0IGJlIHRoZSByZS1lbmNvZGVkIGJ5dGVzLCBub3QgdGhlIG9yaWdpbmFsIEZvcm1EYXRhXG4gICAgICBjb25zdCBzZW50Qnl0ZXMgPSBjYXB0dXJlZEluaXQhLmJvZHkgYXMgVWludDhBcnJheTtcbiAgICAgIGV4cGVjdChzZW50Qnl0ZXMpLnRvQmVJbnN0YW5jZU9mKFVpbnQ4QXJyYXkpO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBjb25zdCBjb250ZW50VHlwZSA9IGhlYWRlcnMuZ2V0KFwiY29udGVudC10eXBlXCIpITtcbiAgICAgIGV4cGVjdChjb250ZW50VHlwZSkudG9NYXRjaCgvXm11bHRpcGFydFxcL2Zvcm0tZGF0YTsgYm91bmRhcnk9Lyk7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShzaGEyNTYoc2VudEJ5dGVzKSk7XG5cbiAgICAgIC8vIHRoZSBoYXNoZWQvc2VudCBieXRlcyBtdXN0IHJvdW5kLXRyaXAgYmFjayB0byB0aGUgb3JpZ2luYWwgZmllbGRzXG4gICAgICBjb25zdCByb3VuZFRyaXBwZWQgPSBhd2FpdCBuZXcgUmVzcG9uc2Uoc2VudEJ5dGVzLCB7XG4gICAgICAgIGhlYWRlcnM6IHsgXCJjb250ZW50LXR5cGVcIjogY29udGVudFR5cGUgfSxcbiAgICAgIH0pLmZvcm1EYXRhKCk7XG4gICAgICBleHBlY3Qocm91bmRUcmlwcGVkLmdldChcImZpZWxkXCIpKS50b0JlKFwidmFsdWVcIik7XG4gICAgICBjb25zdCBmaWxlID0gcm91bmRUcmlwcGVkLmdldChcImZpbGVcIikgYXMgRmlsZTtcbiAgICAgIGV4cGVjdChmaWxlLm5hbWUpLnRvQmUoXCJmaWxlLnR4dFwiKTtcbiAgICAgIGV4cGVjdChhd2FpdCBmaWxlLnRleHQoKSkudG9CZShcImZpbGUgY29udGVudHNcIik7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFzaGVzIGEgQmxvYiBib2R5IG92ZXIgaXRzIHJhdyBieXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW1wiYmxvYiBjb250ZW50c1wiXSwgeyB0eXBlOiBcInRleHQvcGxhaW5cIiB9KTtcblxuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgYm9keTogYmxvYixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShcbiAgICAgICAgc2hhMjU2KGF3YWl0IGJsb2IuYXJyYXlCdWZmZXIoKSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImhhc2hlcyBhbiBBcnJheUJ1ZmZlciBib2R5IG92ZXIgaXRzIHJhdyBieXRlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWZmZXIgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoXCJhcnJheSBidWZmZXIgY29udGVudHNcIikuYnVmZmVyO1xuXG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUFVUXCIsXG4gICAgICAgIGJvZHk6IGJ1ZmZlcixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgICBleHBlY3QoaGVhZGVycy5nZXQoXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiKSkudG9CZShzaGEyNTYoYnVmZmVyKSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFzaGVzIGEgdHlwZWQgYXJyYXkgYm9keSBvdmVyIHRoZSBieXRlcyBpdCB2aWV3c1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBieXRlcyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShcInh4dHlwZWQgYXJyYXkgY29udGVudHNcIik7XG4gICAgICBjb25zdCB2aWV3ID0gYnl0ZXMuc3ViYXJyYXkoMik7XG5cbiAgICAgIGF3YWl0IChnbG9iYWwgYXMgYW55KS53aW5kb3cuZmV0Y2goXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiLCB7XG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgIGJvZHk6IHZpZXcsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoXG4gICAgICAgIHNoYTI1NihcInR5cGVkIGFycmF5IGNvbnRlbnRzXCIpLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJ3cmFwcyBmZXRjaCBvbmNlIHdoZW4gYSBzZWNvbmQgcGF0Y2hlZCBjaHVuayBsb2FkcyBpbiB0aGUgc2FtZSBzY29wZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBFdmVyeSBlbnRyeXBvaW50IGNodW5rIGNhcnJpZXMgYSBjb3B5LiBXcmFwcGVkIHR3aWNlLCB0aGUgb3V0ZXIgd3JhcHBlclxuICAgICAgLy8gcmUtZW5jb2RlZCBhIEZvcm1EYXRhIGJvZHkgdG8gYnl0ZXMgYW5kIHRoZSBpbm5lciBvbmUgb3Zlcndyb3RlIHRoZVxuICAgICAgLy8gcmlnaHQgaGFzaCB3aXRoIG9uZSBvZiB0aG9zZSBieXRlcyBhcyBKU09OLlxuICAgICAgY29uc3QgcGF0Y2hlZE9uY2UgPSAoZ2xvYmFsIGFzIGFueSkuZmV0Y2g7XG4gICAgICBjb25zdCBwYXRjaGVkWGhyID0gKGdsb2JhbCBhcyBhbnkpLlhNTEh0dHBSZXF1ZXN0O1xuICAgICAgamVzdC5yZXNldE1vZHVsZXMoKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzIC0tIHRoZSBzZWNvbmQgY2h1bmsncyBjb3B5XG4gICAgICByZXF1aXJlKFwiLi9wYXRjaC1mZXRjaC5qc1wiKTtcbiAgICAgIGV4cGVjdCgoZ2xvYmFsIGFzIGFueSkuZmV0Y2gpLnRvQmUocGF0Y2hlZE9uY2UpO1xuICAgICAgZXhwZWN0KChnbG9iYWwgYXMgYW55KS5YTUxIdHRwUmVxdWVzdCkudG9CZShwYXRjaGVkWGhyKTtcblxuICAgICAgY29uc3QgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgIGZvcm1EYXRhLmFwcGVuZChcImZpZWxkXCIsIFwidmFsdWVcIik7XG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBmb3JtRGF0YSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3Qob3JpZ2luYWxGZXRjaCkudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoXG4gICAgICAgIHNoYTI1NihjYXB0dXJlZEluaXQhLmJvZHkgYXMgVWludDhBcnJheSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImhhc2hlcyBhbiBlbXB0eSBieXRlIGFycmF5IHdoZW4gbm8gYm9keSBpcyBwcmVzZW50XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IChnbG9iYWwgYXMgYW55KS53aW5kb3cuZmV0Y2goXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiLCB7XG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoXG4gICAgICAgIHNoYTI1NihuZXcgVWludDhBcnJheSgwKSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImhhc2hlcyBhIFJlcXVlc3QncyBvd24gYm9keSB3aGVuIGluaXQgaXMgb21pdHRlZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbmV3IFJlcXVlc3QoXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiLCB7XG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgIGJvZHk6IFwicmVxdWVzdCBib2R5XCIsXG4gICAgICAgIGhlYWRlcnM6IHsgXCJjb250ZW50LXR5cGVcIjogXCJ0ZXh0L3BsYWluXCIgfSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKHJlcXVlc3QpO1xuXG4gICAgICBjb25zdCBbc2VudElucHV0XSA9IG9yaWdpbmFsRmV0Y2gubW9jay5jYWxsc1swXTtcbiAgICAgIGV4cGVjdChzZW50SW5wdXQpLnRvQmUocmVxdWVzdCk7XG4gICAgICAvLyBUaGUgYm9keSB3YXMgcmVhZCBmcm9tIGEgY2xvbmUsIHNvIHRoZSByZXF1ZXN0IHN0aWxsIGhhcyBpdCB0byBzZW5kLlxuICAgICAgZXhwZWN0KGF3YWl0IChzZW50SW5wdXQgYXMgUmVxdWVzdCkudGV4dCgpKS50b0JlKFwicmVxdWVzdCBib2R5XCIpO1xuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoc2hhMjU2KFwicmVxdWVzdCBib2R5XCIpKTtcbiAgICAgIC8vIGBpbml0LmhlYWRlcnNgIHJlcGxhY2VzIHRoZSByZXF1ZXN0J3Mgb3duLCBzbyB0aGV5IG11c3QgY2Fycnkgb3Zlci5cbiAgICAgIGV4cGVjdChoZWFkZXJzLmdldChcImNvbnRlbnQtdHlwZVwiKSkudG9CZShcInRleHQvcGxhaW5cIik7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFzaGVzIGluaXQncyBib2R5IG92ZXIgYSBSZXF1ZXN0J3Mgb3duIHdoZW4gYm90aCBhcmUgc2V0XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBuZXcgUmVxdWVzdChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgYm9keTogXCJyZXF1ZXN0IGJvZHlcIixcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKHJlcXVlc3QsIHsgYm9keTogXCJpbml0IGJvZHlcIiB9KTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IGNhcHR1cmVkSW5pdCEuaGVhZGVycyBhcyBIZWFkZXJzO1xuICAgICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoc2hhMjU2KFwiaW5pdCBib2R5XCIpKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJwYXNzZXMgYSBHRVQgUmVxdWVzdCB0aHJvdWdoIHdpdGhvdXQgaGFzaGluZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbmV3IFJlcXVlc3QoXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcblxuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChyZXF1ZXN0KTtcblxuICAgICAgZXhwZWN0KG9yaWdpbmFsRmV0Y2gpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHJlcXVlc3QsIHVuZGVmaW5lZCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwicGFzc2VzIHRocm91Z2ggdW50b3VjaGVkIHdoZW4gaW5pdCBpcyBvbWl0dGVkXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IChnbG9iYWwgYXMgYW55KS53aW5kb3cuZmV0Y2goXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcblxuICAgICAgZXhwZWN0KG9yaWdpbmFsRmV0Y2gpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsXG4gICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwicGFzc2VzIHRocm91Z2ggd2l0aG91dCBoYXNoaW5nIGZvciBub24tUFVUL1BPU1QgbWV0aG9kc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCAoZ2xvYmFsIGFzIGFueSkud2luZG93LmZldGNoKFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICAgIGJvZHk6IFwic2hvdWxkIG5vdCBiZSBoYXNoZWRcIixcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QoY2FwdHVyZWRJbml0IS5oZWFkZXJzKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwicGFzc2VzIHRocm91Z2ggd2l0aG91dCBoYXNoaW5nIGZvciBjcm9zcy1vcmlnaW4gcmVxdWVzdHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5mZXRjaChcImh0dHBzOi8vb3RoZXItb3JpZ2luLmNvbS9hcGlcIiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBcInNob3VsZCBub3QgYmUgaGFzaGVkXCIsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KGNhcHR1cmVkSW5pdCEuaGVhZGVycykudG9CZVVuZGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIlhNTEh0dHBSZXF1ZXN0XCIsICgpID0+IHtcbiAgICB0ZXN0KFwiaGFzaGVzIFVSTFNlYXJjaFBhcmFtcyB2aWEgdG9TdHJpbmcoKSwgbm90IEpTT04uc3RyaW5naWZ5XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoeyBhOiBcIjFcIiwgYjogXCIyXCIgfSk7XG4gICAgICBjb25zdCBzZXRSZXF1ZXN0SGVhZGVyID0gamVzdC5mbigpO1xuXG4gICAgICBjb25zdCB4aHIgPSBuZXcgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIgPSBzZXRSZXF1ZXN0SGVhZGVyO1xuICAgICAgeGhyLm9wZW4oXCJQT1NUXCIsIFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9hcGlcIik7XG4gICAgICBhd2FpdCB4aHIuc2VuZChwYXJhbXMpO1xuXG4gICAgICBleHBlY3Qoc2V0UmVxdWVzdEhlYWRlcikudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIFwieC1hbXotY29udGVudC1zaGEyNTZcIixcbiAgICAgICAgc2hhMjU2KHBhcmFtcy50b1N0cmluZygpKSxcbiAgICAgICk7XG4gICAgICBleHBlY3Qoc2V0UmVxdWVzdEhlYWRlcikubm90LnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBcIngtYW16LWNvbnRlbnQtc2hhMjU2XCIsXG4gICAgICAgIHNoYTI1NihcInt9XCIpLFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJoYXNoZXMgYSBwbGFpbiBzdHJpbmcgYm9keVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXRSZXF1ZXN0SGVhZGVyID0gamVzdC5mbigpO1xuXG4gICAgICBjb25zdCB4aHIgPSBuZXcgKGdsb2JhbCBhcyBhbnkpLndpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIgPSBzZXRSZXF1ZXN0SGVhZGVyO1xuICAgICAgeGhyLm9wZW4oXCJQVVRcIiwgXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcbiAgICAgIGF3YWl0IHhoci5zZW5kKFwicmF3IHRleHQgYm9keVwiKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICBcIngtYW16LWNvbnRlbnQtc2hhMjU2XCIsXG4gICAgICAgIHNoYTI1NihcInJhdyB0ZXh0IGJvZHlcIiksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImRvZXMgbm90IGhhc2ggZm9yIG5vbi1QVVQvUE9TVCBtZXRob2RzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNldFJlcXVlc3RIZWFkZXIgPSBqZXN0LmZuKCk7XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyAoZ2xvYmFsIGFzIGFueSkud2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlciA9IHNldFJlcXVlc3RIZWFkZXI7XG4gICAgICB4aHIub3BlbihcIkdFVFwiLCBcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIpO1xuICAgICAgYXdhaXQgeGhyLnNlbmQoXCJzaG91bGQgbm90IGJlIGhhc2hlZFwiKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiZG9lcyBub3QgaGFzaCBmb3IgY3Jvc3Mtb3JpZ2luIHJlcXVlc3RzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNldFJlcXVlc3RIZWFkZXIgPSBqZXN0LmZuKCk7XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyAoZ2xvYmFsIGFzIGFueSkud2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlciA9IHNldFJlcXVlc3RIZWFkZXI7XG4gICAgICB4aHIub3BlbihcIlBPU1RcIiwgXCJodHRwczovL290aGVyLW9yaWdpbi5jb20vYXBpXCIpO1xuICAgICAgYXdhaXQgeGhyLnNlbmQoXCJzaG91bGQgbm90IGJlIGhhc2hlZFwiKTtcblxuICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFzaGVzIHRoZSBieXRlcyBvZiBhIHR5cGVkLWFycmF5IG9yIEJsb2IgYm9keSwgbm90IHRoZWlyIEpTT05cIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShbMSwgMiwgMywgMjUwXSk7XG4gICAgICBmb3IgKGNvbnN0IGJvZHkgb2YgW2J5dGVzLCBuZXcgQmxvYihbYnl0ZXNdKV0pIHtcbiAgICAgICAgY29uc3Qgc2V0UmVxdWVzdEhlYWRlciA9IGplc3QuZm4oKTtcbiAgICAgICAgY29uc3QgeGhyID0gbmV3IChnbG9iYWwgYXMgYW55KS53aW5kb3cuWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIgPSBzZXRSZXF1ZXN0SGVhZGVyO1xuICAgICAgICB4aHIub3BlbihcIlBPU1RcIiwgXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcbiAgICAgICAgYXdhaXQgeGhyLnNlbmQoYm9keSk7XG5cbiAgICAgICAgZXhwZWN0KHNldFJlcXVlc3RIZWFkZXIpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICAgIFwieC1hbXotY29udGVudC1zaGEyNTZcIixcbiAgICAgICAgICBzaGEyNTYoYnl0ZXMpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGVzdChcInNlbmRzIGEgRm9ybURhdGEgYm9keSBhcyB0aGUgZW5jb2RpbmcgaXQgaGFzaGVkLCB3aXRoIGl0cyBib3VuZGFyeVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZW5kID0gamVzdC5zcHlPbihGYWtlWE1MSHR0cFJlcXVlc3QucHJvdG90eXBlLCBcInNlbmRcIik7XG4gICAgICBjb25zdCBzZXRSZXF1ZXN0SGVhZGVyID0gamVzdC5mbigpO1xuICAgICAgY29uc3QgZm9ybSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgZm9ybS5hcHBlbmQoXCJuYW1lXCIsIFwidmFsdWVcIik7XG4gICAgICBmb3JtLmFwcGVuZChcImZpbGVcIiwgbmV3IEJsb2IoW1wiZmlsZS1ieXRlc1wiXSksIFwiYS50eHRcIik7XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyAoZ2xvYmFsIGFzIGFueSkud2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlciA9IHNldFJlcXVlc3RIZWFkZXI7XG4gICAgICB4aHIub3BlbihcIlBPU1RcIiwgXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcbiAgICAgIGF3YWl0IHhoci5zZW5kKGZvcm0pO1xuXG4gICAgICBjb25zdCBzZW50ID0gc2VuZC5tb2NrLmNhbGxzWzBdWzBdIGFzIFVpbnQ4QXJyYXk7XG4gICAgICBleHBlY3Qoc2VudCkudG9CZUluc3RhbmNlT2YoVWludDhBcnJheSk7XG4gICAgICBleHBlY3Qoc2V0UmVxdWVzdEhlYWRlcikudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIFwieC1hbXotY29udGVudC1zaGEyNTZcIixcbiAgICAgICAgc2hhMjU2KHNlbnQpLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gc2V0UmVxdWVzdEhlYWRlci5tb2NrLmNhbGxzLmZpbmQoXG4gICAgICAgIChbbmFtZV0pID0+IG5hbWUgPT09IFwiY29udGVudC10eXBlXCIsXG4gICAgICApPy5bMV07XG4gICAgICBleHBlY3QoY29udGVudFR5cGUpLnRvTWF0Y2goL15tdWx0aXBhcnRcXC9mb3JtLWRhdGE7IGJvdW5kYXJ5PS8pO1xuICAgICAgZXhwZWN0KEJ1ZmZlci5mcm9tKHNlbnQpLnRvU3RyaW5nKCkpLnRvQ29udGFpbihcbiAgICAgICAgY29udGVudFR5cGUuc3BsaXQoXCJib3VuZGFyeT1cIilbMV0sXG4gICAgICApO1xuICAgICAgc2VuZC5tb2NrUmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImRvZXMgbm90IGhhc2ggd2hlbiB0aGVyZSBpcyBubyBib2R5XCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNldFJlcXVlc3RIZWFkZXIgPSBqZXN0LmZuKCk7XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyAoZ2xvYmFsIGFzIGFueSkud2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlciA9IHNldFJlcXVlc3RIZWFkZXI7XG4gICAgICB4aHIub3BlbihcIlBPU1RcIiwgXCJodHRwczovL2V4YW1wbGUuY29tL2FwaVwiKTtcbiAgICAgIGF3YWl0IHhoci5zZW5kKCk7XG5cbiAgICAgIGV4cGVjdChzZXRSZXF1ZXN0SGVhZGVyKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG4vKipcbiAqIFR1cmJvcGFjaydzIHdlYi13b3JrZXIgYm9vdHN0cmFwIGlzIGBzdGF0aWMvY2h1bmtzL3R1cmJvcGFjay13b3JrZXItKi5qc2AsXG4gKiB3aGljaCBgcGF0Y2hGZXRjaEluQ2xpZW50SnNgJ3MgYHR1cmJvcGFjay1gIHNlbGVjdG9yIG1hdGNoZXMg4oCUIHNvIHRoaXMgZmlsZSBpc1xuICogcHJlcGVuZGVkIHRvIGEgc2NyaXB0IHRoYXQgcnVucyBvZmYgdGhlIG1haW4gdGhyZWFkLiBSZWFkaW5nIGB3aW5kb3dgIHRoZXJlXG4gKiB0aHJldyBiZWZvcmUgdGhlIHdvcmtlcidzIG93biBtb2R1bGUgY291bGQgcnVuLCB3aGljaCB0b29rIG91dCBldmVyeVxuICogYG5ldyBXb3JrZXIobmV3IFVSTCjigKYpKWAgYXBwIChgd29ya2VyLW1vZHVsZS11cmxgLCBgd29ya2VyLXJlbGF5LWNvbXBpbGVyYCkuXG4gKi9cbmRlc2NyaWJlKFwicGF0Y2gtZmV0Y2ggaW4gYSB3b3JrZXIgc2NvcGVcIiwgKCkgPT4ge1xuICBsZXQgb3JpZ2luYWxGZXRjaDogamVzdC5Nb2NrO1xuICBsZXQgY2FwdHVyZWRJbml0OiBSZXF1ZXN0SW5pdCB8IHVuZGVmaW5lZDtcbiAgY29uc3QgcmVhbEZldGNoID0gZ2xvYmFsLmZldGNoO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGplc3QucmVzZXRNb2R1bGVzKCk7XG4gICAgY2FwdHVyZWRJbml0ID0gdW5kZWZpbmVkO1xuICAgIG9yaWdpbmFsRmV0Y2ggPSBqZXN0LmZuKChfaW5wdXQ6IHVua25vd24sIGluaXQ/OiBSZXF1ZXN0SW5pdCkgPT4ge1xuICAgICAgY2FwdHVyZWRJbml0ID0gaW5pdDtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IFJlc3BvbnNlKFwib2tcIikpO1xuICAgIH0pO1xuICAgIChnbG9iYWwgYXMgYW55KS5mZXRjaCA9IG9yaWdpbmFsRmV0Y2g7XG4gICAgLy8gTm8gYHdpbmRvd2AsIGFuZCBubyBgWE1MSHR0cFJlcXVlc3RgOiB0aGUgbmFycm93ZXN0IHNjb3BlIHRoZSBwYXRjaCBjYW5cbiAgICAvLyBsYW5kIGluLlxuICAgIGluc3RhbGxTY29wZSh7IHdpdGhXaW5kb3c6IGZhbHNlLCB3aXRoWGhyOiBmYWxzZSB9KTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBkZWxldGUgKGdsb2JhbCBhcyBhbnkpLndpbmRvdztcbiAgICBkZWxldGUgKGdsb2JhbCBhcyBhbnkpLmxvY2F0aW9uO1xuICAgIGdsb2JhbC5mZXRjaCA9IHJlYWxGZXRjaDtcbiAgfSk7XG5cbiAgdGVzdChcImxvYWRzIHdpdGhvdXQgYSB3aW5kb3cgYW5kIHN0aWxsIHNpZ25zIGEgc2FtZS1vcmlnaW4gUE9TVFwiLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzIC0tIHRoZSBwb2ludCBvZiB0aGUgdGVzdCBpcyB0aGF0IHJlcXVpcmluZyBpdCBkb2VzIG5vdCB0aHJvd1xuICAgICAgcmVxdWlyZShcIi4vcGF0Y2gtZmV0Y2guanNcIik7XG4gICAgfSkubm90LnRvVGhyb3coKTtcblxuICAgIGF3YWl0IGdsb2JhbC5mZXRjaChcImh0dHBzOi8vZXhhbXBsZS5jb20vYXBpXCIsIHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBib2R5OiBcIndvcmtlciBib2R5XCIsXG4gICAgfSk7XG5cbiAgICBjb25zdCBoZWFkZXJzID0gY2FwdHVyZWRJbml0IS5oZWFkZXJzIGFzIEhlYWRlcnM7XG4gICAgZXhwZWN0KGhlYWRlcnMuZ2V0KFwieC1hbXotY29udGVudC1zaGEyNTZcIikpLnRvQmUoc2hhMjU2KFwid29ya2VyIGJvZHlcIikpO1xuICB9KTtcblxuICB0ZXN0KFwibGVhdmVzIFhNTEh0dHBSZXF1ZXN0IGFsb25lIHdoZW4gdGhlIHNjb3BlIGhhcyBub25lXCIsICgpID0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAtLSByZS1leGVjdXRlZCBhZ2FpbnN0IHRoaXMgc2NvcGVcbiAgICByZXF1aXJlKFwiLi9wYXRjaC1mZXRjaC5qc1wiKTtcblxuICAgIGV4cGVjdCgoZ2xvYmFsIGFzIGFueSkuWE1MSHR0cFJlcXVlc3QpLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG59KTtcbiJdfQ==
@@ -1,4 +1,7 @@
1
1
  # ~~ Generated by cdk-nextjs ~~
2
+ # cdk-nextjs rewrites any Dockerfile carrying the line above, so that an
3
+ # upgrade does not leave a stale one behind. To own this file yourself, delete
4
+ # that line and cdk-nextjs will leave the rest of it alone.
2
5
  # Modified from: https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
3
6
 
4
7
  # Production image, copy all the files and run next
@@ -14,13 +17,17 @@ ENV NODE_ENV=production
14
17
  RUN addgroup --system --gid 1001 nodejs
15
18
  RUN adduser --system --uid 1001 nextjs
16
19
 
17
- ARG RELATIVE_PATH_TO_PACKAGE
18
- # Copy from local build output instead of builder image
19
- COPY --chown=nextjs:nodejs .next/standalone ./
20
- # static assets needed b/c we don't have cloudfront to serve them from s3
21
- COPY --chown=nextjs:nodejs .next/static ./$RELATIVE_PATH_TO_PACKAGE/.next/static
22
- # Copy public directory for image optimization (Next.js needs source images)
23
- COPY --chown=nextjs:nodejs public ./$RELATIVE_PATH_TO_PACKAGE/public
20
+ ARG RELATIVE_PROJECT_DIR
21
+ # The deployment root cdk-nextjs staged during `next build`: the traced assets of
22
+ # every built output, keyed by repo-root-relative path, plus cdk-nextjs's own
23
+ # request-handling server under cdk-nextjs-runtime/. Replaces `.next/standalone`.
24
+ COPY --chown=nextjs:nodejs .next/cdk-nextjs-adapter/app ./
25
+ # There is no CloudFront in front of this deployment type, so the server answers
26
+ # every static request itself: the manifest lists `.next/static`, the runtime
27
+ # lists `public` when it starts, and it serves both off disk. (Image optimization
28
+ # reads its sources from here too, through the runtime's in-process routing.)
29
+ COPY --chown=nextjs:nodejs .next/static ./$RELATIVE_PROJECT_DIR/.next/static
30
+ COPY --chown=nextjs:nodejs public ./$RELATIVE_PROJECT_DIR/public
24
31
 
25
32
  USER nextjs
26
33
 
@@ -28,8 +35,8 @@ EXPOSE 3000
28
35
 
29
36
  ENV PORT=3000
30
37
 
31
- # server.js is created by next build from the standalone output
32
- # https://nextjs.org/docs/pages/api-reference/next-config-js/output
38
+ # cdk-nextjs's own server, staged above. It invokes the entrypoints `next build`
39
+ # produced in-process; there is no `next start` and no server.js.
33
40
  # CMD will be overwritten by ECS Task Definition
34
41
  ENV HOSTNAME="0.0.0.0"
35
- CMD ["node" "server.js"]
42
+ CMD ["node", "cdk-nextjs-runtime/server.mjs"]
@@ -11,8 +11,12 @@ export interface NextjsCacheProps {
11
11
  readonly buildId: string;
12
12
  /**
13
13
  * Bring your own S3 bucket for cache storage. When provided, cdk-nextjs
14
- * will skip creating a new bucket. Cache objects are prefixed with `buildId`
15
- * so multiple deployments can safely share one bucket.
14
+ * will skip creating a new bucket.
15
+ *
16
+ * The bucket must be dedicated to this one deployment. Don't share it with
17
+ * another deployment (another branch, stage, or app): every deploy's
18
+ * post-deploy step deletes every object under a top-level prefix other than
19
+ * the current `buildId/`, which includes every other deployment's cache.
16
20
  */
17
21
  readonly cacheBucket?: IBucket;
18
22
  /**
@@ -24,8 +28,16 @@ export interface NextjsCacheProps {
24
28
  /**
25
29
  * Bring your own DynamoDB table for revalidation metadata. When provided,
26
30
  * cdk-nextjs will skip creating a new table. The table must have `pk` (String)
27
- * as partition key and `sk` (String) as sort key. Entries are partitioned by
28
- * `buildId` so multiple deployments can safely share one table.
31
+ * as partition key and `sk` (String) as sort key.
32
+ * Enabling TTL on its `ttl` attribute is recommended: each tag revalidation
33
+ * writes a revalidation log row that expires through it after 15 minutes.
34
+ * Without TTL those rows are kept until a deploy replaces their build, whose
35
+ * post-deploy step deletes them.
36
+ *
37
+ * The table must be dedicated to this one deployment. Don't share it with
38
+ * another deployment (another branch, stage, or app): every deploy's
39
+ * post-deploy step deletes the entries of the build it last recorded in the
40
+ * table, which with a shared table is another deployment's live build.
29
41
  */
30
42
  readonly revalidationTable?: ITableV2;
31
43
  }
@@ -46,10 +58,76 @@ export declare class NextjsCache extends Construct {
46
58
  /**
47
59
  * Creates DynamoDB table for revalidation metadata
48
60
  * Schema: pk (buildId or "METADATA"), sk (tag#cacheKey or "CURRENT_BUILD"), createdAt, revalidatedAt
61
+ *
62
+ * Also the `'use cache'` revalidation log (pk "<buildId>#log",
63
+ * sk "<epoch-ms>#<tag>"), whose rows expire through the `ttl` attribute.
49
64
  */
50
65
  private createRevalidationTable;
51
66
  /**
52
67
  * Deploy pre-built cache files from .next/cdk-nextjs-init-cache to S3
53
68
  */
54
69
  private createDeployment;
70
+ /**
71
+ * `/tmp` and memory for `BucketDeployment`'s unzip Lambda, scaled to the init
72
+ * cache it has to unpack.
73
+ *
74
+ * That Lambda downloads the asset zip into `/tmp` and then extracts it
75
+ * alongside, so it needs room for both at once. CDK defaults it to 512 MiB of
76
+ * ephemeral storage and 128 MB of memory — fine for a small app, and a hard
77
+ * failure for one whose prerendered payloads are large. A fixture with 60
78
+ * statically generated pages carrying ~1 MB of RSC each produced a 664 MiB
79
+ * seed directory and the handler died on
80
+ * `OSError: [Errno 28] No space left on device` inside `zip.extractall`.
81
+ * Worse, `cdk deploy --hotswap` invokes the custom resource directly with a
82
+ * placeholder response URL, so the `Status: FAILED` it sends goes nowhere: the
83
+ * CLI prints "Contents of AWS::S3::Bucket … hotswapped!", exits 0, and the app
84
+ * comes up serving a *partially* seeded cache. Every route whose entry did not
85
+ * make it is then a miss that re-renders — which, for a
86
+ * `cacheComponents: true` app, means a postponed shell where the prerender
87
+ * should have been.
88
+ *
89
+ * The zip's compressed size is not known at synth time (CDK archives the asset
90
+ * later), so the worst case — an incompressible payload — is what gets
91
+ * budgeted: twice the directory, plus headroom, rounded up to a
92
+ * {@link storageStep}. Memory is only raised past
93
+ * CDK's default for caches big enough that 128 MB's slice of a vCPU would make
94
+ * the unzip and upload race the custom resource's 15-minute timeout; small
95
+ * apps keep the cheaper default and their existing template.
96
+ *
97
+ * Above the 10 GiB ephemeral-storage ceiling there is nothing left to ask for,
98
+ * so this warns and lets the deployment fail loudly rather than pretend.
99
+ * `overrides.bucketDeploymentProps` wins over everything here, including
100
+ * `useEfs: true`, which is the supported way out.
101
+ */
102
+ private sizeDeploymentLambda;
103
+ /**
104
+ * Stage the init cache under a `buildId` directory, so that the objects land
105
+ * at `<buildId>/<key>` without a `destinationKeyPrefix`.
106
+ *
107
+ * The keys have to carry the build ID — that is how the runtime cache handler
108
+ * and the post-deploy pruner namespace one deployment's entries from the next
109
+ * (`src/adapter/s3-cache-handler.ts`). Asking `BucketDeployment` for it, as
110
+ * this used to, is what costs: it unconditionally tags the *destination
111
+ * bucket* with `aws-cdk:cr-owned:<destinationKeyPrefix>:<hash>`, so a prefix
112
+ * that changes per build makes the bucket's `Tags` change per build.
113
+ * `AWS::S3::Bucket` `Tags` are not hotswappable, so `cdk deploy
114
+ * --hotswap-fallback` rejected the diff and fell back to a full CloudFormation
115
+ * deployment every single time — measured at 19 of 22 deploys in one harness
116
+ * run, ~110s each against a ~52s hotswap.
117
+ *
118
+ * Putting the build ID in the asset's own paths instead leaves the S3 keys
119
+ * byte-identical and the tag key constant (`aws-cdk:cr-owned:<hash>`, derived
120
+ * from the construct path). Nothing else read the prefix: `prune` is already
121
+ * `false`, and the two handler branches that do scope work to it — emptying
122
+ * the prefix on delete, and deleting the old prefix when the destination
123
+ * changes — are both gated on `retainOnDelete`, which `BucketDeployment`
124
+ * defaults to `true`.
125
+ *
126
+ * A copy rather than the directory itself because the build ID is only known
127
+ * *after* `next build`, so the adapter cannot write into a nested directory in
128
+ * the first place, and because `.next/cdk-nextjs-init-cache` has to stay where
129
+ * it is for the local cache handler to read it (`CDK_NEXTJS_INIT_CACHE_DIR`).
130
+ * CDK is about to read every byte of this to zip it regardless.
131
+ */
132
+ private createStagingDirectory;
55
133
  }