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.
- package/.jsii +2404 -2723
- package/.jsii.tabl.json +1 -1
- package/API.md +1681 -1930
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +667 -4
- package/docs/caching-guide.md +156 -112
- package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
- package/docs/development-guide.md +1 -1
- package/docs/harness-coverage.md +598 -0
- package/docs/init-cache-deployment.md +32 -1
- package/docs/next-build-output-guide.md +30 -20
- package/examples/README.md +5 -1
- package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
- package/lib/adapter/__fixtures__/app-playground.json +4917 -0
- package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
- package/lib/adapter/adapter.mjs +1551 -185
- package/lib/adapter/adapter.test.js +106 -0
- package/lib/adapter/aws-cache-store.d.ts +489 -0
- package/lib/adapter/aws-cache-store.js +1004 -0
- package/lib/adapter/aws-cache-store.test.d.ts +1 -0
- package/lib/adapter/aws-cache-store.test.js +361 -0
- package/lib/adapter/build-outputs.d.ts +80 -0
- package/lib/adapter/build-outputs.js +857 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +863 -0
- package/lib/adapter/cache-handler.d.ts +9 -2
- package/lib/adapter/cache-handler.js +72 -96
- package/lib/adapter/cache-handler.mjs +18956 -17774
- package/lib/adapter/cache-handler.test.js +263 -31
- package/lib/adapter/cache-kinds.d.ts +32 -0
- package/lib/adapter/cache-kinds.js +35 -0
- package/lib/adapter/cache-kinds.test.d.ts +1 -0
- package/lib/adapter/cache-kinds.test.js +69 -0
- package/lib/adapter/cache-utils.d.ts +90 -0
- package/lib/adapter/cache-utils.js +199 -4
- package/lib/adapter/cache-utils.test.d.ts +1 -0
- package/lib/adapter/cache-utils.test.js +179 -0
- package/lib/adapter/function-groups.d.ts +215 -0
- package/lib/adapter/function-groups.js +1099 -0
- package/lib/adapter/function-groups.test.d.ts +1 -0
- package/lib/adapter/function-groups.test.js +743 -0
- package/lib/adapter/init-cache.d.ts +6 -0
- package/lib/adapter/init-cache.js +245 -0
- package/lib/adapter/init-cache.test.d.ts +1 -0
- package/lib/adapter/init-cache.test.js +137 -0
- package/lib/adapter/local-file-cache-handler.d.ts +23 -0
- package/lib/adapter/local-file-cache-handler.js +52 -1
- package/lib/adapter/memory-cache-handler.d.ts +26 -17
- package/lib/adapter/memory-cache-handler.js +32 -50
- package/lib/adapter/memory-cache-handler.test.js +105 -85
- package/lib/adapter/s3-cache-handler.d.ts +179 -40
- package/lib/adapter/s3-cache-handler.js +807 -277
- package/lib/adapter/s3-cache-handler.test.js +1186 -31
- package/lib/adapter/use-cache-common.d.ts +90 -0
- package/lib/adapter/use-cache-common.js +250 -0
- package/lib/adapter/use-cache-common.test.d.ts +1 -0
- package/lib/adapter/use-cache-common.test.js +646 -0
- package/lib/adapter/use-cache-default-handler.d.ts +24 -0
- package/lib/adapter/use-cache-default-handler.js +90 -0
- package/lib/adapter/use-cache-default-handler.mjs +38645 -0
- package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
- package/lib/adapter/use-cache-handlers.test.js +349 -0
- package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
- package/lib/adapter/use-cache-remote-handler.js +186 -0
- package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
- package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
- package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
- package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
- package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
- package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +8 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +2 -4
- package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
- package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
- package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
- package/lib/lambdas/post-deploy/prune-s3.js +41 -12
- package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
- package/lib/nextjs-api.d.ts +102 -18
- package/lib/nextjs-api.js +338 -38
- package/lib/nextjs-api.test.js +537 -1
- package/lib/nextjs-build/global-containers.Dockerfile +15 -10
- package/lib/nextjs-build/nextjs-build.d.ts +339 -63
- package/lib/nextjs-build/nextjs-build.js +684 -327
- package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
- package/lib/nextjs-build/nextjs-build.test.js +412 -0
- package/lib/nextjs-build/patch-fetch.js +1 -1
- package/lib/nextjs-build/patch-fetch.test.js +166 -11
- package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
- package/lib/nextjs-cache.d.ts +82 -4
- package/lib/nextjs-cache.js +186 -10
- package/lib/nextjs-cache.test.js +176 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
- package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
- package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
- package/lib/nextjs-compute/nextjs-containers.js +57 -20
- package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
- package/lib/nextjs-compute/nextjs-functions.js +113 -67
- package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
- package/lib/nextjs-distribution.d.ts +194 -23
- package/lib/nextjs-distribution.js +535 -62
- package/lib/nextjs-distribution.test.d.ts +1 -0
- package/lib/nextjs-distribution.test.js +697 -0
- package/lib/nextjs-post-deploy.d.ts +13 -5
- package/lib/nextjs-post-deploy.js +13 -10
- package/lib/nextjs-post-deploy.test.d.ts +1 -0
- package/lib/nextjs-post-deploy.test.js +34 -0
- package/lib/nextjs-static-assets.d.ts +17 -4
- package/lib/nextjs-static-assets.js +22 -5
- package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
- package/lib/root-constructs/nextjs-base-construct.js +139 -47
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -71
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -70
- package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
- package/lib/root-constructs/nextjs-regional-containers.js +8 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -26
- package/lib/runtime/api-gateway-path.d.ts +34 -0
- package/lib/runtime/api-gateway-path.js +71 -0
- package/lib/runtime/api-gateway-path.test.d.ts +1 -0
- package/lib/runtime/api-gateway-path.test.js +65 -0
- package/lib/runtime/case-redirect.d.ts +22 -0
- package/lib/runtime/case-redirect.js +63 -0
- package/lib/runtime/case-redirect.test.d.ts +1 -0
- package/lib/runtime/case-redirect.test.js +32 -0
- package/lib/runtime/core.d.ts +234 -0
- package/lib/runtime/core.js +1216 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1686 -0
- package/lib/runtime/deployment-root.d.ts +13 -0
- package/lib/runtime/deployment-root.js +29 -0
- package/lib/runtime/dispatch.d.ts +331 -0
- package/lib/runtime/dispatch.js +751 -0
- package/lib/runtime/dispatch.test.d.ts +1 -0
- package/lib/runtime/dispatch.test.js +853 -0
- package/lib/runtime/entrypoints.d.ts +57 -0
- package/lib/runtime/entrypoints.js +115 -0
- package/lib/runtime/http/abort-signal.d.ts +6 -0
- package/lib/runtime/http/abort-signal.js +19 -0
- package/lib/runtime/http/abort-signal.test.d.ts +1 -0
- package/lib/runtime/http/abort-signal.test.js +49 -0
- package/lib/runtime/http/node-server.d.ts +38 -0
- package/lib/runtime/http/node-server.js +99 -0
- package/lib/runtime/http/node-server.test.d.ts +1 -0
- package/lib/runtime/http/node-server.test.js +96 -0
- package/lib/runtime/http/node-sink.d.ts +16 -0
- package/lib/runtime/http/node-sink.js +48 -0
- package/lib/runtime/http/node-sink.test.d.ts +1 -0
- package/lib/runtime/http/node-sink.test.js +66 -0
- package/lib/runtime/http/request.d.ts +62 -0
- package/lib/runtime/http/request.js +134 -0
- package/lib/runtime/http/request.test.d.ts +1 -0
- package/lib/runtime/http/request.test.js +103 -0
- package/lib/runtime/http/response.d.ts +77 -0
- package/lib/runtime/http/response.js +229 -0
- package/lib/runtime/http/response.test.d.ts +1 -0
- package/lib/runtime/http/response.test.js +178 -0
- package/lib/runtime/http/sink.d.ts +73 -0
- package/lib/runtime/http/sink.js +188 -0
- package/lib/runtime/http/sink.test.d.ts +1 -0
- package/lib/runtime/http/sink.test.js +257 -0
- package/lib/runtime/image-utils.d.ts +78 -0
- package/lib/runtime/image-utils.js +129 -0
- package/lib/runtime/image-utils.test.d.ts +1 -0
- package/lib/runtime/image-utils.test.js +237 -0
- package/lib/runtime/image.d.ts +76 -0
- package/lib/runtime/image.js +296 -0
- package/lib/runtime/image.test.d.ts +1 -0
- package/lib/runtime/image.test.js +405 -0
- package/lib/runtime/lambda-event.d.ts +4 -0
- package/lib/runtime/lambda-event.js +113 -0
- package/lib/runtime/lambda-event.test.d.ts +1 -0
- package/lib/runtime/lambda-event.test.js +119 -0
- package/lib/runtime/lambda.mjs +41600 -0
- package/lib/runtime/load-module.d.ts +8 -0
- package/lib/runtime/load-module.js +35 -0
- package/lib/runtime/manifest.d.ts +215 -0
- package/lib/runtime/manifest.js +118 -0
- package/lib/runtime/middleware.d.ts +43 -0
- package/lib/runtime/middleware.js +113 -0
- package/lib/runtime/middleware.test.d.ts +1 -0
- package/lib/runtime/middleware.test.js +259 -0
- package/lib/runtime/next-modules.d.ts +71 -0
- package/lib/runtime/next-modules.js +144 -0
- package/lib/runtime/next-modules.test.d.ts +1 -0
- package/lib/runtime/next-modules.test.js +34 -0
- package/lib/runtime/public-files.d.ts +32 -0
- package/lib/runtime/public-files.js +117 -0
- package/lib/runtime/public-files.test.d.ts +1 -0
- package/lib/runtime/public-files.test.js +97 -0
- package/lib/runtime/server.mjs +41593 -0
- package/lib/runtime/static-files.d.ts +50 -0
- package/lib/runtime/static-files.js +266 -0
- package/lib/runtime/static-files.test.d.ts +1 -0
- package/lib/runtime/static-files.test.js +118 -0
- package/lib/runtime/util.d.ts +28 -0
- package/lib/runtime/util.js +79 -0
- package/lib/utils/base-path.d.ts +106 -13
- package/lib/utils/base-path.js +254 -41
- package/lib/utils/base-path.test.js +219 -51
- package/lib/utils/get-architecture.d.ts +7 -8
- package/lib/utils/get-architecture.js +12 -13
- package/lib/utils/zip-directory.d.ts +14 -0
- package/lib/utils/zip-directory.js +121 -0
- package/lib/utils/zip-directory.test.d.ts +1 -0
- package/lib/utils/zip-directory.test.js +99 -0
- package/package.json +22 -3
- package/scripts/capture-adapter-fixture.mjs +325 -0
- package/scripts/e2e-deploy.sh +398 -0
- package/scripts/e2e-harness/README.md +707 -0
- package/scripts/e2e-harness/app.js +370 -0
- package/scripts/e2e-harness/common.sh +249 -0
- package/scripts/e2e-harness/screen.mjs +302 -0
- package/scripts/e2e-harness/stage-proxy.mjs +145 -0
- package/scripts/e2e-harness/type-filters.mjs +47 -0
- package/scripts/e2e-logs.sh +75 -0
- package/scripts/e2e-offline.sh +91 -0
- package/scripts/e2e-sweep.sh +370 -0
- package/scripts/e2e-warm.sh +114 -0
- package/scripts/zero-config-build.mjs +418 -0
- package/docs/1k-concurrent-users-executions.png +0 -0
- package/docs/plans/adapter-runtime-release.md +0 -362
- package/docs/plans/phase-0-image-function-opt-in.md +0 -295
- package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
- package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
- package/lib/image-optimization/handler-utils.d.ts +0 -34
- package/lib/image-optimization/handler-utils.js +0 -83
- package/lib/image-optimization/handler-utils.test.js +0 -178
- package/lib/nextjs-build/functions.Dockerfile +0 -31
- package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
- package/lib/nextjs-compute/nextjs-image-function.js +0 -59
- package/lib/utils/experimental-flags.d.ts +0 -24
- package/lib/utils/experimental-flags.js +0 -30
- /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
|
|
841
|
-
new
|
|
920
|
+
const listResponse = await s3Client2.send(
|
|
921
|
+
new import_client_s32.ListObjectsV2Command(listObjectsV2Input)
|
|
842
922
|
);
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
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
|
-
|
|
856
|
-
`
|
|
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
|
-
...
|
|
954
|
+
...checkResults.filter(Boolean)
|
|
860
955
|
);
|
|
861
|
-
|
|
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
|
-
|
|
879
|
-
`Deleting
|
|
971
|
+
debug2(
|
|
972
|
+
`Deleting objects: ${batch.map((b) => b.Key)} from ${bucketName}`
|
|
880
973
|
);
|
|
881
|
-
await
|
|
882
|
-
new
|
|
974
|
+
await s3Client2.send(
|
|
975
|
+
new import_client_s32.DeleteObjectsCommand({
|
|
883
976
|
Bucket: bucketName,
|
|
884
977
|
Delete: { Objects: batch }
|
|
885
978
|
})
|
|
886
979
|
);
|
|
887
|
-
|
|
980
|
+
debug2(`Deleted ${batch.length} objects from ${bucketName}`);
|
|
888
981
|
} catch (error) {
|
|
889
|
-
console.error("Error deleting
|
|
982
|
+
console.error("Error deleting objects:", error);
|
|
890
983
|
}
|
|
891
984
|
}
|
|
892
985
|
);
|
|
893
986
|
}
|
|
894
|
-
|
|
895
|
-
`
|
|
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
|
|
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
|
-
|
|
1018
|
+
debug3("No metadata entry found, this may be the first deployment");
|
|
928
1019
|
}
|
|
929
1020
|
if (!previousBuildId) {
|
|
930
|
-
|
|
1021
|
+
debug3("No previous build to prune");
|
|
931
1022
|
await updateMetadata(tableName, currentBuildId);
|
|
932
1023
|
return;
|
|
933
1024
|
}
|
|
934
1025
|
if (previousBuildId === currentBuildId) {
|
|
935
|
-
|
|
1026
|
+
debug3(
|
|
936
1027
|
`Previous build ID matches current build ID (${currentBuildId}), nothing to prune`
|
|
937
1028
|
);
|
|
938
1029
|
return;
|
|
939
1030
|
}
|
|
940
|
-
|
|
1031
|
+
debug3(`Pruning revalidation entries for previous build: ${previousBuildId}`);
|
|
941
1032
|
const itemsToDelete = [];
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
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
|
-
|
|
964
|
-
}
|
|
965
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|