cdk-nextjs 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/.jsii +2404 -2723
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1681 -1930
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +667 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1551 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +857 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +863 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +8 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  88. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  92. package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
  93. package/lib/lambdas/post-deploy/prune-s3.js +41 -12
  94. package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
  95. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  96. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  103. package/lib/nextjs-api.d.ts +102 -18
  104. package/lib/nextjs-api.js +338 -38
  105. package/lib/nextjs-api.test.js +537 -1
  106. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  107. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  108. package/lib/nextjs-build/nextjs-build.js +684 -327
  109. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  110. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  111. package/lib/nextjs-build/patch-fetch.js +1 -1
  112. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  113. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  114. package/lib/nextjs-cache.d.ts +82 -4
  115. package/lib/nextjs-cache.js +186 -10
  116. package/lib/nextjs-cache.test.js +176 -1
  117. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  118. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  120. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  121. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  122. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  123. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  124. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  125. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  126. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  127. package/lib/nextjs-distribution.d.ts +194 -23
  128. package/lib/nextjs-distribution.js +535 -62
  129. package/lib/nextjs-distribution.test.d.ts +1 -0
  130. package/lib/nextjs-distribution.test.js +697 -0
  131. package/lib/nextjs-post-deploy.d.ts +13 -5
  132. package/lib/nextjs-post-deploy.js +13 -10
  133. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  134. package/lib/nextjs-post-deploy.test.js +34 -0
  135. package/lib/nextjs-static-assets.d.ts +17 -4
  136. package/lib/nextjs-static-assets.js +22 -5
  137. package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
  138. package/lib/root-constructs/nextjs-base-construct.js +139 -47
  139. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  140. package/lib/root-constructs/nextjs-global-containers.js +20 -71
  141. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  142. package/lib/root-constructs/nextjs-global-functions.js +52 -70
  143. package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
  144. package/lib/root-constructs/nextjs-regional-containers.js +8 -15
  145. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  146. package/lib/root-constructs/nextjs-regional-functions.js +8 -26
  147. package/lib/runtime/api-gateway-path.d.ts +34 -0
  148. package/lib/runtime/api-gateway-path.js +71 -0
  149. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  150. package/lib/runtime/api-gateway-path.test.js +65 -0
  151. package/lib/runtime/case-redirect.d.ts +22 -0
  152. package/lib/runtime/case-redirect.js +63 -0
  153. package/lib/runtime/case-redirect.test.d.ts +1 -0
  154. package/lib/runtime/case-redirect.test.js +32 -0
  155. package/lib/runtime/core.d.ts +234 -0
  156. package/lib/runtime/core.js +1216 -0
  157. package/lib/runtime/core.test.d.ts +1 -0
  158. package/lib/runtime/core.test.js +1686 -0
  159. package/lib/runtime/deployment-root.d.ts +13 -0
  160. package/lib/runtime/deployment-root.js +29 -0
  161. package/lib/runtime/dispatch.d.ts +331 -0
  162. package/lib/runtime/dispatch.js +751 -0
  163. package/lib/runtime/dispatch.test.d.ts +1 -0
  164. package/lib/runtime/dispatch.test.js +853 -0
  165. package/lib/runtime/entrypoints.d.ts +57 -0
  166. package/lib/runtime/entrypoints.js +115 -0
  167. package/lib/runtime/http/abort-signal.d.ts +6 -0
  168. package/lib/runtime/http/abort-signal.js +19 -0
  169. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  170. package/lib/runtime/http/abort-signal.test.js +49 -0
  171. package/lib/runtime/http/node-server.d.ts +38 -0
  172. package/lib/runtime/http/node-server.js +99 -0
  173. package/lib/runtime/http/node-server.test.d.ts +1 -0
  174. package/lib/runtime/http/node-server.test.js +96 -0
  175. package/lib/runtime/http/node-sink.d.ts +16 -0
  176. package/lib/runtime/http/node-sink.js +48 -0
  177. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  178. package/lib/runtime/http/node-sink.test.js +66 -0
  179. package/lib/runtime/http/request.d.ts +62 -0
  180. package/lib/runtime/http/request.js +134 -0
  181. package/lib/runtime/http/request.test.d.ts +1 -0
  182. package/lib/runtime/http/request.test.js +103 -0
  183. package/lib/runtime/http/response.d.ts +77 -0
  184. package/lib/runtime/http/response.js +229 -0
  185. package/lib/runtime/http/response.test.d.ts +1 -0
  186. package/lib/runtime/http/response.test.js +178 -0
  187. package/lib/runtime/http/sink.d.ts +73 -0
  188. package/lib/runtime/http/sink.js +188 -0
  189. package/lib/runtime/http/sink.test.d.ts +1 -0
  190. package/lib/runtime/http/sink.test.js +257 -0
  191. package/lib/runtime/image-utils.d.ts +78 -0
  192. package/lib/runtime/image-utils.js +129 -0
  193. package/lib/runtime/image-utils.test.d.ts +1 -0
  194. package/lib/runtime/image-utils.test.js +237 -0
  195. package/lib/runtime/image.d.ts +76 -0
  196. package/lib/runtime/image.js +296 -0
  197. package/lib/runtime/image.test.d.ts +1 -0
  198. package/lib/runtime/image.test.js +405 -0
  199. package/lib/runtime/lambda-event.d.ts +4 -0
  200. package/lib/runtime/lambda-event.js +113 -0
  201. package/lib/runtime/lambda-event.test.d.ts +1 -0
  202. package/lib/runtime/lambda-event.test.js +119 -0
  203. package/lib/runtime/lambda.mjs +41600 -0
  204. package/lib/runtime/load-module.d.ts +8 -0
  205. package/lib/runtime/load-module.js +35 -0
  206. package/lib/runtime/manifest.d.ts +215 -0
  207. package/lib/runtime/manifest.js +118 -0
  208. package/lib/runtime/middleware.d.ts +43 -0
  209. package/lib/runtime/middleware.js +113 -0
  210. package/lib/runtime/middleware.test.d.ts +1 -0
  211. package/lib/runtime/middleware.test.js +259 -0
  212. package/lib/runtime/next-modules.d.ts +71 -0
  213. package/lib/runtime/next-modules.js +144 -0
  214. package/lib/runtime/next-modules.test.d.ts +1 -0
  215. package/lib/runtime/next-modules.test.js +34 -0
  216. package/lib/runtime/public-files.d.ts +32 -0
  217. package/lib/runtime/public-files.js +117 -0
  218. package/lib/runtime/public-files.test.d.ts +1 -0
  219. package/lib/runtime/public-files.test.js +97 -0
  220. package/lib/runtime/server.mjs +41593 -0
  221. package/lib/runtime/static-files.d.ts +50 -0
  222. package/lib/runtime/static-files.js +266 -0
  223. package/lib/runtime/static-files.test.d.ts +1 -0
  224. package/lib/runtime/static-files.test.js +118 -0
  225. package/lib/runtime/util.d.ts +28 -0
  226. package/lib/runtime/util.js +79 -0
  227. package/lib/utils/base-path.d.ts +106 -13
  228. package/lib/utils/base-path.js +254 -41
  229. package/lib/utils/base-path.test.js +219 -51
  230. package/lib/utils/get-architecture.d.ts +7 -8
  231. package/lib/utils/get-architecture.js +12 -13
  232. package/lib/utils/zip-directory.d.ts +14 -0
  233. package/lib/utils/zip-directory.js +121 -0
  234. package/lib/utils/zip-directory.test.d.ts +1 -0
  235. package/lib/utils/zip-directory.test.js +99 -0
  236. package/package.json +22 -3
  237. package/scripts/capture-adapter-fixture.mjs +325 -0
  238. package/scripts/e2e-deploy.sh +398 -0
  239. package/scripts/e2e-harness/README.md +707 -0
  240. package/scripts/e2e-harness/app.js +370 -0
  241. package/scripts/e2e-harness/common.sh +249 -0
  242. package/scripts/e2e-harness/screen.mjs +302 -0
  243. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  244. package/scripts/e2e-harness/type-filters.mjs +47 -0
  245. package/scripts/e2e-logs.sh +75 -0
  246. package/scripts/e2e-offline.sh +91 -0
  247. package/scripts/e2e-sweep.sh +370 -0
  248. package/scripts/e2e-warm.sh +114 -0
  249. package/scripts/zero-config-build.mjs +418 -0
  250. package/docs/1k-concurrent-users-executions.png +0 -0
  251. package/docs/plans/adapter-runtime-release.md +0 -362
  252. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  253. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  254. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  255. package/lib/image-optimization/handler-utils.d.ts +0 -34
  256. package/lib/image-optimization/handler-utils.js +0 -83
  257. package/lib/image-optimization/handler-utils.test.js +0 -178
  258. package/lib/nextjs-build/functions.Dockerfile +0 -31
  259. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  260. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  261. package/lib/utils/experimental-flags.d.ts +0 -24
  262. package/lib/utils/experimental-flags.js +0 -30
  263. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
@@ -827,40 +827,133 @@ var import_client_s3 = require("@aws-sdk/client-s3");
827
827
  var import_debug = __toESM(require_src());
828
828
  var debug = (0, import_debug.default)("cdk-nextjs:post-deploy:prune-cache-bucket");
829
829
  var s3Client = new import_client_s3.S3Client();
830
+ var PRUNE_BUDGET_MS = 3 * 6e4;
830
831
  async function pruneCacheBucket(props) {
831
832
  const { bucketName, currentBuildId } = props;
833
+ const deadline = Date.now() + PRUNE_BUDGET_MS;
834
+ const oldPrefixes = [];
835
+ let deleted = 0;
836
+ let continuationToken;
837
+ do {
838
+ const page = await s3Client.send(
839
+ new import_client_s3.ListObjectsV2Command({
840
+ Bucket: bucketName,
841
+ Delimiter: "/",
842
+ ContinuationToken: continuationToken
843
+ })
844
+ );
845
+ for (const { Prefix } of page.CommonPrefixes ?? []) {
846
+ if (Prefix && Prefix !== `${currentBuildId}/`) oldPrefixes.push(Prefix);
847
+ }
848
+ deleted += await deleteObjects(bucketName, page.Contents);
849
+ continuationToken = page.NextContinuationToken;
850
+ } while (continuationToken);
851
+ debug(`Found ${oldPrefixes.length} old build prefixes to delete`);
852
+ for (const [i, prefix] of oldPrefixes.entries()) {
853
+ continuationToken = void 0;
854
+ do {
855
+ if (Date.now() > deadline) {
856
+ console.warn(
857
+ `Cache bucket pruning stopped at its time budget after deleting ${deleted} objects; ${oldPrefixes.length - i} old build prefixes are left for the next deploy`
858
+ );
859
+ return;
860
+ }
861
+ const page = await s3Client.send(
862
+ new import_client_s3.ListObjectsV2Command({
863
+ Bucket: bucketName,
864
+ Prefix: prefix,
865
+ ContinuationToken: continuationToken
866
+ })
867
+ );
868
+ deleted += await deleteObjects(bucketName, page.Contents);
869
+ continuationToken = page.NextContinuationToken;
870
+ } while (continuationToken);
871
+ }
872
+ debug(
873
+ `Cache bucket pruning complete. Deleted ${deleted} objects from ${bucketName}`
874
+ );
875
+ }
876
+ async function deleteObjects(bucketName, contents = []) {
877
+ const objects = contents.filter((obj) => obj.Key).map((obj) => ({ Key: obj.Key }));
878
+ if (objects.length === 0) return 0;
879
+ try {
880
+ debug(
881
+ `Deleting cache objects: ${objects.map((o) => o.Key)} from ${bucketName}`
882
+ );
883
+ await s3Client.send(
884
+ new import_client_s3.DeleteObjectsCommand({
885
+ Bucket: bucketName,
886
+ Delete: { Objects: objects }
887
+ })
888
+ );
889
+ } catch (error) {
890
+ console.error("Error deleting cache objects:", error);
891
+ }
892
+ return objects.length;
893
+ }
894
+
895
+ // src/lambdas/post-deploy/prune-revalidation-table.ts
896
+ var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
897
+ var import_debug3 = __toESM(require_src());
898
+
899
+ // src/lambdas/post-deploy/prune-s3.ts
900
+ var import_client_s32 = require("@aws-sdk/client-s3");
901
+ var import_debug2 = __toESM(require_src());
902
+ var debug2 = (0, import_debug2.default)("cdk-nextjs:post-deploy:prune-s3");
903
+ var s3Client2 = new import_client_s32.S3Client();
904
+ var MAX_CONCURRENT_OPERATIONS = 50;
905
+ var BUILD_ID_METADATA_KEY = "build_id";
906
+ async function pruneS3(props) {
907
+ const { bucketName, currentBuildId, msTtl, keyPrefix } = props;
908
+ const bare = (keyPrefix || "").replace(/^\/+/, "").replace(/\/+$/, "");
909
+ const prefix = bare ? `${bare}/_next/` : "_next/";
910
+ const cutoffDate = new Date(Date.now() - msTtl);
832
911
  const objectsToDelete = [];
833
912
  let continuationToken = void 0;
834
913
  let listObjectsCount = 0;
835
914
  do {
836
915
  const listObjectsV2Input = {
837
916
  Bucket: bucketName,
838
- ContinuationToken: continuationToken
917
+ ContinuationToken: continuationToken,
918
+ Prefix: prefix
839
919
  };
840
- const listResponse = await s3Client.send(
841
- new import_client_s3.ListObjectsV2Command(listObjectsV2Input)
920
+ const listResponse = await s3Client2.send(
921
+ new import_client_s32.ListObjectsV2Command(listObjectsV2Input)
842
922
  );
843
- if (!listResponse.Contents || listResponse.Contents.length === 0) {
844
- break;
845
- }
846
- const oldCacheObjects = listResponse.Contents.filter((obj) => {
847
- if (!obj.Key) return false;
848
- const buildIdMatch = obj.Key.match(/^([^\/]+)\//);
849
- if (buildIdMatch) {
850
- const objectBuildId = buildIdMatch[1];
851
- return objectBuildId !== currentBuildId;
852
- }
853
- return true;
923
+ const contents = listResponse.Contents ?? [];
924
+ const oldObjects = contents.filter((obj) => {
925
+ const lastModified = obj.LastModified || /* @__PURE__ */ new Date();
926
+ return obj.Key && lastModified < cutoffDate;
854
927
  });
855
- debug(
856
- `Found ${oldCacheObjects.length} cache objects with old BUILD_ID prefixes to delete`
928
+ debug2(
929
+ `Checking old objects metadata to determine pruning: ${oldObjects.map((o) => o.Key)}`
930
+ );
931
+ const checkResults = await processBatch(
932
+ oldObjects,
933
+ MAX_CONCURRENT_OPERATIONS,
934
+ async (object) => {
935
+ if (!object.Key) return null;
936
+ try {
937
+ const headResponse = await s3Client2.send(
938
+ new import_client_s32.HeadObjectCommand({
939
+ Bucket: bucketName,
940
+ Key: object.Key
941
+ })
942
+ );
943
+ const objectBuildId = headResponse.Metadata?.[BUILD_ID_METADATA_KEY];
944
+ if (objectBuildId && objectBuildId !== currentBuildId) {
945
+ return { Key: object.Key };
946
+ }
947
+ } catch (error) {
948
+ console.error(`Error checking object ${object.Key}:`, error);
949
+ }
950
+ return null;
951
+ }
857
952
  );
858
953
  objectsToDelete.push(
859
- ...oldCacheObjects.filter((obj) => obj.Key).map((obj) => ({ Key: obj.Key }))
954
+ ...checkResults.filter(Boolean)
860
955
  );
861
- if (listResponse.NextContinuationToken) {
862
- continuationToken = listResponse.NextContinuationToken;
863
- }
956
+ continuationToken = listResponse.NextContinuationToken;
864
957
  listObjectsCount++;
865
958
  } while (continuationToken && listObjectsCount <= 100);
866
959
  if (objectsToDelete.length > 0) {
@@ -875,24 +968,24 @@ async function pruneCacheBucket(props) {
875
968
  // Process up to 5 delete batches in parallel
876
969
  async (batch) => {
877
970
  try {
878
- debug(
879
- `Deleting cache objects: ${batch.map((b) => b.Key)} from ${bucketName}`
971
+ debug2(
972
+ `Deleting objects: ${batch.map((b) => b.Key)} from ${bucketName}`
880
973
  );
881
- await s3Client.send(
882
- new import_client_s3.DeleteObjectsCommand({
974
+ await s3Client2.send(
975
+ new import_client_s32.DeleteObjectsCommand({
883
976
  Bucket: bucketName,
884
977
  Delete: { Objects: batch }
885
978
  })
886
979
  );
887
- debug(`Deleted ${batch.length} cache objects from ${bucketName}`);
980
+ debug2(`Deleted ${batch.length} objects from ${bucketName}`);
888
981
  } catch (error) {
889
- console.error("Error deleting cache objects:", error);
982
+ console.error("Error deleting objects:", error);
890
983
  }
891
984
  }
892
985
  );
893
986
  }
894
- debug(
895
- `Cache bucket pruning complete. Deleted ${objectsToDelete.length} objects from ${bucketName}`
987
+ debug2(
988
+ `Pruning complete. Deleted ${objectsToDelete.length} objects from ${bucketName}`
896
989
  );
897
990
  }
898
991
  async function processBatch(items, batchSize, processFn) {
@@ -906,9 +999,7 @@ async function processBatch(items, batchSize, processFn) {
906
999
  }
907
1000
 
908
1001
  // src/lambdas/post-deploy/prune-revalidation-table.ts
909
- var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
910
- var import_debug2 = __toESM(require_src());
911
- var debug2 = (0, import_debug2.default)("cdk-nextjs:post-deploy:prune-revalidation-table");
1002
+ var debug3 = (0, import_debug3.default)("cdk-nextjs:post-deploy:prune-revalidation-table");
912
1003
  var dynamoClient = new import_client_dynamodb.DynamoDBClient();
913
1004
  async function pruneRevalidationTable(props) {
914
1005
  const { tableName, currentBuildId } = props;
@@ -924,34 +1015,34 @@ async function pruneRevalidationTable(props) {
924
1015
  const metadataResponse = await dynamoClient.send(getCommand);
925
1016
  previousBuildId = metadataResponse.Item?.buildId?.S;
926
1017
  } catch (error) {
927
- debug2("No metadata entry found, this may be the first deployment");
1018
+ debug3("No metadata entry found, this may be the first deployment");
928
1019
  }
929
1020
  if (!previousBuildId) {
930
- debug2("No previous build to prune");
1021
+ debug3("No previous build to prune");
931
1022
  await updateMetadata(tableName, currentBuildId);
932
1023
  return;
933
1024
  }
934
1025
  if (previousBuildId === currentBuildId) {
935
- debug2(
1026
+ debug3(
936
1027
  `Previous build ID matches current build ID (${currentBuildId}), nothing to prune`
937
1028
  );
938
1029
  return;
939
1030
  }
940
- debug2(`Pruning revalidation entries for previous build: ${previousBuildId}`);
1031
+ debug3(`Pruning revalidation entries for previous build: ${previousBuildId}`);
941
1032
  const itemsToDelete = [];
942
- let lastEvaluatedKey = void 0;
943
- do {
944
- const queryCommand = new import_client_dynamodb.QueryCommand({
945
- TableName: tableName,
946
- KeyConditionExpression: "pk = :pk",
947
- ExpressionAttributeValues: {
948
- ":pk": { S: previousBuildId }
949
- },
950
- ExclusiveStartKey: lastEvaluatedKey
951
- });
952
- const response = await dynamoClient.send(queryCommand);
953
- if (response.Items && response.Items.length > 0) {
954
- for (const item of response.Items) {
1033
+ for (const pk of [previousBuildId, `${previousBuildId}#log`]) {
1034
+ let lastEvaluatedKey = void 0;
1035
+ do {
1036
+ const queryCommand = new import_client_dynamodb.QueryCommand({
1037
+ TableName: tableName,
1038
+ KeyConditionExpression: "pk = :pk",
1039
+ ExpressionAttributeValues: {
1040
+ ":pk": { S: pk }
1041
+ },
1042
+ ExclusiveStartKey: lastEvaluatedKey
1043
+ });
1044
+ const response = await dynamoClient.send(queryCommand);
1045
+ for (const item of response.Items ?? []) {
955
1046
  if (item.pk?.S && item.sk?.S) {
956
1047
  itemsToDelete.push({
957
1048
  pk: { S: item.pk.S },
@@ -959,10 +1050,10 @@ async function pruneRevalidationTable(props) {
959
1050
  });
960
1051
  }
961
1052
  }
962
- }
963
- lastEvaluatedKey = response.LastEvaluatedKey;
964
- } while (lastEvaluatedKey);
965
- debug2(
1053
+ lastEvaluatedKey = response.LastEvaluatedKey;
1054
+ } while (lastEvaluatedKey);
1055
+ }
1056
+ debug3(
966
1057
  `Found ${itemsToDelete.length} revalidation entries to delete for build ${previousBuildId}`
967
1058
  );
968
1059
  if (itemsToDelete.length > 0) {
@@ -971,7 +1062,7 @@ async function pruneRevalidationTable(props) {
971
1062
  const batch = itemsToDelete.slice(i, i + 25);
972
1063
  deleteBatches.push(batch);
973
1064
  }
974
- await processBatch2(
1065
+ await processBatch(
975
1066
  deleteBatches,
976
1067
  5,
977
1068
  // Process up to 5 delete batches in parallel
@@ -982,7 +1073,7 @@ async function pruneRevalidationTable(props) {
982
1073
  Key: item
983
1074
  }
984
1075
  }));
985
- debug2(
1076
+ debug3(
986
1077
  `Deleting revalidation entries: ${batch.map((b) => `${b.pk.S}/${b.sk.S}`).join(", ")} from ${tableName}`
987
1078
  );
988
1079
  await dynamoClient.send(
@@ -992,7 +1083,7 @@ async function pruneRevalidationTable(props) {
992
1083
  }
993
1084
  })
994
1085
  );
995
- debug2(
1086
+ debug3(
996
1087
  `Deleted ${batch.length} revalidation entries from ${tableName}`
997
1088
  );
998
1089
  } catch (error) {
@@ -1002,7 +1093,7 @@ async function pruneRevalidationTable(props) {
1002
1093
  );
1003
1094
  }
1004
1095
  await updateMetadata(tableName, currentBuildId);
1005
- debug2(
1096
+ debug3(
1006
1097
  `Revalidation table pruning complete. Deleted ${itemsToDelete.length} entries from ${tableName}`
1007
1098
  );
1008
1099
  }
@@ -1017,119 +1108,7 @@ async function updateMetadata(tableName, currentBuildId) {
1017
1108
  }
1018
1109
  });
1019
1110
  await dynamoClient.send(putCommand);
1020
- debug2(`Updated metadata with current build ID: ${currentBuildId}`);
1021
- }
1022
- async function processBatch2(items, batchSize, processFn) {
1023
- const results = [];
1024
- for (let i = 0; i < items.length; i += batchSize) {
1025
- const batch = items.slice(i, i + batchSize);
1026
- const batchResults = await Promise.all(batch.map(processFn));
1027
- results.push(...batchResults);
1028
- }
1029
- return results;
1030
- }
1031
-
1032
- // src/lambdas/post-deploy/prune-s3.ts
1033
- var import_client_s32 = require("@aws-sdk/client-s3");
1034
- var import_debug3 = __toESM(require_src());
1035
- var debug3 = (0, import_debug3.default)("cdk-nextjs:post-deploy:prune-s3");
1036
- var s3Client2 = new import_client_s32.S3Client();
1037
- var MAX_CONCURRENT_OPERATIONS = 50;
1038
- async function pruneS3(props) {
1039
- const { bucketName, currentBuildId, msTtl, keyPrefix } = props;
1040
- const bare = (keyPrefix || "").replace(/^\/+/, "").replace(/\/+$/, "");
1041
- const prefix = bare ? `${bare}/` : void 0;
1042
- const cutoffDate = new Date(Date.now() - msTtl);
1043
- const objectsToDelete = [];
1044
- let continuationToken = void 0;
1045
- let listObjectsCount = 0;
1046
- do {
1047
- const listObjectsV2Input = {
1048
- Bucket: bucketName,
1049
- ContinuationToken: continuationToken,
1050
- Prefix: prefix
1051
- };
1052
- const listResponse = await s3Client2.send(
1053
- new import_client_s32.ListObjectsV2Command(listObjectsV2Input)
1054
- );
1055
- if (!listResponse.Contents || listResponse.Contents.length === 0) {
1056
- break;
1057
- }
1058
- const oldObjects = listResponse.Contents.filter((obj) => {
1059
- const lastModified = obj.LastModified || /* @__PURE__ */ new Date();
1060
- return obj.Key && lastModified < cutoffDate;
1061
- });
1062
- debug3(
1063
- `Checking old objects metadata to determine pruning: ${oldObjects.map((o) => o.Key)}`
1064
- );
1065
- const checkResults = await processBatch3(
1066
- oldObjects,
1067
- MAX_CONCURRENT_OPERATIONS,
1068
- async (object) => {
1069
- if (!object.Key) return null;
1070
- try {
1071
- const headResponse = await s3Client2.send(
1072
- new import_client_s32.HeadObjectCommand({
1073
- Bucket: bucketName,
1074
- Key: object.Key
1075
- })
1076
- );
1077
- const objectBuildId = headResponse.Metadata?.["next-build-id"];
1078
- if (objectBuildId !== currentBuildId) {
1079
- return { Key: object.Key };
1080
- }
1081
- } catch (error) {
1082
- console.error(`Error checking object ${object.Key}:`, error);
1083
- }
1084
- return null;
1085
- }
1086
- );
1087
- objectsToDelete.push(
1088
- ...checkResults.filter(Boolean)
1089
- );
1090
- continuationToken = listResponse.NextContinuationToken;
1091
- listObjectsCount++;
1092
- } while (continuationToken && listObjectsCount <= 100);
1093
- if (objectsToDelete.length > 0) {
1094
- const deleteBatches = [];
1095
- for (let i = 0; i < objectsToDelete.length; i += 1e3) {
1096
- const batch = objectsToDelete.slice(i, i + 1e3);
1097
- deleteBatches.push(batch);
1098
- }
1099
- await processBatch3(
1100
- deleteBatches,
1101
- 5,
1102
- // Process up to 5 delete batches in parallel
1103
- async (batch) => {
1104
- try {
1105
- debug3(
1106
- `Deleting objects: ${batch.map((b) => b.Key)} from ${bucketName}`
1107
- );
1108
- await s3Client2.send(
1109
- new import_client_s32.DeleteObjectsCommand({
1110
- Bucket: bucketName,
1111
- Delete: { Objects: batch }
1112
- })
1113
- );
1114
- debug3(`Deleted ${batch.length} objects from ${bucketName}`);
1115
- } catch (error) {
1116
- console.error("Error deleting objects:", error);
1117
- }
1118
- }
1119
- );
1120
- }
1121
- debug3(
1122
- `Pruning complete. Deleted ${objectsToDelete.length} objects from ${bucketName}`
1123
- );
1124
- }
1125
- async function processBatch3(items, batchSize, processFn) {
1126
- const results = [];
1127
- for (let i = 0; i < items.length; i += batchSize) {
1128
- const batch = items.slice(i, i + batchSize);
1129
- const batchResults = await Promise.all(batch.map(processFn));
1130
- results.push(...batchResults);
1131
- }
1132
- return results;
1111
+ debug3(`Updated metadata with current build ID: ${currentBuildId}`);
1133
1112
  }
1134
1113
 
1135
1114
  // src/lambdas/utils.ts