cdk-nextjs 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2467 -2714
- package/.jsii.tabl.json +1 -1
- package/API.md +1725 -1909
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +687 -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 +13 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
- 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/post-deploy.lambda.js +3 -2
- 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 +19 -3
- package/lib/lambdas/post-deploy/prune-s3.js +54 -15
- package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
- 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 +107 -18
- package/lib/nextjs-api.js +349 -39
- package/lib/nextjs-api.test.js +582 -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 +23 -3
- package/lib/nextjs-post-deploy.js +14 -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 +23 -4
- package/lib/nextjs-static-assets.js +29 -6
- package/lib/nextjs-static-assets.test.js +20 -1
- package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
- package/lib/root-constructs/nextjs-base-construct.js +144 -34
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -70
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -69
- package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
- package/lib/root-constructs/nextjs-regional-containers.js +17 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -25
- 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 +123 -11
- package/lib/utils/base-path.js +276 -39
- package/lib/utils/base-path.test.js +275 -50
- 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,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.REDEPLOY_DESCRIPTION_PREFIX = void 0;
|
|
7
|
+
exports.redeployStage = redeployStage;
|
|
8
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
9
|
+
const client_api_gateway_1 = require("@aws-sdk/client-api-gateway");
|
|
10
|
+
const debug_1 = __importDefault(require("debug"));
|
|
11
|
+
const debug = (0, debug_1.default)("cdk-nextjs:redeploy-stage");
|
|
12
|
+
/**
|
|
13
|
+
* Marks the deployments this function makes, so a later run prunes only its
|
|
14
|
+
* own. CloudFormation owns every other deployment on the API and deletes them
|
|
15
|
+
* itself.
|
|
16
|
+
*/
|
|
17
|
+
exports.REDEPLOY_DESCRIPTION_PREFIX = "cdk-nextjs: redeploy after";
|
|
18
|
+
const apiGateway = new client_api_gateway_1.APIGatewayClient({});
|
|
19
|
+
/**
|
|
20
|
+
* Deploys `stageName` again from the API as it is now, then deletes the
|
|
21
|
+
* deployments earlier runs made that no stage still points at.
|
|
22
|
+
*
|
|
23
|
+
* Why: CloudFormation creates the new `AWS::ApiGateway::Deployment` while
|
|
24
|
+
* resources removed from the template still exist (it deletes them only in
|
|
25
|
+
* `UPDATE_COMPLETE_CLEANUP_IN_PROGRESS`), so that snapshot keeps them. A
|
|
26
|
+
* removed function group's `/api/{proxy+}` stays routable, to a Lambda that is
|
|
27
|
+
* then deleted, and API Gateway answers 500 until the next deployment. This
|
|
28
|
+
* runs on `UPDATE_COMPLETE`, after cleanup, so its snapshot is the real tree.
|
|
29
|
+
*/
|
|
30
|
+
async function redeployStage({ restApiId, stageName, stackStatus, }) {
|
|
31
|
+
const created = await apiGateway.send(new client_api_gateway_1.CreateDeploymentCommand({
|
|
32
|
+
restApiId,
|
|
33
|
+
stageName,
|
|
34
|
+
description: `${exports.REDEPLOY_DESCRIPTION_PREFIX} ${stackStatus}`,
|
|
35
|
+
}));
|
|
36
|
+
const deploymentId = created.id;
|
|
37
|
+
debug(`Deployed ${restApiId}/${stageName} as ${deploymentId}`);
|
|
38
|
+
const { item: stages = [] } = await apiGateway.send(new client_api_gateway_1.GetStagesCommand({ restApiId }));
|
|
39
|
+
const referenced = new Set(stages.map((stage) => stage.deploymentId));
|
|
40
|
+
let position;
|
|
41
|
+
do {
|
|
42
|
+
const page = await apiGateway.send(new client_api_gateway_1.GetDeploymentsCommand({ restApiId, position, limit: 500 }));
|
|
43
|
+
for (const deployment of page.items ?? []) {
|
|
44
|
+
if (!deployment.id ||
|
|
45
|
+
deployment.id === deploymentId ||
|
|
46
|
+
referenced.has(deployment.id) ||
|
|
47
|
+
!deployment.description?.startsWith(exports.REDEPLOY_DESCRIPTION_PREFIX)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
await apiGateway.send(new client_api_gateway_1.DeleteDeploymentCommand({
|
|
52
|
+
restApiId,
|
|
53
|
+
deploymentId: deployment.id,
|
|
54
|
+
}));
|
|
55
|
+
debug(`Deleted previous redeploy ${deployment.id}`);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
// Pruning is housekeeping: the stage already serves the new deployment.
|
|
59
|
+
// A stage created meanwhile can reference it (400), or another run got
|
|
60
|
+
// there first (404); either way the next run tries again.
|
|
61
|
+
console.warn(`Could not delete deployment ${deployment.id} of ${restApiId}:`, error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
position = page.position;
|
|
65
|
+
} while (position);
|
|
66
|
+
return deploymentId;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkZXBsb3ktc3RhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGFtYmRhcy9yZWRlcGxveS1zdGFnZS9yZWRlcGxveS1zdGFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUF1Q0Esc0NBd0RDO0FBL0ZELHNEQUFzRDtBQUN0RCxvRUFNcUM7QUFDckMsa0RBQTZCO0FBRTdCLE1BQU0sS0FBSyxHQUFHLElBQUEsZUFBUSxFQUFDLDJCQUEyQixDQUFDLENBQUM7QUFFcEQ7Ozs7R0FJRztBQUNVLFFBQUEsMkJBQTJCLEdBQUcsNEJBQTRCLENBQUM7QUFFeEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxxQ0FBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQVM1Qzs7Ozs7Ozs7OztHQVVHO0FBQ0ksS0FBSyxVQUFVLGFBQWEsQ0FBQyxFQUNsQyxTQUFTLEVBQ1QsU0FBUyxFQUNULFdBQVcsR0FDUTtJQUNuQixNQUFNLE9BQU8sR0FBRyxNQUFNLFVBQVUsQ0FBQyxJQUFJLENBQ25DLElBQUksNENBQXVCLENBQUM7UUFDMUIsU0FBUztRQUNULFNBQVM7UUFDVCxXQUFXLEVBQUUsR0FBRyxtQ0FBMkIsSUFBSSxXQUFXLEVBQUU7S0FDN0QsQ0FBQyxDQUNILENBQUM7SUFDRixNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsRUFBRyxDQUFDO0lBQ2pDLEtBQUssQ0FBQyxZQUFZLFNBQVMsSUFBSSxTQUFTLE9BQU8sWUFBWSxFQUFFLENBQUMsQ0FBQztJQUUvRCxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxFQUFFLEVBQUUsR0FBRyxNQUFNLFVBQVUsQ0FBQyxJQUFJLENBQ2pELElBQUkscUNBQWdCLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUNwQyxDQUFDO0lBQ0YsTUFBTSxVQUFVLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7SUFFdEUsSUFBSSxRQUE0QixDQUFDO0lBQ2pDLEdBQUcsQ0FBQztRQUNGLE1BQU0sSUFBSSxHQUFHLE1BQU0sVUFBVSxDQUFDLElBQUksQ0FDaEMsSUFBSSwwQ0FBcUIsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQy9ELENBQUM7UUFDRixLQUFLLE1BQU0sVUFBVSxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRSxFQUFFLENBQUM7WUFDMUMsSUFDRSxDQUFDLFVBQVUsQ0FBQyxFQUFFO2dCQUNkLFVBQVUsQ0FBQyxFQUFFLEtBQUssWUFBWTtnQkFDOUIsVUFBVSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUM3QixDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLG1DQUEyQixDQUFDLEVBQ2hFLENBQUM7Z0JBQ0QsU0FBUztZQUNYLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUNuQixJQUFJLDRDQUF1QixDQUFDO29CQUMxQixTQUFTO29CQUNULFlBQVksRUFBRSxVQUFVLENBQUMsRUFBRTtpQkFDNUIsQ0FBQyxDQUNILENBQUM7Z0JBQ0YsS0FBSyxDQUFDLDZCQUE2QixVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN0RCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZix3RUFBd0U7Z0JBQ3hFLHVFQUF1RTtnQkFDdkUsMERBQTBEO2dCQUMxRCxPQUFPLENBQUMsSUFBSSxDQUNWLCtCQUErQixVQUFVLENBQUMsRUFBRSxPQUFPLFNBQVMsR0FBRyxFQUMvRCxLQUFLLENBQ04sQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBQ0QsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDM0IsQ0FBQyxRQUFRLFFBQVEsRUFBRTtJQUVuQixPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5pbXBvcnQge1xuICBBUElHYXRld2F5Q2xpZW50LFxuICBDcmVhdGVEZXBsb3ltZW50Q29tbWFuZCxcbiAgRGVsZXRlRGVwbG95bWVudENvbW1hbmQsXG4gIEdldERlcGxveW1lbnRzQ29tbWFuZCxcbiAgR2V0U3RhZ2VzQ29tbWFuZCxcbn0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1hcGktZ2F0ZXdheVwiO1xuaW1wb3J0IGdldERlYnVnIGZyb20gXCJkZWJ1Z1wiO1xuXG5jb25zdCBkZWJ1ZyA9IGdldERlYnVnKFwiY2RrLW5leHRqczpyZWRlcGxveS1zdGFnZVwiKTtcblxuLyoqXG4gKiBNYXJrcyB0aGUgZGVwbG95bWVudHMgdGhpcyBmdW5jdGlvbiBtYWtlcywgc28gYSBsYXRlciBydW4gcHJ1bmVzIG9ubHkgaXRzXG4gKiBvd24uIENsb3VkRm9ybWF0aW9uIG93bnMgZXZlcnkgb3RoZXIgZGVwbG95bWVudCBvbiB0aGUgQVBJIGFuZCBkZWxldGVzIHRoZW1cbiAqIGl0c2VsZi5cbiAqL1xuZXhwb3J0IGNvbnN0IFJFREVQTE9ZX0RFU0NSSVBUSU9OX1BSRUZJWCA9IFwiY2RrLW5leHRqczogcmVkZXBsb3kgYWZ0ZXJcIjtcblxuY29uc3QgYXBpR2F0ZXdheSA9IG5ldyBBUElHYXRld2F5Q2xpZW50KHt9KTtcblxuZXhwb3J0IGludGVyZmFjZSBSZWRlcGxveVN0YWdlSW5wdXQge1xuICByZWFkb25seSByZXN0QXBpSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgc3RhZ2VOYW1lOiBzdHJpbmc7XG4gIC8qKiBUaGUgc3RhY2sgc3RhdHVzIHRoYXQgdHJpZ2dlcmVkIHRoZSBydW4sIGZvciB0aGUgZGVzY3JpcHRpb24uICovXG4gIHJlYWRvbmx5IHN0YWNrU3RhdHVzOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVwbG95cyBgc3RhZ2VOYW1lYCBhZ2FpbiBmcm9tIHRoZSBBUEkgYXMgaXQgaXMgbm93LCB0aGVuIGRlbGV0ZXMgdGhlXG4gKiBkZXBsb3ltZW50cyBlYXJsaWVyIHJ1bnMgbWFkZSB0aGF0IG5vIHN0YWdlIHN0aWxsIHBvaW50cyBhdC5cbiAqXG4gKiBXaHk6IENsb3VkRm9ybWF0aW9uIGNyZWF0ZXMgdGhlIG5ldyBgQVdTOjpBcGlHYXRld2F5OjpEZXBsb3ltZW50YCB3aGlsZVxuICogcmVzb3VyY2VzIHJlbW92ZWQgZnJvbSB0aGUgdGVtcGxhdGUgc3RpbGwgZXhpc3QgKGl0IGRlbGV0ZXMgdGhlbSBvbmx5IGluXG4gKiBgVVBEQVRFX0NPTVBMRVRFX0NMRUFOVVBfSU5fUFJPR1JFU1NgKSwgc28gdGhhdCBzbmFwc2hvdCBrZWVwcyB0aGVtLiBBXG4gKiByZW1vdmVkIGZ1bmN0aW9uIGdyb3VwJ3MgYC9hcGkve3Byb3h5K31gIHN0YXlzIHJvdXRhYmxlLCB0byBhIExhbWJkYSB0aGF0IGlzXG4gKiB0aGVuIGRlbGV0ZWQsIGFuZCBBUEkgR2F0ZXdheSBhbnN3ZXJzIDUwMCB1bnRpbCB0aGUgbmV4dCBkZXBsb3ltZW50LiBUaGlzXG4gKiBydW5zIG9uIGBVUERBVEVfQ09NUExFVEVgLCBhZnRlciBjbGVhbnVwLCBzbyBpdHMgc25hcHNob3QgaXMgdGhlIHJlYWwgdHJlZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGVwbG95U3RhZ2Uoe1xuICByZXN0QXBpSWQsXG4gIHN0YWdlTmFtZSxcbiAgc3RhY2tTdGF0dXMsXG59OiBSZWRlcGxveVN0YWdlSW5wdXQpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjcmVhdGVkID0gYXdhaXQgYXBpR2F0ZXdheS5zZW5kKFxuICAgIG5ldyBDcmVhdGVEZXBsb3ltZW50Q29tbWFuZCh7XG4gICAgICByZXN0QXBpSWQsXG4gICAgICBzdGFnZU5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogYCR7UkVERVBMT1lfREVTQ1JJUFRJT05fUFJFRklYfSAke3N0YWNrU3RhdHVzfWAsXG4gICAgfSksXG4gICk7XG4gIGNvbnN0IGRlcGxveW1lbnRJZCA9IGNyZWF0ZWQuaWQhO1xuICBkZWJ1ZyhgRGVwbG95ZWQgJHtyZXN0QXBpSWR9LyR7c3RhZ2VOYW1lfSBhcyAke2RlcGxveW1lbnRJZH1gKTtcblxuICBjb25zdCB7IGl0ZW06IHN0YWdlcyA9IFtdIH0gPSBhd2FpdCBhcGlHYXRld2F5LnNlbmQoXG4gICAgbmV3IEdldFN0YWdlc0NvbW1hbmQoeyByZXN0QXBpSWQgfSksXG4gICk7XG4gIGNvbnN0IHJlZmVyZW5jZWQgPSBuZXcgU2V0KHN0YWdlcy5tYXAoKHN0YWdlKSA9PiBzdGFnZS5kZXBsb3ltZW50SWQpKTtcblxuICBsZXQgcG9zaXRpb246IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgZG8ge1xuICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBhcGlHYXRld2F5LnNlbmQoXG4gICAgICBuZXcgR2V0RGVwbG95bWVudHNDb21tYW5kKHsgcmVzdEFwaUlkLCBwb3NpdGlvbiwgbGltaXQ6IDUwMCB9KSxcbiAgICApO1xuICAgIGZvciAoY29uc3QgZGVwbG95bWVudCBvZiBwYWdlLml0ZW1zID8/IFtdKSB7XG4gICAgICBpZiAoXG4gICAgICAgICFkZXBsb3ltZW50LmlkIHx8XG4gICAgICAgIGRlcGxveW1lbnQuaWQgPT09IGRlcGxveW1lbnRJZCB8fFxuICAgICAgICByZWZlcmVuY2VkLmhhcyhkZXBsb3ltZW50LmlkKSB8fFxuICAgICAgICAhZGVwbG95bWVudC5kZXNjcmlwdGlvbj8uc3RhcnRzV2l0aChSRURFUExPWV9ERVNDUklQVElPTl9QUkVGSVgpXG4gICAgICApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBhcGlHYXRld2F5LnNlbmQoXG4gICAgICAgICAgbmV3IERlbGV0ZURlcGxveW1lbnRDb21tYW5kKHtcbiAgICAgICAgICAgIHJlc3RBcGlJZCxcbiAgICAgICAgICAgIGRlcGxveW1lbnRJZDogZGVwbG95bWVudC5pZCxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgICAgZGVidWcoYERlbGV0ZWQgcHJldmlvdXMgcmVkZXBsb3kgJHtkZXBsb3ltZW50LmlkfWApO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gUHJ1bmluZyBpcyBob3VzZWtlZXBpbmc6IHRoZSBzdGFnZSBhbHJlYWR5IHNlcnZlcyB0aGUgbmV3IGRlcGxveW1lbnQuXG4gICAgICAgIC8vIEEgc3RhZ2UgY3JlYXRlZCBtZWFud2hpbGUgY2FuIHJlZmVyZW5jZSBpdCAoNDAwKSwgb3IgYW5vdGhlciBydW4gZ290XG4gICAgICAgIC8vIHRoZXJlIGZpcnN0ICg0MDQpOyBlaXRoZXIgd2F5IHRoZSBuZXh0IHJ1biB0cmllcyBhZ2Fpbi5cbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBDb3VsZCBub3QgZGVsZXRlIGRlcGxveW1lbnQgJHtkZXBsb3ltZW50LmlkfSBvZiAke3Jlc3RBcGlJZH06YCxcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcG9zaXRpb24gPSBwYWdlLnBvc2l0aW9uO1xuICB9IHdoaWxlIChwb3NpdGlvbik7XG5cbiAgcmV0dXJuIGRlcGxveW1lbnRJZDtcbn1cbiJdfQ==
|
|
@@ -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,15 +108,40 @@ 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
|
/**
|
|
91
139
|
* Create base resource path if needed. Important if `basePath` is set.
|
|
140
|
+
*
|
|
141
|
+
* A nested `basePath` ("/team/app") has to become one resource per segment:
|
|
142
|
+
* API Gateway path parts can't contain "/", so passing the whole thing to a
|
|
143
|
+
* single `addResource` fails validation at synth. `resolveBasePath` accepts
|
|
144
|
+
* nested values, so this is reachable.
|
|
92
145
|
*/
|
|
93
146
|
private createBaseResource;
|
|
94
147
|
private createStaticIntegrationRole;
|
|
@@ -106,9 +159,45 @@ export declare class NextjsApi extends Construct {
|
|
|
106
159
|
private createS3Integration;
|
|
107
160
|
private getStaticMethodOptions;
|
|
108
161
|
/**
|
|
109
|
-
*
|
|
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.
|
|
110
197
|
*/
|
|
111
|
-
private
|
|
198
|
+
private resourcePathsFor;
|
|
199
|
+
/** Walk or create a resource path, reusing whatever already exists. */
|
|
200
|
+
private resourceFor;
|
|
112
201
|
/**
|
|
113
202
|
* Create Lambda Proxy integration for all other routes
|
|
114
203
|
*/
|