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
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.crc32 = crc32;
4
+ exports.zipDirectory = zipDirectory;
5
+ // Zip headers are bit fields.
6
+ /* eslint-disable no-bitwise */
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = require("node:path");
9
+ const node_zlib_1 = require("node:zlib");
10
+ /** `zlib.crc32` only exists from Node 20.15, and synth runs on the user's Node. */
11
+ const CRC_TABLE = Array.from({ length: 256 }, (_, n) => {
12
+ let c = n;
13
+ for (let k = 0; k < 8; k++)
14
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
15
+ return c >>> 0;
16
+ });
17
+ function crc32(data) {
18
+ let crc = 0xffffffff;
19
+ for (let i = 0; i < data.length; i++) {
20
+ crc = CRC_TABLE[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);
21
+ }
22
+ return (crc ^ 0xffffffff) >>> 0;
23
+ }
24
+ /**
25
+ * Zip `dir` with its symlinks stored *as* symlinks, which Lambda extracts as
26
+ * such. `Code.fromAsset(dir)` can't be used for a deployment root because
27
+ * `cdk-assets` dereferences them when it zips, and under pnpm that
28
+ * materializes a store package at its logical path while the siblings it
29
+ * resolves its own dependencies through stay behind in the store. Preserved,
30
+ * the links resolve the way they do in the workspace, and the way they do in
31
+ * a Containers image (`COPY` preserves them too).
32
+ *
33
+ * Deterministic — entries sorted, timestamps fixed, modes normalized — so the
34
+ * asset hash only changes when the contents do.
35
+ */
36
+ function zipDirectory(dir) {
37
+ const chunks = [];
38
+ const central = [];
39
+ let offset = 0;
40
+ let count = 0;
41
+ const add = (name, mode, content) => {
42
+ // Links stay stored: some extractors read a deflated link's target as-is.
43
+ const deflate = content.length > 0 && (mode & 0o170000) === 0o100000;
44
+ const data = deflate ? (0, node_zlib_1.deflateRawSync)(content) : content;
45
+ const nameBytes = Buffer.from(name, "utf8");
46
+ // Version 2.0; UTF-8 names; 1980-01-01 00:00; no extra fields.
47
+ const fields = Buffer.alloc(26);
48
+ fields.writeUInt16LE(20, 0);
49
+ fields.writeUInt16LE(0x0800, 2);
50
+ fields.writeUInt16LE(deflate ? 8 : 0, 4);
51
+ fields.writeUInt16LE(0, 6);
52
+ fields.writeUInt16LE(0x21, 8);
53
+ fields.writeUInt32LE(crc32(content), 10);
54
+ fields.writeUInt32LE(data.length, 14);
55
+ fields.writeUInt32LE(content.length, 18);
56
+ fields.writeUInt16LE(nameBytes.length, 22);
57
+ const local = Buffer.alloc(4);
58
+ local.writeUInt32LE(0x04034b50);
59
+ chunks.push(local, fields, nameBytes, data);
60
+ const entry = Buffer.alloc(46);
61
+ entry.writeUInt32LE(0x02014b50, 0);
62
+ // Made by Unix, so extractors honor the mode in the external attributes.
63
+ entry.writeUInt16LE(0x0314, 4);
64
+ fields.copy(entry, 6);
65
+ entry.writeUInt32LE(((mode << 16) | (name.endsWith("/") ? 0x10 : 0)) >>> 0, 38);
66
+ entry.writeUInt32LE(offset, 42);
67
+ central.push(entry, nameBytes);
68
+ offset += 30 + nameBytes.length + data.length;
69
+ count++;
70
+ };
71
+ const walk = (relative) => {
72
+ // Code-unit order rather than `localeCompare`, which varies by locale.
73
+ const names = (0, node_fs_1.readdirSync)((0, node_path_1.join)(dir, relative)).sort();
74
+ for (const name of names) {
75
+ const path = (0, node_path_1.join)(dir, relative, name);
76
+ const key = relative ? `${relative}/${name}` : name;
77
+ const stats = (0, node_fs_1.lstatSync)(path);
78
+ if (stats.isSymbolicLink()) {
79
+ add(key, 0o120777, Buffer.from((0, node_fs_1.readlinkSync)(path), "utf8"));
80
+ }
81
+ else if (stats.isDirectory()) {
82
+ add(`${key}/`, 0o40755, Buffer.alloc(0));
83
+ walk(key);
84
+ }
85
+ else {
86
+ add(key, stats.mode & 0o111 ? 0o100755 : 0o100644, (0, node_fs_1.readFileSync)(path));
87
+ }
88
+ }
89
+ };
90
+ walk("");
91
+ // Zip64 only for the entry count: a pnpm root reaches 65,535 files,
92
+ // directories and links well inside Lambda's 250 MB unzipped cap, but that
93
+ // cap keeps every size and offset inside 32 bits.
94
+ const centralSize = central.reduce((sum, chunk) => sum + chunk.length, 0);
95
+ const zip64 = [];
96
+ if (count > 0xffff) {
97
+ const record = Buffer.alloc(56);
98
+ record.writeUInt32LE(0x06064b50, 0);
99
+ record.writeBigUInt64LE(BigInt(44), 4);
100
+ record.writeUInt16LE(0x032d, 12);
101
+ record.writeUInt16LE(45, 14);
102
+ record.writeBigUInt64LE(BigInt(count), 24);
103
+ record.writeBigUInt64LE(BigInt(count), 32);
104
+ record.writeBigUInt64LE(BigInt(centralSize), 40);
105
+ record.writeBigUInt64LE(BigInt(offset), 48);
106
+ const locator = Buffer.alloc(20);
107
+ locator.writeUInt32LE(0x07064b50, 0);
108
+ locator.writeBigUInt64LE(BigInt(offset + centralSize), 8);
109
+ locator.writeUInt32LE(1, 16);
110
+ zip64.push(record, locator);
111
+ }
112
+ const end = Buffer.alloc(22);
113
+ end.writeUInt32LE(0x06054b50, 0);
114
+ // 0xffff defers to the Zip64 record.
115
+ end.writeUInt16LE(Math.min(count, 0xffff), 8);
116
+ end.writeUInt16LE(Math.min(count, 0xffff), 10);
117
+ end.writeUInt32LE(centralSize, 12);
118
+ end.writeUInt32LE(offset, 16);
119
+ return Buffer.concat([...chunks, ...central, ...zip64, end]);
120
+ }
121
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemlwLWRpcmVjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy96aXAtZGlyZWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBYUEsc0JBTUM7QUFjRCxvQ0EyRkM7QUE1SEQsOEJBQThCO0FBQzlCLCtCQUErQjtBQUMvQixxQ0FBNkU7QUFDN0UseUNBQWlDO0FBQ2pDLHlDQUEyQztBQUUzQyxtRkFBbUY7QUFDbkYsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNyRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRTtRQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDekUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2pCLENBQUMsQ0FBQyxDQUFDO0FBRUgsU0FBZ0IsS0FBSyxDQUFDLElBQVk7SUFDaEMsSUFBSSxHQUFHLEdBQUcsVUFBVSxDQUFDO0lBQ3JCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDckMsR0FBRyxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsR0FBRyxVQUFVLENBQUMsS0FB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RUFBRSxFQUFFLENBQUMsQ0FBQztRQUM1QyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzFELE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzdCLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFDRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdCLEdBQUcsQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pDLHFDQUFxQztJQUNyQyxHQUFHLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlDLEdBQUcsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDL0MsR0FBRyxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDOUIsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxNQUFNLEVBQUUsR0FBRyxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUMvRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gWmlwIGhlYWRlcnMgYXJlIGJpdCBmaWVsZHMuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1iaXR3aXNlICovXG5pbXBvcnQgeyBsc3RhdFN5bmMsIHJlYWRkaXJTeW5jLCByZWFkRmlsZVN5bmMsIHJlYWRsaW5rU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgZGVmbGF0ZVJhd1N5bmMgfSBmcm9tIFwibm9kZTp6bGliXCI7XG5cbi8qKiBgemxpYi5jcmMzMmAgb25seSBleGlzdHMgZnJvbSBOb2RlIDIwLjE1LCBhbmQgc3ludGggcnVucyBvbiB0aGUgdXNlcidzIE5vZGUuICovXG5jb25zdCBDUkNfVEFCTEUgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiAyNTYgfSwgKF8sIG4pID0+IHtcbiAgbGV0IGMgPSBuO1xuICBmb3IgKGxldCBrID0gMDsgayA8IDg7IGsrKykgYyA9IGMgJiAxID8gMHhlZGI4ODMyMCBeIChjID4+PiAxKSA6IGMgPj4+IDE7XG4gIHJldHVybiBjID4+PiAwO1xufSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmMzMihkYXRhOiBCdWZmZXIpOiBudW1iZXIge1xuICBsZXQgY3JjID0gMHhmZmZmZmZmZjtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgY3JjID0gQ1JDX1RBQkxFWyhjcmMgXiBkYXRhW2ldKSAmIDB4ZmZdIF4gKGNyYyA+Pj4gOCk7XG4gIH1cbiAgcmV0dXJuIChjcmMgXiAweGZmZmZmZmZmKSA+Pj4gMDtcbn1cblxuLyoqXG4gKiBaaXAgYGRpcmAgd2l0aCBpdHMgc3ltbGlua3Mgc3RvcmVkICphcyogc3ltbGlua3MsIHdoaWNoIExhbWJkYSBleHRyYWN0cyBhc1xuICogc3VjaC4gYENvZGUuZnJvbUFzc2V0KGRpcilgIGNhbid0IGJlIHVzZWQgZm9yIGEgZGVwbG95bWVudCByb290IGJlY2F1c2VcbiAqIGBjZGstYXNzZXRzYCBkZXJlZmVyZW5jZXMgdGhlbSB3aGVuIGl0IHppcHMsIGFuZCB1bmRlciBwbnBtIHRoYXRcbiAqIG1hdGVyaWFsaXplcyBhIHN0b3JlIHBhY2thZ2UgYXQgaXRzIGxvZ2ljYWwgcGF0aCB3aGlsZSB0aGUgc2libGluZ3MgaXRcbiAqIHJlc29sdmVzIGl0cyBvd24gZGVwZW5kZW5jaWVzIHRocm91Z2ggc3RheSBiZWhpbmQgaW4gdGhlIHN0b3JlLiBQcmVzZXJ2ZWQsXG4gKiB0aGUgbGlua3MgcmVzb2x2ZSB0aGUgd2F5IHRoZXkgZG8gaW4gdGhlIHdvcmtzcGFjZSwgYW5kIHRoZSB3YXkgdGhleSBkbyBpblxuICogYSBDb250YWluZXJzIGltYWdlIChgQ09QWWAgcHJlc2VydmVzIHRoZW0gdG9vKS5cbiAqXG4gKiBEZXRlcm1pbmlzdGljIOKAlCBlbnRyaWVzIHNvcnRlZCwgdGltZXN0YW1wcyBmaXhlZCwgbW9kZXMgbm9ybWFsaXplZCDigJQgc28gdGhlXG4gKiBhc3NldCBoYXNoIG9ubHkgY2hhbmdlcyB3aGVuIHRoZSBjb250ZW50cyBkby5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHppcERpcmVjdG9yeShkaXI6IHN0cmluZyk6IEJ1ZmZlciB7XG4gIGNvbnN0IGNodW5rczogQnVmZmVyW10gPSBbXTtcbiAgY29uc3QgY2VudHJhbDogQnVmZmVyW10gPSBbXTtcbiAgbGV0IG9mZnNldCA9IDA7XG4gIGxldCBjb3VudCA9IDA7XG5cbiAgY29uc3QgYWRkID0gKG5hbWU6IHN0cmluZywgbW9kZTogbnVtYmVyLCBjb250ZW50OiBCdWZmZXIpID0+IHtcbiAgICAvLyBMaW5rcyBzdGF5IHN0b3JlZDogc29tZSBleHRyYWN0b3JzIHJlYWQgYSBkZWZsYXRlZCBsaW5rJ3MgdGFyZ2V0IGFzLWlzLlxuICAgIGNvbnN0IGRlZmxhdGUgPSBjb250ZW50Lmxlbmd0aCA+IDAgJiYgKG1vZGUgJiAwbzE3MDAwMCkgPT09IDBvMTAwMDAwO1xuICAgIGNvbnN0IGRhdGEgPSBkZWZsYXRlID8gZGVmbGF0ZVJhd1N5bmMoY29udGVudCkgOiBjb250ZW50O1xuICAgIGNvbnN0IG5hbWVCeXRlcyA9IEJ1ZmZlci5mcm9tKG5hbWUsIFwidXRmOFwiKTtcbiAgICAvLyBWZXJzaW9uIDIuMDsgVVRGLTggbmFtZXM7IDE5ODAtMDEtMDEgMDA6MDA7IG5vIGV4dHJhIGZpZWxkcy5cbiAgICBjb25zdCBmaWVsZHMgPSBCdWZmZXIuYWxsb2MoMjYpO1xuICAgIGZpZWxkcy53cml0ZVVJbnQxNkxFKDIwLCAwKTtcbiAgICBmaWVsZHMud3JpdGVVSW50MTZMRSgweDA4MDAsIDIpO1xuICAgIGZpZWxkcy53cml0ZVVJbnQxNkxFKGRlZmxhdGUgPyA4IDogMCwgNCk7XG4gICAgZmllbGRzLndyaXRlVUludDE2TEUoMCwgNik7XG4gICAgZmllbGRzLndyaXRlVUludDE2TEUoMHgyMSwgOCk7XG4gICAgZmllbGRzLndyaXRlVUludDMyTEUoY3JjMzIoY29udGVudCksIDEwKTtcbiAgICBmaWVsZHMud3JpdGVVSW50MzJMRShkYXRhLmxlbmd0aCwgMTQpO1xuICAgIGZpZWxkcy53cml0ZVVJbnQzMkxFKGNvbnRlbnQubGVuZ3RoLCAxOCk7XG4gICAgZmllbGRzLndyaXRlVUludDE2TEUobmFtZUJ5dGVzLmxlbmd0aCwgMjIpO1xuXG4gICAgY29uc3QgbG9jYWwgPSBCdWZmZXIuYWxsb2MoNCk7XG4gICAgbG9jYWwud3JpdGVVSW50MzJMRSgweDA0MDM0YjUwKTtcbiAgICBjaHVua3MucHVzaChsb2NhbCwgZmllbGRzLCBuYW1lQnl0ZXMsIGRhdGEpO1xuXG4gICAgY29uc3QgZW50cnkgPSBCdWZmZXIuYWxsb2MoNDYpO1xuICAgIGVudHJ5LndyaXRlVUludDMyTEUoMHgwMjAxNGI1MCwgMCk7XG4gICAgLy8gTWFkZSBieSBVbml4LCBzbyBleHRyYWN0b3JzIGhvbm9yIHRoZSBtb2RlIGluIHRoZSBleHRlcm5hbCBhdHRyaWJ1dGVzLlxuICAgIGVudHJ5LndyaXRlVUludDE2TEUoMHgwMzE0LCA0KTtcbiAgICBmaWVsZHMuY29weShlbnRyeSwgNik7XG4gICAgZW50cnkud3JpdGVVSW50MzJMRShcbiAgICAgICgobW9kZSA8PCAxNikgfCAobmFtZS5lbmRzV2l0aChcIi9cIikgPyAweDEwIDogMCkpID4+PiAwLFxuICAgICAgMzgsXG4gICAgKTtcbiAgICBlbnRyeS53cml0ZVVJbnQzMkxFKG9mZnNldCwgNDIpO1xuICAgIGNlbnRyYWwucHVzaChlbnRyeSwgbmFtZUJ5dGVzKTtcblxuICAgIG9mZnNldCArPSAzMCArIG5hbWVCeXRlcy5sZW5ndGggKyBkYXRhLmxlbmd0aDtcbiAgICBjb3VudCsrO1xuICB9O1xuXG4gIGNvbnN0IHdhbGsgPSAocmVsYXRpdmU6IHN0cmluZykgPT4ge1xuICAgIC8vIENvZGUtdW5pdCBvcmRlciByYXRoZXIgdGhhbiBgbG9jYWxlQ29tcGFyZWAsIHdoaWNoIHZhcmllcyBieSBsb2NhbGUuXG4gICAgY29uc3QgbmFtZXMgPSByZWFkZGlyU3luYyhqb2luKGRpciwgcmVsYXRpdmUpKS5zb3J0KCk7XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgICBjb25zdCBwYXRoID0gam9pbihkaXIsIHJlbGF0aXZlLCBuYW1lKTtcbiAgICAgIGNvbnN0IGtleSA9IHJlbGF0aXZlID8gYCR7cmVsYXRpdmV9LyR7bmFtZX1gIDogbmFtZTtcbiAgICAgIGNvbnN0IHN0YXRzID0gbHN0YXRTeW5jKHBhdGgpO1xuICAgICAgaWYgKHN0YXRzLmlzU3ltYm9saWNMaW5rKCkpIHtcbiAgICAgICAgYWRkKGtleSwgMG8xMjA3NzcsIEJ1ZmZlci5mcm9tKHJlYWRsaW5rU3luYyhwYXRoKSwgXCJ1dGY4XCIpKTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBhZGQoYCR7a2V5fS9gLCAwbzQwNzU1LCBCdWZmZXIuYWxsb2MoMCkpO1xuICAgICAgICB3YWxrKGtleSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhZGQoa2V5LCBzdGF0cy5tb2RlICYgMG8xMTEgPyAwbzEwMDc1NSA6IDBvMTAwNjQ0LCByZWFkRmlsZVN5bmMocGF0aCkpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgd2FsayhcIlwiKTtcblxuICAvLyBaaXA2NCBvbmx5IGZvciB0aGUgZW50cnkgY291bnQ6IGEgcG5wbSByb290IHJlYWNoZXMgNjUsNTM1IGZpbGVzLFxuICAvLyBkaXJlY3RvcmllcyBhbmQgbGlua3Mgd2VsbCBpbnNpZGUgTGFtYmRhJ3MgMjUwIE1CIHVuemlwcGVkIGNhcCwgYnV0IHRoYXRcbiAgLy8gY2FwIGtlZXBzIGV2ZXJ5IHNpemUgYW5kIG9mZnNldCBpbnNpZGUgMzIgYml0cy5cbiAgY29uc3QgY2VudHJhbFNpemUgPSBjZW50cmFsLnJlZHVjZSgoc3VtLCBjaHVuaykgPT4gc3VtICsgY2h1bmsubGVuZ3RoLCAwKTtcbiAgY29uc3QgemlwNjQ6IEJ1ZmZlcltdID0gW107XG4gIGlmIChjb3VudCA+IDB4ZmZmZikge1xuICAgIGNvbnN0IHJlY29yZCA9IEJ1ZmZlci5hbGxvYyg1Nik7XG4gICAgcmVjb3JkLndyaXRlVUludDMyTEUoMHgwNjA2NGI1MCwgMCk7XG4gICAgcmVjb3JkLndyaXRlQmlnVUludDY0TEUoQmlnSW50KDQ0KSwgNCk7XG4gICAgcmVjb3JkLndyaXRlVUludDE2TEUoMHgwMzJkLCAxMik7XG4gICAgcmVjb3JkLndyaXRlVUludDE2TEUoNDUsIDE0KTtcbiAgICByZWNvcmQud3JpdGVCaWdVSW50NjRMRShCaWdJbnQoY291bnQpLCAyNCk7XG4gICAgcmVjb3JkLndyaXRlQmlnVUludDY0TEUoQmlnSW50KGNvdW50KSwgMzIpO1xuICAgIHJlY29yZC53cml0ZUJpZ1VJbnQ2NExFKEJpZ0ludChjZW50cmFsU2l6ZSksIDQwKTtcbiAgICByZWNvcmQud3JpdGVCaWdVSW50NjRMRShCaWdJbnQob2Zmc2V0KSwgNDgpO1xuICAgIGNvbnN0IGxvY2F0b3IgPSBCdWZmZXIuYWxsb2MoMjApO1xuICAgIGxvY2F0b3Iud3JpdGVVSW50MzJMRSgweDA3MDY0YjUwLCAwKTtcbiAgICBsb2NhdG9yLndyaXRlQmlnVUludDY0TEUoQmlnSW50KG9mZnNldCArIGNlbnRyYWxTaXplKSwgOCk7XG4gICAgbG9jYXRvci53cml0ZVVJbnQzMkxFKDEsIDE2KTtcbiAgICB6aXA2NC5wdXNoKHJlY29yZCwgbG9jYXRvcik7XG4gIH1cbiAgY29uc3QgZW5kID0gQnVmZmVyLmFsbG9jKDIyKTtcbiAgZW5kLndyaXRlVUludDMyTEUoMHgwNjA1NGI1MCwgMCk7XG4gIC8vIDB4ZmZmZiBkZWZlcnMgdG8gdGhlIFppcDY0IHJlY29yZC5cbiAgZW5kLndyaXRlVUludDE2TEUoTWF0aC5taW4oY291bnQsIDB4ZmZmZiksIDgpO1xuICBlbmQud3JpdGVVSW50MTZMRShNYXRoLm1pbihjb3VudCwgMHhmZmZmKSwgMTApO1xuICBlbmQud3JpdGVVSW50MzJMRShjZW50cmFsU2l6ZSwgMTIpO1xuICBlbmQud3JpdGVVSW50MzJMRShvZmZzZXQsIDE2KTtcbiAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoWy4uLmNodW5rcywgLi4uY2VudHJhbCwgLi4uemlwNjQsIGVuZF0pO1xufVxuIl19
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const node_child_process_1 = require("node:child_process");
37
+ const node_fs_1 = require("node:fs");
38
+ const node_os_1 = require("node:os");
39
+ const node_path_1 = require("node:path");
40
+ const zlib = __importStar(require("node:zlib"));
41
+ const zip_directory_1 = require("./zip-directory");
42
+ /** A pnpm-shaped tree: the logical path links into the store. */
43
+ function makeTree() {
44
+ const root = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-zip-"));
45
+ const pkg = (0, node_path_1.join)(root, "node_modules", ".pnpm", "a@1.0.0", "node_modules", "a");
46
+ (0, node_fs_1.mkdirSync)(pkg, { recursive: true });
47
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(pkg, "index.js"), "module.exports = 'a';\n".repeat(50));
48
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(pkg, "bin.sh"), "#!/bin/sh\n", { mode: 0o755 });
49
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(root, "app", "node_modules"), { recursive: true });
50
+ (0, node_fs_1.symlinkSync)("../../node_modules/.pnpm/a@1.0.0/node_modules/a", (0, node_path_1.join)(root, "app", "node_modules", "a"));
51
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(root, "empty"));
52
+ return root;
53
+ }
54
+ describe("crc32", () => {
55
+ // Its own, because `zlib.crc32` is missing before Node 20.15.
56
+ it("matches zlib's", () => {
57
+ for (const data of ["", "a", "hello, world", "x".repeat(100_000)]) {
58
+ expect((0, zip_directory_1.crc32)(Buffer.from(data))).toBe(zlib.crc32(data));
59
+ }
60
+ });
61
+ });
62
+ describe("zipDirectory", () => {
63
+ it("round-trips symlinks as symlinks through unzip", () => {
64
+ const root = makeTree();
65
+ const out = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-unzip-"));
66
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(out, "root.zip"), (0, zip_directory_1.zipDirectory)(root));
67
+ (0, node_child_process_1.execFileSync)("unzip", ["-q", "root.zip", "-d", "x"], { cwd: out });
68
+ const link = (0, node_path_1.join)(out, "x", "app", "node_modules", "a");
69
+ expect((0, node_fs_1.lstatSync)(link).isSymbolicLink()).toBe(true);
70
+ expect((0, node_fs_1.readlinkSync)(link)).toBe("../../node_modules/.pnpm/a@1.0.0/node_modules/a");
71
+ expect((0, node_fs_1.readFileSync)((0, node_path_1.join)(link, "index.js"), "utf8")).toContain("'a'");
72
+ // eslint-disable-next-line no-bitwise
73
+ expect((0, node_fs_1.lstatSync)((0, node_path_1.join)(link, "bin.sh")).mode & 0o111).toBeTruthy();
74
+ expect((0, node_fs_1.lstatSync)((0, node_path_1.join)(out, "x", "empty")).isDirectory()).toBe(true);
75
+ });
76
+ it("is deterministic, so the asset hash only moves with the contents", () => {
77
+ const root = makeTree();
78
+ const first = (0, zip_directory_1.zipDirectory)(root);
79
+ (0, node_fs_1.utimesSync)((0, node_path_1.join)(root, "empty"), 0, 0);
80
+ expect((0, zip_directory_1.zipDirectory)(root).equals(first)).toBe(true);
81
+ // The same tree built somewhere else, at another time.
82
+ expect((0, zip_directory_1.zipDirectory)(makeTree()).equals(first)).toBe(true);
83
+ });
84
+ it("writes a Zip64 end record past 65,535 entries", () => {
85
+ const root = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-zip64-"));
86
+ // Links are the cheapest entries to make.
87
+ for (let i = 0; i < 0x10000 + 10; i++) {
88
+ (0, node_fs_1.symlinkSync)("t", (0, node_path_1.join)(root, `l${i}`));
89
+ }
90
+ const out = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "cdk-nextjs-unzip64-"));
91
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(out, "root.zip"), (0, zip_directory_1.zipDirectory)(root));
92
+ const listing = (0, node_child_process_1.execFileSync)("unzip", ["-l", "root.zip"], {
93
+ cwd: out,
94
+ maxBuffer: 64 * 1024 * 1024,
95
+ }).toString();
96
+ expect(listing.trim().split("\n").pop()).toMatch(/\b65546 files$/);
97
+ }, 60_000);
98
+ });
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemlwLWRpcmVjdG9yeS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3ppcC1kaXJlY3RvcnkudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJEQUFrRDtBQUNsRCxxQ0FTaUI7QUFDakIscUNBQWlDO0FBQ2pDLHlDQUFpQztBQUNqQyxnREFBa0M7QUFDbEMsbURBQXNEO0FBRXRELGlFQUFpRTtBQUNqRSxTQUFTLFFBQVE7SUFDZixNQUFNLElBQUksR0FBRyxJQUFBLHFCQUFXLEVBQUMsSUFBQSxnQkFBSSxFQUFDLElBQUEsZ0JBQU0sR0FBRSxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUM1RCxNQUFNLEdBQUcsR0FBRyxJQUFBLGdCQUFJLEVBQ2QsSUFBSSxFQUNKLGNBQWMsRUFDZCxPQUFPLEVBQ1AsU0FBUyxFQUNULGNBQWMsRUFDZCxHQUFHLENBQ0osQ0FBQztJQUNGLElBQUEsbUJBQVMsRUFBQyxHQUFHLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNwQyxJQUFBLHVCQUFhLEVBQUMsSUFBQSxnQkFBSSxFQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSx5QkFBeUIsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzRSxJQUFBLHVCQUFhLEVBQUMsSUFBQSxnQkFBSSxFQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsRUFBRSxhQUFhLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNuRSxJQUFBLG1CQUFTLEVBQUMsSUFBQSxnQkFBSSxFQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNsRSxJQUFBLHFCQUFXLEVBQ1QsaURBQWlELEVBQ2pELElBQUEs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UixTQUFTLEVBQUUsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJO1NBQzVCLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNkLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDckUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2IsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGVjRmlsZVN5bmMgfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQge1xuICBsc3RhdFN5bmMsXG4gIG1rZGlyU3luYyxcbiAgbWtkdGVtcFN5bmMsXG4gIHJlYWRGaWxlU3luYyxcbiAgcmVhZGxpbmtTeW5jLFxuICBzeW1saW5rU3luYyxcbiAgdXRpbWVzU3luYyxcbiAgd3JpdGVGaWxlU3luYyxcbn0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0ICogYXMgemxpYiBmcm9tIFwibm9kZTp6bGliXCI7XG5pbXBvcnQgeyBjcmMzMiwgemlwRGlyZWN0b3J5IH0gZnJvbSBcIi4vemlwLWRpcmVjdG9yeVwiO1xuXG4vKiogQSBwbnBtLXNoYXBlZCB0cmVlOiB0aGUgbG9naWNhbCBwYXRoIGxpbmtzIGludG8gdGhlIHN0b3JlLiAqL1xuZnVuY3Rpb24gbWFrZVRyZWUoKTogc3RyaW5nIHtcbiAgY29uc3Qgcm9vdCA9IG1rZHRlbXBTeW5jKGpvaW4odG1wZGlyKCksIFwiY2RrLW5leHRqcy16aXAtXCIpKTtcbiAgY29uc3QgcGtnID0gam9pbihcbiAgICByb290LFxuICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgXCIucG5wbVwiLFxuICAgIFwiYUAxLjAuMFwiLFxuICAgIFwibm9kZV9tb2R1bGVzXCIsXG4gICAgXCJhXCIsXG4gICk7XG4gIG1rZGlyU3luYyhwa2csIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB3cml0ZUZpbGVTeW5jKGpvaW4ocGtnLCBcImluZGV4LmpzXCIpLCBcIm1vZHVsZS5leHBvcnRzID0gJ2EnO1xcblwiLnJlcGVhdCg1MCkpO1xuICB3cml0ZUZpbGVTeW5jKGpvaW4ocGtnLCBcImJpbi5zaFwiKSwgXCIjIS9iaW4vc2hcXG5cIiwgeyBtb2RlOiAwbzc1NSB9KTtcbiAgbWtkaXJTeW5jKGpvaW4ocm9vdCwgXCJhcHBcIiwgXCJub2RlX21vZHVsZXNcIiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICBzeW1saW5rU3luYyhcbiAgICBcIi4uLy4uL25vZGVfbW9kdWxlcy8ucG5wbS9hQDEuMC4wL25vZGVfbW9kdWxlcy9hXCIsXG4gICAgam9pbihyb290LCBcImFwcFwiLCBcIm5vZGVfbW9kdWxlc1wiLCBcImFcIiksXG4gICk7XG4gIG1rZGlyU3luYyhqb2luKHJvb3QsIFwiZW1wdHlcIikpO1xuICByZXR1cm4gcm9vdDtcbn1cblxuZGVzY3JpYmUoXCJjcmMzMlwiLCAoKSA9PiB7XG4gIC8vIEl0cyBvd24sIGJlY2F1c2UgYHpsaWIuY3JjMzJgIGlzIG1pc3NpbmcgYmVmb3JlIE5vZGUgMjAuMTUuXG4gIGl0KFwibWF0Y2hlcyB6bGliJ3NcIiwgKCkgPT4ge1xuICAgIGZvciAoY29uc3QgZGF0YSBvZiBbXCJcIiwgXCJhXCIsIFwiaGVsbG8sIHdvcmxkXCIsIFwieFwiLnJlcGVhdCgxMDBfMDAwKV0pIHtcbiAgICAgIGV4cGVjdChjcmMzMihCdWZmZXIuZnJvbShkYXRhKSkpLnRvQmUoemxpYi5jcmMzMihkYXRhKSk7XG4gICAgfVxuICB9KTtcbn0pO1xuXG5kZXNjcmliZShcInppcERpcmVjdG9yeVwiLCAoKSA9PiB7XG4gIGl0KFwicm91bmQtdHJpcHMgc3ltbGlua3MgYXMgc3ltbGlua3MgdGhyb3VnaCB1bnppcFwiLCAoKSA9PiB7XG4gICAgY29uc3Qgcm9vdCA9IG1ha2VUcmVlKCk7XG4gICAgY29uc3Qgb3V0ID0gbWtkdGVtcFN5bmMoam9pbih0bXBkaXIoKSwgXCJjZGstbmV4dGpzLXVuemlwLVwiKSk7XG4gICAgd3JpdGVGaWxlU3luYyhqb2luKG91dCwgXCJyb290LnppcFwiKSwgemlwRGlyZWN0b3J5KHJvb3QpKTtcbiAgICBleGVjRmlsZVN5bmMoXCJ1bnppcFwiLCBbXCItcVwiLCBcInJvb3QuemlwXCIsIFwiLWRcIiwgXCJ4XCJdLCB7IGN3ZDogb3V0IH0pO1xuXG4gICAgY29uc3QgbGluayA9IGpvaW4ob3V0LCBcInhcIiwgXCJhcHBcIiwgXCJub2RlX21vZHVsZXNcIiwgXCJhXCIpO1xuICAgIGV4cGVjdChsc3RhdFN5bmMobGluaykuaXNTeW1ib2xpY0xpbmsoKSkudG9CZSh0cnVlKTtcbiAgICBleHBlY3QocmVhZGxpbmtTeW5jKGxpbmspKS50b0JlKFxuICAgICAgXCIuLi8uLi9ub2RlX21vZHVsZXMvLnBucG0vYUAxLjAuMC9ub2RlX21vZHVsZXMvYVwiLFxuICAgICk7XG4gICAgZXhwZWN0KHJlYWRGaWxlU3luYyhqb2luKGxpbmssIFwiaW5kZXguanNcIiksIFwidXRmOFwiKSkudG9Db250YWluKFwiJ2EnXCIpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgZXhwZWN0KGxzdGF0U3luYyhqb2luKGxpbmssIFwiYmluLnNoXCIpKS5tb2RlICYgMG8xMTEpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QobHN0YXRTeW5jKGpvaW4ob3V0LCBcInhcIiwgXCJlbXB0eVwiKSkuaXNEaXJlY3RvcnkoKSkudG9CZSh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoXCJpcyBkZXRlcm1pbmlzdGljLCBzbyB0aGUgYXNzZXQgaGFzaCBvbmx5IG1vdmVzIHdpdGggdGhlIGNvbnRlbnRzXCIsICgpID0+IHtcbiAgICBjb25zdCByb290ID0gbWFrZVRyZWUoKTtcbiAgICBjb25zdCBmaXJzdCA9IHppcERpcmVjdG9yeShyb290KTtcbiAgICB1dGltZXNTeW5jKGpvaW4ocm9vdCwgXCJlbXB0eVwiKSwgMCwgMCk7XG4gICAgZXhwZWN0KHppcERpcmVjdG9yeShyb290KS5lcXVhbHMoZmlyc3QpKS50b0JlKHRydWUpO1xuICAgIC8vIFRoZSBzYW1lIHRyZWUgYnVpbHQgc29tZXdoZXJlIGVsc2UsIGF0IGFub3RoZXIgdGltZS5cbiAgICBleHBlY3QoemlwRGlyZWN0b3J5KG1ha2VUcmVlKCkpLmVxdWFscyhmaXJzdCkpLnRvQmUodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KFwid3JpdGVzIGEgWmlwNjQgZW5kIHJlY29yZCBwYXN0IDY1LDUzNSBlbnRyaWVzXCIsICgpID0+IHtcbiAgICBjb25zdCByb290ID0gbWtkdGVtcFN5bmMoam9pbih0bXBkaXIoKSwgXCJjZGstbmV4dGpzLXppcDY0LVwiKSk7XG4gICAgLy8gTGlua3MgYXJlIHRoZSBjaGVhcGVzdCBlbnRyaWVzIHRvIG1ha2UuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAweDEwMDAwICsgMTA7IGkrKykge1xuICAgICAgc3ltbGlua1N5bmMoXCJ0XCIsIGpvaW4ocm9vdCwgYGwke2l9YCkpO1xuICAgIH1cbiAgICBjb25zdCBvdXQgPSBta2R0ZW1wU3luYyhqb2luKHRtcGRpcigpLCBcImNkay1uZXh0anMtdW56aXA2NC1cIikpO1xuICAgIHdyaXRlRmlsZVN5bmMoam9pbihvdXQsIFwicm9vdC56aXBcIiksIHppcERpcmVjdG9yeShyb290KSk7XG4gICAgY29uc3QgbGlzdGluZyA9IGV4ZWNGaWxlU3luYyhcInVuemlwXCIsIFtcIi1sXCIsIFwicm9vdC56aXBcIl0sIHtcbiAgICAgIGN3ZDogb3V0LFxuICAgICAgbWF4QnVmZmVyOiA2NCAqIDEwMjQgKiAxMDI0LFxuICAgIH0pLnRvU3RyaW5nKCk7XG4gICAgZXhwZWN0KGxpc3RpbmcudHJpbSgpLnNwbGl0KFwiXFxuXCIpLnBvcCgpKS50b01hdGNoKC9cXGI2NTU0NiBmaWxlcyQvKTtcbiAgfSwgNjBfMDAwKTtcbn0pO1xuIl19
package/package.json CHANGED
@@ -14,12 +14,14 @@
14
14
  "@aws-cdk/integ-runner": "latest",
15
15
  "@aws-cdk/integ-tests-alpha": "latest",
16
16
  "@aws-crypto/sha256-js": "^5.2.0",
17
+ "@aws-sdk/client-api-gateway": "^3.1141.0",
17
18
  "@aws-sdk/client-cloudfront": "^3.1121.0",
18
19
  "@aws-sdk/client-dynamodb": "^3.1121.0",
19
20
  "@aws-sdk/client-s3": "^3.1121.0",
20
21
  "@aws-sdk/client-ssm": "^3.1136.0",
21
22
  "@aws-sdk/lib-storage": "^3.1121.0",
22
23
  "@mrgrain/jsii-struct-builder": "^0.7.64",
24
+ "@next/routing": "16.3.5",
23
25
  "@smithy/signature-v4": "^2.3.0",
24
26
  "@types/aws-lambda": "^8.10.162",
25
27
  "@types/debug": "^4.1.13",
@@ -28,6 +30,7 @@
28
30
  "@types/node": "^24",
29
31
  "@typescript-eslint/eslint-plugin": "^8",
30
32
  "@typescript-eslint/parser": "^8",
33
+ "aws-cdk": "^2.1142.0",
31
34
  "aws-cdk-lib": "2.261.0",
32
35
  "cdk-nag": "^2.38.2",
33
36
  "cdklabs-projen-project-types": "^0.6.8",
@@ -81,7 +84,7 @@
81
84
  "publishConfig": {
82
85
  "access": "public"
83
86
  },
84
- "version": "0.6.2",
87
+ "version": "0.7.0",
85
88
  "jest": {
86
89
  "coverageProvider": "v8",
87
90
  "testPathIgnorePatterns": [
@@ -149,6 +152,14 @@
149
152
  "./cache-handler": {
150
153
  "import": "./lib/adapter/cache-handler.mjs",
151
154
  "default": "./lib/adapter/cache-handler.mjs"
155
+ },
156
+ "./cache-handlers/default": {
157
+ "import": "./lib/adapter/use-cache-default-handler.mjs",
158
+ "default": "./lib/adapter/use-cache-default-handler.mjs"
159
+ },
160
+ "./cache-handlers/remote": {
161
+ "import": "./lib/adapter/use-cache-remote-handler.mjs",
162
+ "default": "./lib/adapter/use-cache-remote-handler.mjs"
152
163
  }
153
164
  },
154
165
  "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"pnpm dlx projen\".",
@@ -161,12 +172,20 @@
161
172
  "bundle:adapter/adapter:watch": "pnpm dlx projen bundle:adapter/adapter:watch",
162
173
  "bundle:adapter/cache-handler": "pnpm dlx projen bundle:adapter/cache-handler",
163
174
  "bundle:adapter/cache-handler:watch": "pnpm dlx projen bundle:adapter/cache-handler:watch",
164
- "bundle:image-optimization/handler": "pnpm dlx projen bundle:image-optimization/handler",
165
- "bundle:image-optimization/handler:watch": "pnpm dlx projen bundle:image-optimization/handler:watch",
175
+ "bundle:adapter/use-cache-default-handler": "pnpm dlx projen bundle:adapter/use-cache-default-handler",
176
+ "bundle:adapter/use-cache-default-handler:watch": "pnpm dlx projen bundle:adapter/use-cache-default-handler:watch",
177
+ "bundle:adapter/use-cache-remote-handler": "pnpm dlx projen bundle:adapter/use-cache-remote-handler",
178
+ "bundle:adapter/use-cache-remote-handler:watch": "pnpm dlx projen bundle:adapter/use-cache-remote-handler:watch",
166
179
  "bundle:lambdas/post-deploy/post-deploy.lambda": "pnpm dlx projen bundle:lambdas/post-deploy/post-deploy.lambda",
167
180
  "bundle:lambdas/post-deploy/post-deploy.lambda:watch": "pnpm dlx projen bundle:lambdas/post-deploy/post-deploy.lambda:watch",
181
+ "bundle:lambdas/redeploy-stage/redeploy-stage.lambda": "pnpm dlx projen bundle:lambdas/redeploy-stage/redeploy-stage.lambda",
182
+ "bundle:lambdas/redeploy-stage/redeploy-stage.lambda:watch": "pnpm dlx projen bundle:lambdas/redeploy-stage/redeploy-stage.lambda:watch",
168
183
  "bundle:nextjs-build/patch-fetch": "pnpm dlx projen bundle:nextjs-build/patch-fetch",
169
184
  "bundle:nextjs-build/patch-fetch:watch": "pnpm dlx projen bundle:nextjs-build/patch-fetch:watch",
185
+ "bundle:runtime/lambda": "pnpm dlx projen bundle:runtime/lambda",
186
+ "bundle:runtime/lambda:watch": "pnpm dlx projen bundle:runtime/lambda:watch",
187
+ "bundle:runtime/server": "pnpm dlx projen bundle:runtime/server",
188
+ "bundle:runtime/server:watch": "pnpm dlx projen bundle:runtime/server:watch",
170
189
  "clobber": "pnpm dlx projen clobber",
171
190
  "compat": "pnpm dlx projen compat",
172
191
  "compile": "pnpm dlx projen compile",
@@ -0,0 +1,325 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Capture a real `onBuildComplete` context from an example app and write it to
4
+ * `src/adapter/__fixtures__/<name>.json`, for the unit tests in
5
+ * `src/adapter/build-outputs.test.ts`.
6
+ *
7
+ * Regenerate the fixtures whenever `next` is upgraded: the shape of
8
+ * `ctx.routing` / `ctx.outputs` is Next.js's, not ours, and it changes between
9
+ * minors (`routing.middlewareMatchers`, for one, did not exist in 16.2).
10
+ *
11
+ * pnpm bundle
12
+ * node scripts/capture-adapter-fixture.mjs app-playground
13
+ * NEXTJS_BASE_PATH=/prod node scripts/capture-adapter-fixture.mjs \
14
+ * app-playground --name app-playground-base-path
15
+ *
16
+ * Pass `--reuse-capture` to re-trim the previous run's dump without rebuilding.
17
+ *
18
+ * How it captures: `examples/<app>`'s `sync-cdk-nextjs` script copies this
19
+ * repo's bundled adapter into its own `node_modules/cdk-nextjs`, and
20
+ * `next.config.ts` resolves `adapterPath` to that copy. The copy is untracked build output, so we
21
+ * append a wrapper to it that dumps `ctx` before delegating to the real hook,
22
+ * then run `next build`. Nothing tracked is modified.
23
+ *
24
+ * How it trims: a raw capture of app-playground is ~9 MB, almost all of it
25
+ * repeated `node_modules` paths in per-output `assets`/`assetsHashes` maps. The
26
+ * fixture keeps a curated subset of outputs, and within each output keeps every
27
+ * non-`node_modules` asset key plus a deterministic sample of the
28
+ * `node_modules` ones. Absolute paths are rewritten to a `/repo` placeholder so
29
+ * the fixture is machine-independent. The trim is recorded in `_meta`.
30
+ */
31
+ import { execFileSync } from "node:child_process";
32
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
33
+ import { dirname, join, resolve } from "node:path";
34
+ import { fileURLToPath } from "node:url";
35
+
36
+ const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
37
+ const PLACEHOLDER_ROOT = "/repo";
38
+ /** Per kept output, how many `node_modules/` asset keys to retain. */
39
+ const NODE_MODULES_ASSET_SAMPLE = 8;
40
+ /**
41
+ * Cap on *concrete* prerenders, per route template. Per template rather than
42
+ * overall, so that adding a route to `KEEP_PATHNAMES` cannot push another
43
+ * route's concrete pages (`/isr/1` and its `.rsc`/segment variants) out of the
44
+ * fixture. Dynamic templates are always kept in full.
45
+ */
46
+ const MAX_PRERENDERS_PER_ROUTE = 12;
47
+ const MAX_STATIC_FILES = 8;
48
+
49
+ /**
50
+ * Which route templates to keep per example app. Chosen to cover: the root
51
+ * page, a dynamic ISR route, a multi-segment dynamic route whose param names
52
+ * prefix one another, optional catch-all and encoded params, the synthetic
53
+ * `_not-found` page, and both a static and a mutating route handler. Each
54
+ * app-router page also has a sibling `.rsc` output, kept automatically.
55
+ */
56
+ const KEEP_PATHNAMES = {
57
+ "app-playground": [
58
+ "/",
59
+ "/_not-found",
60
+ "/isr/[id]",
61
+ "/api/health",
62
+ "/api/revalidate",
63
+ "/api/echo",
64
+ // The destination of `next.config.ts`'s one `beforeFiles` rewrite.
65
+ "/e2e/rewrite/echo",
66
+ // `[id]` is a prefix of `[id2]`, which is what `@next/routing`'s param
67
+ // expansion gets wrong (see `dispatch.test.ts`).
68
+ "/params/prefix/[id]/[id2]",
69
+ "/params/optional/[[...rest]]",
70
+ "/params/encoded/[slug]",
71
+ ],
72
+ // Small enough to keep whole; `keep` being empty means "keep everything".
73
+ "pages-i18n": [],
74
+ };
75
+
76
+ function main() {
77
+ const args = process.argv.slice(2);
78
+ const app = args[0];
79
+ if (!app) {
80
+ console.error(
81
+ "usage: node scripts/capture-adapter-fixture.mjs <example-app> [--name <fixture-name>]",
82
+ );
83
+ process.exit(1);
84
+ }
85
+ const nameFlag = args.indexOf("--name");
86
+ const name = nameFlag === -1 ? app : args[nameFlag + 1];
87
+ // Re-trim the dump a previous run left behind instead of rebuilding. For when
88
+ // the trim rules change but `next` has not; skips a ~2 minute `next build`.
89
+ const reuse = args.includes("--reuse-capture");
90
+
91
+ const appDir = join(repoRoot, "examples", app);
92
+ const dumpPath = join(appDir, ".next", `adapter-ctx-capture.json`);
93
+ const fixturePath = join(
94
+ repoRoot,
95
+ "src",
96
+ "adapter",
97
+ "__fixtures__",
98
+ `${name}.json`,
99
+ );
100
+
101
+ if (!reuse) {
102
+ // The example app's sync script copies this repo's *bundled* adapter, so a
103
+ // stale bundle would silently capture the previous implementation.
104
+ run("pnpm", ["bundle"], repoRoot);
105
+ run("pnpm", ["run", "sync-cdk-nextjs"], appDir);
106
+ patchAdapterCopy(appDir);
107
+ rmSync(dumpPath, { force: true });
108
+ run("npx", ["next", "build"], appDir, {
109
+ CDK_NEXTJS_DUMP_CTX: dumpPath,
110
+ });
111
+ }
112
+
113
+ const raw = JSON.parse(readFileSync(dumpPath, "utf8"));
114
+ const fixture = trim(raw, { app, name });
115
+ mkdirSync(dirname(fixturePath), { recursive: true });
116
+ writeFileSync(fixturePath, `${JSON.stringify(fixture, null, 2)}\n`);
117
+ console.log(
118
+ `wrote ${fixturePath} (${(readFileSync(fixturePath).length / 1024).toFixed(0)} KB)`,
119
+ );
120
+ }
121
+
122
+ function run(cmd, args, cwd, env = {}) {
123
+ console.error(`$ ${cmd} ${args.join(" ")} (in ${cwd})`);
124
+ execFileSync(cmd, args, {
125
+ cwd,
126
+ stdio: ["ignore", "inherit", "inherit"],
127
+ env: { ...process.env, ...env },
128
+ });
129
+ }
130
+
131
+ /**
132
+ * Append a `ctx`-dumping wrapper to the untracked copy of the bundled adapter
133
+ * that the sync script just made.
134
+ */
135
+ function patchAdapterCopy(appDir) {
136
+ const copy = join(
137
+ appDir,
138
+ "node_modules",
139
+ "cdk-nextjs",
140
+ "lib",
141
+ "adapter",
142
+ "adapter.mjs",
143
+ );
144
+ const needle = "export {\n adapter_default as default\n};";
145
+ const source = readFileSync(copy, "utf8");
146
+ if (!source.includes(needle)) {
147
+ throw new Error(
148
+ `Could not find the default export in ${copy}. The esbuild output shape changed; update this script.`,
149
+ );
150
+ }
151
+ writeFileSync(
152
+ copy,
153
+ source.replace(
154
+ needle,
155
+ `
156
+ const __captureAdapter = {
157
+ ...adapter_default,
158
+ async onBuildComplete(ctx) {
159
+ const { writeFile } = await import("node:fs/promises");
160
+ const { routing, outputs, projectDir, repoRoot, distDir, nextVersion, buildId, config } = ctx;
161
+ await writeFile(
162
+ process.env.CDK_NEXTJS_DUMP_CTX,
163
+ JSON.stringify({
164
+ routing,
165
+ outputs,
166
+ projectDir,
167
+ repoRoot,
168
+ distDir,
169
+ nextVersion,
170
+ buildId,
171
+ config: {
172
+ basePath: config.basePath,
173
+ trailingSlash: config.trailingSlash,
174
+ assetPrefix: config.assetPrefix,
175
+ i18n: config.i18n,
176
+ },
177
+ }),
178
+ );
179
+ return adapter_default.onBuildComplete(ctx);
180
+ },
181
+ };
182
+ export { __captureAdapter as default };`,
183
+ ),
184
+ );
185
+ }
186
+
187
+ function trim(raw, { app, name }) {
188
+ const realRoot = raw.repoRoot;
189
+ const rewrite = (value) =>
190
+ typeof value === "string" && value.startsWith(realRoot)
191
+ ? PLACEHOLDER_ROOT + value.slice(realRoot.length)
192
+ : value;
193
+
194
+ // Output `pathname`s carry `basePath` (`/prod/api/health`) while `id`,
195
+ // `sourcePage` and `prerenders[].route` do not, so the allowlist matches on
196
+ // the basePath-stripped pathname and `keptTemplates` holds stripped names.
197
+ const basePath = raw.config.basePath || "";
198
+ const normalize = (pathname) => {
199
+ let p = pathname;
200
+ if (basePath && (p === basePath || p.startsWith(`${basePath}/`))) {
201
+ p = p.slice(basePath.length);
202
+ }
203
+ p = p.replace(/\.rsc$/, "");
204
+ return p === "" || p === "/index" ? "/" : p;
205
+ };
206
+
207
+ const keep = new Set(KEEP_PATHNAMES[app] ?? []);
208
+ const keptTemplates = new Set();
209
+ const keepOutput = (output) => {
210
+ const base = normalize(output.pathname);
211
+ if (keep.size === 0 || keep.has(base)) {
212
+ keptTemplates.add(base);
213
+ return true;
214
+ }
215
+ return false;
216
+ };
217
+
218
+ const trimOutput = (output) => {
219
+ const assetKeys = Object.keys(output.assets).sort();
220
+ const local = assetKeys.filter((k) => !k.startsWith("node_modules/"));
221
+ const vendored = assetKeys
222
+ .filter((k) => k.startsWith("node_modules/"))
223
+ .slice(0, NODE_MODULES_ASSET_SAMPLE);
224
+ const kept = [...local, ...vendored];
225
+
226
+ const assets = {};
227
+ const assetsHashes = {};
228
+ for (const key of kept) {
229
+ assets[key] = rewrite(output.assets[key]);
230
+ if (output.assetsHashes[key] !== undefined) {
231
+ assetsHashes[key] = output.assetsHashes[key];
232
+ }
233
+ }
234
+ // The entrypoint's own hash is keyed in `assetsHashes` but deliberately
235
+ // absent from `assets`; keeping it is what lets the tests assert the
236
+ // entrypoint gets staged from its hash-derived key.
237
+ for (const [key, hash] of Object.entries(output.assetsHashes)) {
238
+ if (!(key in output.assets)) {
239
+ assetsHashes[key] = hash;
240
+ }
241
+ }
242
+ return {
243
+ ...output,
244
+ filePath: rewrite(output.filePath),
245
+ assets,
246
+ assetsHashes,
247
+ };
248
+ };
249
+
250
+ const outputs = {
251
+ pages: raw.outputs.pages.filter(keepOutput).map(trimOutput),
252
+ pagesApi: raw.outputs.pagesApi.filter(keepOutput).map(trimOutput),
253
+ appPages: raw.outputs.appPages.filter(keepOutput).map(trimOutput),
254
+ appRoutes: raw.outputs.appRoutes.filter(keepOutput).map(trimOutput),
255
+ prerenders: [
256
+ // Dynamic templates are never dropped: they are what
257
+ // `buildAdapterManifest` turns into extra `entrypoints`/`pathnames`
258
+ // entries (Pages Router `/_next/data/…/[slug].json` in particular), so a
259
+ // fixture without them would not exercise that path at all.
260
+ ...raw.outputs.prerenders.filter(
261
+ (p) => keptTemplates.has(p.route) && p.pathname.includes("["),
262
+ ),
263
+ ...capPerRoute(
264
+ raw.outputs.prerenders.filter(
265
+ (p) => keptTemplates.has(p.route) && !p.pathname.includes("["),
266
+ ),
267
+ MAX_PRERENDERS_PER_ROUTE,
268
+ ),
269
+ ].map((p) => ({
270
+ ...p,
271
+ fallback: p.fallback
272
+ ? { ...p.fallback, filePath: rewrite(p.fallback.filePath) }
273
+ : p.fallback,
274
+ })),
275
+ staticFiles: [
276
+ ...raw.outputs.staticFiles.filter(
277
+ (f) => !normalize(f.pathname).startsWith("/_next/static"),
278
+ ),
279
+ ...raw.outputs.staticFiles.filter((f) =>
280
+ normalize(f.pathname).startsWith("/_next/static"),
281
+ ),
282
+ ]
283
+ .slice(0, MAX_STATIC_FILES)
284
+ .map((f) => ({ ...f, filePath: rewrite(f.filePath) })),
285
+ middleware: raw.outputs.middleware
286
+ ? trimOutput(raw.outputs.middleware)
287
+ : undefined,
288
+ };
289
+
290
+ return {
291
+ _meta: {
292
+ fixture: name,
293
+ capturedFrom: `examples/${app}`,
294
+ nextVersion: raw.nextVersion,
295
+ generatedBy: "scripts/capture-adapter-fixture.mjs",
296
+ trimmed: {
297
+ repoRootRewrittenTo: PLACEHOLDER_ROOT,
298
+ keptRouteTemplates: [...keptTemplates].sort(),
299
+ nodeModulesAssetsPerOutput: NODE_MODULES_ASSET_SAMPLE,
300
+ maxConcretePrerendersPerRoute: MAX_PRERENDERS_PER_ROUTE,
301
+ maxStaticFiles: MAX_STATIC_FILES,
302
+ },
303
+ },
304
+ routing: raw.routing,
305
+ outputs,
306
+ projectDir: rewrite(raw.projectDir),
307
+ repoRoot: PLACEHOLDER_ROOT,
308
+ distDir: rewrite(raw.distDir),
309
+ nextVersion: raw.nextVersion,
310
+ buildId: raw.buildId,
311
+ config: raw.config,
312
+ };
313
+ }
314
+
315
+ /** The first `max` of `prerenders` for each `route`, in their original order. */
316
+ function capPerRoute(prerenders, max) {
317
+ const seen = new Map();
318
+ return prerenders.filter((p) => {
319
+ const count = seen.get(p.route) ?? 0;
320
+ seen.set(p.route, count + 1);
321
+ return count < max;
322
+ });
323
+ }
324
+
325
+ main();