cdk-nextjs 0.6.1 → 0.7.0

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