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.
- 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 +1548 -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 +852 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +861 -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 +1213 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1678 -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 +41595 -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 +55 -0
- package/lib/runtime/next-modules.js +124 -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 +41588 -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
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { EventBridgeHandler } from "aws-lambda";
|
|
2
|
+
/**
|
|
3
|
+
* The `detail` of a "CloudFormation Stack Status Change" event, as documented
|
|
4
|
+
* in the CloudFormation User Guide ("Stack Status Change event detail").
|
|
5
|
+
*/
|
|
6
|
+
interface StackStatusChangeDetail {
|
|
7
|
+
readonly "stack-id": string;
|
|
8
|
+
readonly "status-details": {
|
|
9
|
+
readonly status: string;
|
|
10
|
+
readonly "status-reason"?: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Invoked by `NextjsApi`'s EventBridge rule when its stack finishes an update;
|
|
15
|
+
* see {@link redeployStage}. The API and stage come from the environment rather
|
|
16
|
+
* than the event: the rule only matches this stack, and the event names the
|
|
17
|
+
* stack, not the API.
|
|
18
|
+
*/
|
|
19
|
+
export declare const handler: EventBridgeHandler<"CloudFormation Stack Status Change", StackStatusChangeDetail, void>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handler = void 0;
|
|
4
|
+
const redeploy_stage_1 = require("./redeploy-stage");
|
|
5
|
+
/**
|
|
6
|
+
* Invoked by `NextjsApi`'s EventBridge rule when its stack finishes an update;
|
|
7
|
+
* see {@link redeployStage}. The API and stage come from the environment rather
|
|
8
|
+
* than the event: the rule only matches this stack, and the event names the
|
|
9
|
+
* stack, not the API.
|
|
10
|
+
*/
|
|
11
|
+
const handler = async (event) => {
|
|
12
|
+
const restApiId = process.env.REST_API_ID;
|
|
13
|
+
const stageName = process.env.STAGE_NAME;
|
|
14
|
+
if (!restApiId || !stageName) {
|
|
15
|
+
throw new Error("REST_API_ID and STAGE_NAME must be set.");
|
|
16
|
+
}
|
|
17
|
+
await (0, redeploy_stage_1.redeployStage)({
|
|
18
|
+
restApiId,
|
|
19
|
+
stageName,
|
|
20
|
+
stackStatus: event.detail["status-details"].status,
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
exports.handler = handler;
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkZXBsb3ktc3RhZ2UubGFtYmRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xhbWJkYXMvcmVkZXBsb3ktc3RhZ2UvcmVkZXBsb3ktc3RhZ2UubGFtYmRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFEQUFpRDtBQWNqRDs7Ozs7R0FLRztBQUNJLE1BQU0sT0FBTyxHQUloQixLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7SUFDbEIsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7SUFDekMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQzdCLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBQ0QsTUFBTSxJQUFBLDhCQUFhLEVBQUM7UUFDbEIsU0FBUztRQUNULFNBQVM7UUFDVCxXQUFXLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE1BQU07S0FDbkQsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBZlcsUUFBQSxPQUFPLFdBZWxCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBFdmVudEJyaWRnZUhhbmRsZXIgfSBmcm9tIFwiYXdzLWxhbWJkYVwiO1xuaW1wb3J0IHsgcmVkZXBsb3lTdGFnZSB9IGZyb20gXCIuL3JlZGVwbG95LXN0YWdlXCI7XG5cbi8qKlxuICogVGhlIGBkZXRhaWxgIG9mIGEgXCJDbG91ZEZvcm1hdGlvbiBTdGFjayBTdGF0dXMgQ2hhbmdlXCIgZXZlbnQsIGFzIGRvY3VtZW50ZWRcbiAqIGluIHRoZSBDbG91ZEZvcm1hdGlvbiBVc2VyIEd1aWRlIChcIlN0YWNrIFN0YXR1cyBDaGFuZ2UgZXZlbnQgZGV0YWlsXCIpLlxuICovXG5pbnRlcmZhY2UgU3RhY2tTdGF0dXNDaGFuZ2VEZXRhaWwge1xuICByZWFkb25seSBcInN0YWNrLWlkXCI6IHN0cmluZztcbiAgcmVhZG9ubHkgXCJzdGF0dXMtZGV0YWlsc1wiOiB7XG4gICAgcmVhZG9ubHkgc3RhdHVzOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgXCJzdGF0dXMtcmVhc29uXCI/OiBzdHJpbmc7XG4gIH07XG59XG5cbi8qKlxuICogSW52b2tlZCBieSBgTmV4dGpzQXBpYCdzIEV2ZW50QnJpZGdlIHJ1bGUgd2hlbiBpdHMgc3RhY2sgZmluaXNoZXMgYW4gdXBkYXRlO1xuICogc2VlIHtAbGluayByZWRlcGxveVN0YWdlfS4gVGhlIEFQSSBhbmQgc3RhZ2UgY29tZSBmcm9tIHRoZSBlbnZpcm9ubWVudCByYXRoZXJcbiAqIHRoYW4gdGhlIGV2ZW50OiB0aGUgcnVsZSBvbmx5IG1hdGNoZXMgdGhpcyBzdGFjaywgYW5kIHRoZSBldmVudCBuYW1lcyB0aGVcbiAqIHN0YWNrLCBub3QgdGhlIEFQSS5cbiAqL1xuZXhwb3J0IGNvbnN0IGhhbmRsZXI6IEV2ZW50QnJpZGdlSGFuZGxlcjxcbiAgXCJDbG91ZEZvcm1hdGlvbiBTdGFjayBTdGF0dXMgQ2hhbmdlXCIsXG4gIFN0YWNrU3RhdHVzQ2hhbmdlRGV0YWlsLFxuICB2b2lkXG4+ID0gYXN5bmMgKGV2ZW50KSA9PiB7XG4gIGNvbnN0IHJlc3RBcGlJZCA9IHByb2Nlc3MuZW52LlJFU1RfQVBJX0lEO1xuICBjb25zdCBzdGFnZU5hbWUgPSBwcm9jZXNzLmVudi5TVEFHRV9OQU1FO1xuICBpZiAoIXJlc3RBcGlJZCB8fCAhc3RhZ2VOYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiUkVTVF9BUElfSUQgYW5kIFNUQUdFX05BTUUgbXVzdCBiZSBzZXQuXCIpO1xuICB9XG4gIGF3YWl0IHJlZGVwbG95U3RhZ2Uoe1xuICAgIHJlc3RBcGlJZCxcbiAgICBzdGFnZU5hbWUsXG4gICAgc3RhY2tTdGF0dXM6IGV2ZW50LmRldGFpbFtcInN0YXR1cy1kZXRhaWxzXCJdLnN0YXR1cyxcbiAgfSk7XG59O1xuIl19
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
4
|
+
// Only the client is mocked; the command classes stay real so assertions can
|
|
5
|
+
// read `command.input`. `send` goes through the holder because the module
|
|
6
|
+
// constructs its client at import time.
|
|
7
|
+
jest.mock("@aws-sdk/client-api-gateway", () => ({
|
|
8
|
+
...jest.requireActual("@aws-sdk/client-api-gateway"),
|
|
9
|
+
APIGatewayClient: jest.fn(() => ({
|
|
10
|
+
send: (...args) => holder.send(...args),
|
|
11
|
+
})),
|
|
12
|
+
}));
|
|
13
|
+
const client_api_gateway_1 = require("@aws-sdk/client-api-gateway");
|
|
14
|
+
const redeploy_stage_1 = require("./redeploy-stage");
|
|
15
|
+
const holder = { send: jest.fn() };
|
|
16
|
+
const input = {
|
|
17
|
+
restApiId: "api1",
|
|
18
|
+
stageName: "prod",
|
|
19
|
+
stackStatus: "UPDATE_COMPLETE",
|
|
20
|
+
};
|
|
21
|
+
/** The API as it is: its deployments (pages of them) and its stages. */
|
|
22
|
+
function stubApi(pages, stages) {
|
|
23
|
+
holder.send.mockImplementation((command) => {
|
|
24
|
+
if (command instanceof client_api_gateway_1.CreateDeploymentCommand) {
|
|
25
|
+
return Promise.resolve({ id: "new" });
|
|
26
|
+
}
|
|
27
|
+
if (command instanceof client_api_gateway_1.GetStagesCommand) {
|
|
28
|
+
return Promise.resolve({ item: stages });
|
|
29
|
+
}
|
|
30
|
+
if (command instanceof client_api_gateway_1.GetDeploymentsCommand) {
|
|
31
|
+
const index = Number(command.input.position ?? 0);
|
|
32
|
+
return Promise.resolve({
|
|
33
|
+
items: pages[index],
|
|
34
|
+
position: index + 1 < pages.length ? String(index + 1) : undefined,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return Promise.resolve({});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function sent(type) {
|
|
41
|
+
return holder.send.mock.calls
|
|
42
|
+
.map(([command]) => command)
|
|
43
|
+
.filter((command) => command instanceof type);
|
|
44
|
+
}
|
|
45
|
+
beforeEach(() => holder.send.mockReset());
|
|
46
|
+
it("deploys the stage from the live API", async () => {
|
|
47
|
+
stubApi([[]], [{ stageName: "prod", deploymentId: "new" }]);
|
|
48
|
+
await expect((0, redeploy_stage_1.redeployStage)(input)).resolves.toBe("new");
|
|
49
|
+
expect(sent(client_api_gateway_1.CreateDeploymentCommand).map((c) => c.input)).toEqual([
|
|
50
|
+
{
|
|
51
|
+
restApiId: "api1",
|
|
52
|
+
stageName: "prod",
|
|
53
|
+
description: `${redeploy_stage_1.REDEPLOY_DESCRIPTION_PREFIX} UPDATE_COMPLETE`,
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
it("deletes only its own earlier deployments no stage references", async () => {
|
|
58
|
+
const ours = (id) => ({
|
|
59
|
+
id,
|
|
60
|
+
description: `${redeploy_stage_1.REDEPLOY_DESCRIPTION_PREFIX} UPDATE_COMPLETE`,
|
|
61
|
+
});
|
|
62
|
+
stubApi([
|
|
63
|
+
// CloudFormation's own, its previous run's, and the new one.
|
|
64
|
+
[
|
|
65
|
+
{
|
|
66
|
+
id: "cfn",
|
|
67
|
+
description: "Automatically created by the RestApi construct",
|
|
68
|
+
},
|
|
69
|
+
ours("prev"),
|
|
70
|
+
],
|
|
71
|
+
// A run whose deployment another stage still serves, on a second page.
|
|
72
|
+
[ours("pinned"), ours("new")],
|
|
73
|
+
], [
|
|
74
|
+
{ stageName: "prod", deploymentId: "new" },
|
|
75
|
+
{ stageName: "canary", deploymentId: "pinned" },
|
|
76
|
+
]);
|
|
77
|
+
await (0, redeploy_stage_1.redeployStage)(input);
|
|
78
|
+
expect(sent(client_api_gateway_1.DeleteDeploymentCommand).map((c) => c.input)).toEqual([
|
|
79
|
+
{ restApiId: "api1", deploymentId: "prev" },
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
it("does not fail the run when a prune is rejected", async () => {
|
|
83
|
+
stubApi([[{ id: "prev", description: `${redeploy_stage_1.REDEPLOY_DESCRIPTION_PREFIX} x` }]], []);
|
|
84
|
+
const warn = jest.spyOn(console, "warn").mockImplementation(() => { });
|
|
85
|
+
const send = holder.send.getMockImplementation();
|
|
86
|
+
holder.send.mockImplementation((command) => command instanceof client_api_gateway_1.DeleteDeploymentCommand
|
|
87
|
+
? Promise.reject(new Error("BadRequestException"))
|
|
88
|
+
: send(command));
|
|
89
|
+
await expect((0, redeploy_stage_1.redeployStage)(input)).resolves.toBe("new");
|
|
90
|
+
expect(warn).toHaveBeenCalled();
|
|
91
|
+
warn.mockRestore();
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkZXBsb3ktc3RhZ2UudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGFzL3JlZGVwbG95LXN0YWdlL3JlZGVwbG95LXN0YWdlLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxzREFBc0Q7QUFDdEQsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSx3Q0FBd0M7QUFDeEMsSUFBSSxDQUFDLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyw2QkFBNkIsQ0FBQztJQUNwRCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDL0IsSUFBSSxFQUFFLENBQUMsR0FBRyxJQUFlLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUM7S0FDbkQsQ0FBQyxDQUFDO0NBQ0osQ0FBQyxDQUFDLENBQUM7QUFFSixvRUFLcUM7QUFDckMscURBQThFO0FBRTlFLE1BQU0sTUFBTSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBRW5DLE1BQU0sS0FBSyxHQUFHO0lBQ1osU0FBUyxFQUFFLE1BQU07SUFDakIsU0FBUyxFQUFFLE1BQU07SUFDakIsV0FBVyxFQUFFLGlCQUFpQjtDQUMvQixDQUFDO0FBRUYsd0VBQXdFO0FBQ3hFLFNBQVMsT0FBTyxDQUNkLEtBQStDLEVBQy9DLE1BQXFEO0lBRXJELE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxPQUFnQixFQUFFLEVBQUU7UUFDbEQsSUFBSSxPQUFPLFlBQVksNENBQXVCLEVBQUUsQ0FBQztZQUMvQyxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN4QyxDQUFDO1FB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c291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG4vLyBPbmx5IHRoZSBjbGllbnQgaXMgbW9ja2VkOyB0aGUgY29tbWFuZCBjbGFzc2VzIHN0YXkgcmVhbCBzbyBhc3NlcnRpb25zIGNhblxuLy8gcmVhZCBgY29tbWFuZC5pbnB1dGAuIGBzZW5kYCBnb2VzIHRocm91Z2ggdGhlIGhvbGRlciBiZWNhdXNlIHRoZSBtb2R1bGVcbi8vIGNvbnN0cnVjdHMgaXRzIGNsaWVudCBhdCBpbXBvcnQgdGltZS5cbmplc3QubW9jayhcIkBhd3Mtc2RrL2NsaWVudC1hcGktZ2F0ZXdheVwiLCAoKSA9PiAoe1xuICAuLi5qZXN0LnJlcXVpcmVBY3R1YWwoXCJAYXdzLXNkay9jbGllbnQtYXBpLWdhdGV3YXlcIiksXG4gIEFQSUdhdGV3YXlDbGllbnQ6IGplc3QuZm4oKCkgPT4gKHtcbiAgICBzZW5kOiAoLi4uYXJnczogdW5rbm93bltdKSA9PiBob2xkZXIuc2VuZCguLi5hcmdzKSxcbiAgfSkpLFxufSkpO1xuXG5pbXBvcnQge1xuICBDcmVhdGVEZXBsb3ltZW50Q29tbWFuZCxcbiAgRGVsZXRlRGVwbG95bWVudENvbW1hbmQsXG4gIEdldERlcGxveW1lbnRzQ29tbWFuZCxcbiAgR2V0U3RhZ2VzQ29tbWFuZCxcbn0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1hcGktZ2F0ZXdheVwiO1xuaW1wb3J0IHsgUkVERVBMT1lfREVTQ1JJUFRJT05fUFJFRklYLCByZWRlcGxveVN0YWdlIH0gZnJvbSBcIi4vcmVkZXBsb3ktc3RhZ2VcIjtcblxuY29uc3QgaG9sZGVyID0geyBzZW5kOiBqZXN0LmZuKCkgfTtcblxuY29uc3QgaW5wdXQgPSB7XG4gIHJlc3RBcGlJZDogXCJhcGkxXCIsXG4gIHN0YWdlTmFtZTogXCJwcm9kXCIsXG4gIHN0YWNrU3RhdHVzOiBcIlVQREFURV9DT01QTEVURVwiLFxufTtcblxuLyoqIFRoZSBBUEkgYXMgaXQgaXM6IGl0cyBkZXBsb3ltZW50cyAocGFnZXMgb2YgdGhlbSkgYW5kIGl0cyBzdGFnZXMuICovXG5mdW5jdGlvbiBzdHViQXBpKFxuICBwYWdlczogeyBpZDogc3RyaW5nOyBkZXNjcmlwdGlvbj86IHN0cmluZyB9W11bXSxcbiAgc3RhZ2VzOiB7IHN0YWdlTmFtZTogc3RyaW5nOyBkZXBsb3ltZW50SWQ6IHN0cmluZyB9W10sXG4pIHtcbiAgaG9sZGVyLnNlbmQubW9ja0ltcGxlbWVudGF0aW9uKChjb21tYW5kOiB1bmtub3duKSA9PiB7XG4gICAgaWYgKGNvbW1hbmQgaW5zdGFuY2VvZiBDcmVhdGVEZXBsb3ltZW50Q29tbWFuZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGlkOiBcIm5ld1wiIH0pO1xuICAgIH1cbiAgICBpZiAoY29tbWFuZCBpbnN0YW5jZW9mIEdldFN0YWdlc0NvbW1hbmQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBpdGVtOiBzdGFnZXMgfSk7XG4gICAgfVxuICAgIGlmIChjb21tYW5kIGluc3RhbmNlb2YgR2V0RGVwbG95bWVudHNDb21tYW5kKSB7XG4gICAgICBjb25zdCBpbmRleCA9IE51bWJlcihjb21tYW5kLmlucHV0LnBvc2l0aW9uID8/IDApO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgIGl0ZW1zOiBwYWdlc1tpbmRleF0sXG4gICAgICAgIHBvc2l0aW9uOiBpbmRleCArIDEgPCBwYWdlcy5sZW5ndGggPyBTdHJpbmcoaW5kZXggKyAxKSA6IHVuZGVmaW5lZCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHNlbnQ8VD4odHlwZTogbmV3ICguLi5hcmdzOiBuZXZlcltdKSA9PiBUKTogVFtdIHtcbiAgcmV0dXJuIGhvbGRlci5zZW5kLm1vY2suY2FsbHNcbiAgICAubWFwKChbY29tbWFuZF0pID0+IGNvbW1hbmQpXG4gICAgLmZpbHRlcigoY29tbWFuZCk6IGNvbW1hbmQgaXMgVCA9PiBjb21tYW5kIGluc3RhbmNlb2YgdHlwZSk7XG59XG5cbmJlZm9yZUVhY2goKCkgPT4gaG9sZGVyLnNlbmQubW9ja1Jlc2V0KCkpO1xuXG5pdChcImRlcGxveXMgdGhlIHN0YWdlIGZyb20gdGhlIGxpdmUgQVBJXCIsIGFzeW5jICgpID0+IHtcbiAgc3R1YkFwaShbW11dLCBbeyBzdGFnZU5hbWU6IFwicHJvZFwiLCBkZXBsb3ltZW50SWQ6IFwibmV3XCIgfV0pO1xuXG4gIGF3YWl0IGV4cGVjdChyZWRlcGxveVN0YWdlKGlucHV0KSkucmVzb2x2ZXMudG9CZShcIm5ld1wiKTtcblxuICBleHBlY3Qoc2VudChDcmVhdGVEZXBsb3ltZW50Q29tbWFuZCkubWFwKChjKSA9PiBjLmlucHV0KSkudG9FcXVhbChbXG4gICAge1xuICAgICAgcmVzdEFwaUlkOiBcImFwaTFcIixcbiAgICAgIHN0YWdlTmFtZTogXCJwcm9kXCIsXG4gICAgICBkZXNjcmlwdGlvbjogYCR7UkVERVBMT1lfREVTQ1JJUFRJT05fUFJFRklYfSBVUERBVEVfQ09NUExFVEVgLFxuICAgIH0sXG4gIF0pO1xufSk7XG5cbml0KFwiZGVsZXRlcyBvbmx5IGl0cyBvd24gZWFybGllciBkZXBsb3ltZW50cyBubyBzdGFnZSByZWZlcmVuY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgY29uc3Qgb3VycyA9IChpZDogc3RyaW5nKSA9PiAoe1xuICAgIGlkLFxuICAgIGRlc2NyaXB0aW9uOiBgJHtSRURFUExPWV9ERVNDUklQVElPTl9QUkVGSVh9IFVQREFURV9DT01QTEVURWAsXG4gIH0pO1xuICBzdHViQXBpKFxuICAgIFtcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uJ3Mgb3duLCBpdHMgcHJldmlvdXMgcnVuJ3MsIGFuZCB0aGUgbmV3IG9uZS5cbiAgICAgIFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiBcImNmblwiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBcIkF1dG9tYXRpY2FsbHkgY3JlYXRlZCBieSB0aGUgUmVzdEFwaSBjb25zdHJ1Y3RcIixcbiAgICAgICAgfSxcbiAgICAgICAgb3VycyhcInByZXZcIiksXG4gICAgICBdLFxuICAgICAgLy8gQSBydW4gd2hvc2UgZGVwbG95bWVudCBhbm90aGVyIHN0YWdlIHN0aWxsIHNlcnZlcywgb24gYSBzZWNvbmQgcGFnZS5cbiAgICAgIFtvdXJzKFwicGlubmVkXCIpLCBvdXJzKFwibmV3XCIpXSxcbiAgICBdLFxuICAgIFtcbiAgICAgIHsgc3RhZ2VOYW1lOiBcInByb2RcIiwgZGVwbG95bWVudElkOiBcIm5ld1wiIH0sXG4gICAgICB7IHN0YWdlTmFtZTogXCJjYW5hcnlcIiwgZGVwbG95bWVudElkOiBcInBpbm5lZFwiIH0sXG4gICAgXSxcbiAgKTtcblxuICBhd2FpdCByZWRlcGxveVN0YWdlKGlucHV0KTtcblxuICBleHBlY3Qoc2VudChEZWxldGVEZXBsb3ltZW50Q29tbWFuZCkubWFwKChjKSA9PiBjLmlucHV0KSkudG9FcXVhbChbXG4gICAgeyByZXN0QXBpSWQ6IFwiYXBpMVwiLCBkZXBsb3ltZW50SWQ6IFwicHJldlwiIH0sXG4gIF0pO1xufSk7XG5cbml0KFwiZG9lcyBub3QgZmFpbCB0aGUgcnVuIHdoZW4gYSBwcnVuZSBpcyByZWplY3RlZFwiLCBhc3luYyAoKSA9PiB7XG4gIHN0dWJBcGkoXG4gICAgW1t7IGlkOiBcInByZXZcIiwgZGVzY3JpcHRpb246IGAke1JFREVQTE9ZX0RFU0NSSVBUSU9OX1BSRUZJWH0geGAgfV1dLFxuICAgIFtdLFxuICApO1xuICBjb25zdCB3YXJuID0gamVzdC5zcHlPbihjb25zb2xlLCBcIndhcm5cIikubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHt9KTtcbiAgY29uc3Qgc2VuZCA9IGhvbGRlci5zZW5kLmdldE1vY2tJbXBsZW1lbnRhdGlvbigpITtcbiAgaG9sZGVyLnNlbmQubW9ja0ltcGxlbWVudGF0aW9uKChjb21tYW5kOiB1bmtub3duKSA9PlxuICAgIGNvbW1hbmQgaW5zdGFuY2VvZiBEZWxldGVEZXBsb3ltZW50Q29tbWFuZFxuICAgICAgPyBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoXCJCYWRSZXF1ZXN0RXhjZXB0aW9uXCIpKVxuICAgICAgOiBzZW5kKGNvbW1hbmQpLFxuICApO1xuXG4gIGF3YWl0IGV4cGVjdChyZWRlcGxveVN0YWdlKGlucHV0KSkucmVzb2x2ZXMudG9CZShcIm5ld1wiKTtcbiAgZXhwZWN0KHdhcm4pLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgd2Fybi5tb2NrUmVzdG9yZSgpO1xufSk7XG4iXX0=
|
package/lib/nextjs-api.d.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { RestApi, MethodOptions, RestApiProps, AwsIntegrationProps, LambdaIntegrationOptions } from "aws-cdk-lib/aws-apigateway";
|
|
2
2
|
import { IVpc } from "aws-cdk-lib/aws-ec2";
|
|
3
|
-
import {
|
|
3
|
+
import { Rule } from "aws-cdk-lib/aws-events";
|
|
4
|
+
import { Function as LambdaFunction, IFunction } from "aws-cdk-lib/aws-lambda";
|
|
4
5
|
import { IBucket } from "aws-cdk-lib/aws-s3";
|
|
5
6
|
import { Construct } from "constructs";
|
|
6
|
-
import {
|
|
7
|
+
import { OptionalFunctionProps } from "./generated-structs/OptionalFunctionProps";
|
|
8
|
+
import { NextjsFunctionGroupBehavior, PublicDirEntry } from "./nextjs-build/nextjs-build";
|
|
7
9
|
export interface NextjsApiOverrides {
|
|
8
10
|
readonly restApiProps?: RestApiProps;
|
|
9
11
|
readonly staticIntegrationProps?: AwsIntegrationProps;
|
|
10
12
|
readonly s3MethodOptions?: MethodOptions;
|
|
11
13
|
readonly dynamicIntegrationProps?: LambdaIntegrationOptions;
|
|
12
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Props for the function that deploys the stage again after each stack
|
|
16
|
+
* update.
|
|
17
|
+
* @see NextjsApiProps.redeployAfterUpdate
|
|
18
|
+
*/
|
|
19
|
+
readonly redeployFunctionProps?: OptionalFunctionProps;
|
|
13
20
|
}
|
|
14
21
|
export interface NextjsApiProps {
|
|
15
22
|
/**
|
|
@@ -29,19 +36,6 @@ export interface NextjsApiProps {
|
|
|
29
36
|
* Required if `NextjsRegionalFunctions`. The Lambda function for server-side rendering
|
|
30
37
|
*/
|
|
31
38
|
readonly serverFunction?: IFunction;
|
|
32
|
-
/**
|
|
33
|
-
* Dedicated image optimization Lambda for the `_next/image` route. When
|
|
34
|
-
* omitted, no `_next/image` resource is created and those requests fall
|
|
35
|
-
* through to `serverFunction` via the `{proxy+}` catch-all.
|
|
36
|
-
*
|
|
37
|
-
* When provided, it is assumed to support Lambda response streaming (as the
|
|
38
|
-
* dedicated image Lambda this package builds does) and is invoked with
|
|
39
|
-
* `ResponseTransferMode.STREAM` accordingly. If you supply a custom
|
|
40
|
-
* `imageFunction` that doesn't support streaming, override
|
|
41
|
-
* `responseTransferMode` to `BUFFERED` via `overrides.imageIntegrationProps`,
|
|
42
|
-
* otherwise API Gateway returns a 502.
|
|
43
|
-
*/
|
|
44
|
-
readonly imageFunction?: IFunction;
|
|
45
39
|
/**
|
|
46
40
|
* The S3 bucket containing static assets
|
|
47
41
|
*/
|
|
@@ -61,6 +55,40 @@ export interface NextjsApiProps {
|
|
|
61
55
|
* [Future] Required if `NextjsRegionalContainers`. VPC to create VPC Link and ECS Service Discovery
|
|
62
56
|
*/
|
|
63
57
|
readonly vpc?: IVpc;
|
|
58
|
+
/**
|
|
59
|
+
* The non-`default` function groups, the Lambdas
|
|
60
|
+
* {@link functionGroupBehaviors} route to.
|
|
61
|
+
* @default - no splitting; `{proxy+}` serves every dynamic route
|
|
62
|
+
*/
|
|
63
|
+
readonly functionGroups?: NextjsApiFunctionGroup[];
|
|
64
|
+
/**
|
|
65
|
+
* `NextjsBuild.functionGroupBehaviors`: each distinct `route` becomes a
|
|
66
|
+
* resource subtree integrated with its group, so the routes each group was
|
|
67
|
+
* packaged with reach it rather than {@link serverFunction}.
|
|
68
|
+
* @default - none
|
|
69
|
+
*/
|
|
70
|
+
readonly functionGroupBehaviors?: NextjsFunctionGroupBehavior[];
|
|
71
|
+
/**
|
|
72
|
+
* Deploy the stage again once each stack update has finished, so it serves
|
|
73
|
+
* the API as it is after the update.
|
|
74
|
+
*
|
|
75
|
+
* CloudFormation snapshots the API into a new deployment while resources
|
|
76
|
+
* removed from the template still exist — it deletes them only during
|
|
77
|
+
* cleanup — so the stage keeps serving them. After removing a function
|
|
78
|
+
* group, its routes then point at a deleted Lambda and answer 500 until the
|
|
79
|
+
* next deployment. An EventBridge rule on this stack's `UPDATE_COMPLETE`
|
|
80
|
+
* (and `UPDATE_ROLLBACK_COMPLETE`) invokes a small function that deploys the
|
|
81
|
+
* stage from the live API and deletes the deployments its earlier runs made.
|
|
82
|
+
*
|
|
83
|
+
* Ignored when `overrides.restApiProps.deploy` is `false`: there is no stage.
|
|
84
|
+
* @default true
|
|
85
|
+
*/
|
|
86
|
+
readonly redeployAfterUpdate?: boolean;
|
|
87
|
+
}
|
|
88
|
+
/** A non-default function group and the Lambda its routes must reach. */
|
|
89
|
+
export interface NextjsApiFunctionGroup {
|
|
90
|
+
readonly name: string;
|
|
91
|
+
readonly function: IFunction;
|
|
64
92
|
}
|
|
65
93
|
/**
|
|
66
94
|
* Creates an API Gateway REST API for Next.js applications
|
|
@@ -80,11 +108,31 @@ export declare class NextjsApi extends Construct {
|
|
|
80
108
|
* mapping added that way won't show up here.
|
|
81
109
|
*/
|
|
82
110
|
get url(): string;
|
|
111
|
+
/**
|
|
112
|
+
* Deploys the stage again after each stack update.
|
|
113
|
+
* @see NextjsApiProps.redeployAfterUpdate
|
|
114
|
+
*/
|
|
115
|
+
readonly redeployFunction?: LambdaFunction;
|
|
116
|
+
/**
|
|
117
|
+
* Matches this stack's `UPDATE_COMPLETE` and `UPDATE_ROLLBACK_COMPLETE` and
|
|
118
|
+
* invokes {@link redeployFunction}.
|
|
119
|
+
*/
|
|
120
|
+
readonly redeployRule?: Rule;
|
|
83
121
|
private readonly baseResource;
|
|
84
122
|
private readonly nextResource;
|
|
123
|
+
/**
|
|
124
|
+
* Resources created only as parents of a group route, and their paths. API
|
|
125
|
+
* Gateway answers a request for a resource with no method itself — 403
|
|
126
|
+
* "Missing Authentication Token" — rather than falling back to a `{proxy+}`
|
|
127
|
+
* higher up, so each needs one. Without it a `/api/reports/**` group turned
|
|
128
|
+
* `/api/reports` and `/api` into 403s.
|
|
129
|
+
*/
|
|
130
|
+
private readonly groupParentResources;
|
|
85
131
|
private readonly props;
|
|
86
132
|
private staticIntegrationRole;
|
|
87
133
|
constructor(scope: Construct, id: string, props: NextjsApiProps);
|
|
134
|
+
/** @see NextjsApiProps.redeployAfterUpdate */
|
|
135
|
+
private createRedeploy;
|
|
88
136
|
private validateProps;
|
|
89
137
|
private createRestApi;
|
|
90
138
|
/**
|
|
@@ -111,9 +159,45 @@ export declare class NextjsApi extends Construct {
|
|
|
111
159
|
private createS3Integration;
|
|
112
160
|
private getStaticMethodOptions;
|
|
113
161
|
/**
|
|
114
|
-
*
|
|
162
|
+
* One resource subtree per function group pattern.
|
|
163
|
+
*
|
|
164
|
+
* Unlike CloudFront this needs no ordering: API Gateway matches on a resource
|
|
165
|
+
* *tree*, so `/api/reports/{proxy+}` beats `/api/{proxy+}` beats `/{proxy+}`
|
|
166
|
+
* structurally, and "longest pattern wins" comes for free. What does need care
|
|
167
|
+
* is not creating the same path twice — two groups under `/api` share the `api`
|
|
168
|
+
* resource — so every segment goes through {@link resourceFor}.
|
|
169
|
+
*/
|
|
170
|
+
private createFunctionGroupIntegrations;
|
|
171
|
+
/**
|
|
172
|
+
* The group pattern validation accepts every character a CloudFront path
|
|
173
|
+
* pattern can hold, and API Gateway's path parts hold fewer: `~`, `@`, `+`,
|
|
174
|
+
* `&` and quotes pass it and then fail `addResource` with an error that names
|
|
175
|
+
* neither the group nor the pattern. Say which, and what to do instead.
|
|
176
|
+
*/
|
|
177
|
+
private assertRoutable;
|
|
178
|
+
/**
|
|
179
|
+
* Refuse a group route that shares a resource with a `public/` entry.
|
|
180
|
+
*
|
|
181
|
+
* A public directory `docs` is `docs/{proxy+}` with a `GET` to S3. `/docs/**`
|
|
182
|
+
* adds `ANY` to that same resource, and API Gateway prefers the `GET`, so
|
|
183
|
+
* every page load under the group went to S3; `/docs/guide/**` is a more
|
|
184
|
+
* specific resource instead, and takes `/docs/guide/…` away from the public
|
|
185
|
+
* files. A public file `pricing` and an exact `/pricing` are the same
|
|
186
|
+
* resource the same way. `NextjsDistribution` rejects the CloudFront
|
|
187
|
+
* equivalents.
|
|
188
|
+
*/
|
|
189
|
+
private assertNoPublicCollision;
|
|
190
|
+
/**
|
|
191
|
+
* Resource paths, as segment arrays, for one group pattern.
|
|
192
|
+
*
|
|
193
|
+
* A subtree gets `{proxy+}` as its last segment and so owns everything *under*
|
|
194
|
+
* the path but not the path itself, matching both the CloudFront translation and
|
|
195
|
+
* `assignRoutesToGroups`. An exact path gets no proxy segment, which leaves its
|
|
196
|
+
* children falling through to the root `{proxy+}` — also the CloudFront result.
|
|
115
197
|
*/
|
|
116
|
-
private
|
|
198
|
+
private resourcePathsFor;
|
|
199
|
+
/** Walk or create a resource path, reusing whatever already exists. */
|
|
200
|
+
private resourceFor;
|
|
117
201
|
/**
|
|
118
202
|
* Create Lambda Proxy integration for all other routes
|
|
119
203
|
*/
|