cdk-nextjs 0.7.11 → 0.7.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.jsii +310 -100
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +211 -3
  4. package/README.md +116 -101
  5. package/docs/breaking-changes.md +36 -2
  6. package/docs/development-guide.md +10 -0
  7. package/docs/next-build-output-guide.md +1 -1
  8. package/lib/adapter/adapter.mjs +4 -1
  9. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +21 -0
  10. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  11. package/lib/nextjs-api.js +1 -1
  12. package/lib/nextjs-build/nextjs-build.js +1 -1
  13. package/lib/nextjs-cache.js +1 -1
  14. package/lib/nextjs-compute/nextjs-containers.js +1 -1
  15. package/lib/nextjs-compute/nextjs-functions.js +1 -1
  16. package/lib/nextjs-distribution.d.ts +71 -2
  17. package/lib/nextjs-distribution.js +156 -107
  18. package/lib/nextjs-distribution.test.js +361 -12
  19. package/lib/nextjs-post-deploy.js +1 -1
  20. package/lib/nextjs-static-assets.d.ts +74 -5
  21. package/lib/nextjs-static-assets.js +276 -41
  22. package/lib/nextjs-static-assets.test.js +298 -1
  23. package/lib/root-constructs/nextjs-base-construct.d.ts +5 -4
  24. package/lib/root-constructs/nextjs-base-construct.js +17 -8
  25. package/lib/root-constructs/nextjs-global-containers.d.ts +16 -1
  26. package/lib/root-constructs/nextjs-global-containers.js +4 -2
  27. package/lib/root-constructs/nextjs-global-functions.d.ts +16 -1
  28. package/lib/root-constructs/nextjs-global-functions.js +4 -2
  29. package/lib/root-constructs/nextjs-regional-containers.js +1 -1
  30. package/lib/root-constructs/nextjs-regional-functions.js +1 -1
  31. package/lib/runtime/image-utils.d.ts +1 -0
  32. package/lib/runtime/image-utils.js +2 -1
  33. package/lib/runtime/image-utils.test.js +17 -1
  34. package/lib/runtime/image.js +5 -2
  35. package/lib/runtime/image.test.js +21 -1
  36. package/lib/runtime/lambda.mjs +9 -2
  37. package/lib/runtime/server.mjs +9 -2
  38. package/lib/utils/viewer-request-functions.d.ts +53 -0
  39. package/lib/utils/viewer-request-functions.js +172 -0
  40. package/lib/utils/viewer-request-functions.test.d.ts +1 -0
  41. package/lib/utils/viewer-request-functions.test.js +43 -0
  42. package/package.json +4 -1
  43. package/scripts/e2e-harness/app.js +7 -2
  44. package/scripts/render-diagrams.mjs +121 -0
@@ -42,7 +42,7 @@ We could ship this off to Lambda/Fargate and call it a day, but then we wouldn't
42
42
 
43
43
  ## S3
44
44
 
45
- .next/static is simply copied to S3 and then CloudFront is configured to forward requests with paths match `\_next/static` or any paths in `public` folder to S3. `NextjsStaticAssets` is responsible for this. We also add S3 User Metadata with `BUILD_ID` to track which static files are apart of which deployment so we can prune later.
45
+ .next/static is simply copied to S3 and then CloudFront is configured to forward requests with paths match `\_next/static` or any paths in `public` folder to S3. `NextjsStaticAssets` is responsible for this. We also add S3 User Metadata with `BUILD_ID` to track which static files are apart of which deployment so we can prune later. The two trees are uploaded by separate `BucketDeployment`s so that `_next/static` objects get `Cache-Control: public, max-age=31536000, immutable`, the header Next.js itself sends for them (a third gives `_next/static/service-worker` the `public, max-age=0, must-revalidate` Next.js sends for a service worker, which keeps its URL across builds): CloudFront and API Gateway serve them straight from S3, so the object's metadata is the only `Cache-Control` a browser gets. `public` files keep their names when they change, so they get no header unless `overrides.nextjsStaticAssets.bucketDeploymentProps.cacheControl` sets one.
46
46
 
47
47
  Note, with `NextjsRegionalContainers`, we unfortunately cannot configure ALB to forward static requests directly to S3 because the host header dictates which bucket you can route requests to and it's not reliable to manually name buckets based on your domain. Therefore, static assets are copied into the container image to be served in ECS Fargate.
48
48
 
@@ -829,6 +829,8 @@ var require_package = __commonJS({
829
829
  compat: "pnpm dlx projen compat",
830
830
  compile: "pnpm dlx projen compile",
831
831
  default: "pnpm dlx projen default",
832
+ diagrams: "pnpm dlx projen diagrams",
833
+ "diagrams:check": "pnpm dlx projen diagrams:check",
832
834
  docgen: "pnpm dlx projen docgen",
833
835
  eject: "pnpm dlx projen eject",
834
836
  eslint: "pnpm dlx projen eslint",
@@ -866,6 +868,7 @@ var require_package = __commonJS({
866
868
  "@aws-sdk/client-s3": "^3.1141.0",
867
869
  "@aws-sdk/client-ssm": "^3.1141.0",
868
870
  "@aws-sdk/lib-storage": "^3.1141.0",
871
+ "@iconify-json/logos": "1.2.16",
869
872
  "@mrgrain/jsii-struct-builder": "^0.7.64",
870
873
  "@next/routing": "16.4.0",
871
874
  "@smithy/signature-v4": "^2.3.0",
@@ -948,7 +951,7 @@ var require_package = __commonJS({
948
951
  publishConfig: {
949
952
  access: "public"
950
953
  },
951
- version: "0.7.11",
954
+ version: "0.7.13",
952
955
  packageManager: "pnpm@10.32.1",
953
956
  jest: {
954
957
  coverageProvider: "v8",
@@ -4,6 +4,27 @@ import type { NextjsType, PublicDirEntry } from '../';
4
4
  * OptionalNextjsDistributionProps
5
5
  */
6
6
  export interface OptionalNextjsDistributionProps {
7
+ /**
8
+ * A CloudFront KeyValueStore associated with every viewer-request function {@link viewerRequestFunctionCode} is copied into (up to three, one per kind of behavior), so values it reads — Basic auth credentials, an allowlist — live outside the CloudFormation template and change without a deploy.
9
+ * Read it with `cf.kvs()`, no ID needed.
10
+ * @default - none
11
+ * @stability stable
12
+ */
13
+ readonly viewerRequestKeyValueStore?: aws_cloudfront.IKeyValueStore;
14
+ /**
15
+ * CloudFront Function code run first on every viewer request, on every behavior cdk-nextjs adds, static assets included — HTTP Basic auth on a pre-launch site, geo-gating.
16
+ * It must define `viewerRequest(event)` (a function, sync or async, or a
17
+ * `var`/`let`/`const`): return a response to answer the viewer, or the
18
+ * request (or nothing) to carry on. It is spliced into cdk-nextjs's own
19
+ * viewer-request functions, ahead of their logic, so it may not use the
20
+ * name `handler`, and the combined function must fit CloudFront's 10 KB.
21
+ * It runs on `cloudfront-js-2.0`, so it may be async and read
22
+ * {@link viewerRequestKeyValueStore} with `cf.kvs()`. A bring-your-own
23
+ * {@link distribution}'s default behavior isn't covered.
24
+ * @default - none
25
+ * @stability stable
26
+ */
27
+ readonly viewerRequestFunctionCode?: aws_cloudfront.FunctionCode;
7
28
  /**
8
29
  * The most cache behaviors the distribution may have, the default one included.
9
30
  * cdk-nextjs counts what it adds against this at synth, so running
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgbW9zdCBjYWNoZSBiZWhhdmlvcnMgdGhlIGRpc3RyaWJ1dGlvbiBtYXkgaGF2ZSwgdGhlIGRlZmF1bHQgb25lIGluY2x1ZGVkLlxuICAgKiBjZGstbmV4dGpzIGNvdW50cyB3aGF0IGl0IGFkZHMgYWdhaW5zdCB0aGlzIGF0IHN5bnRoLCBzbyBydW5uaW5nXG4gICAqIG91dCBpcyBhIHN5bnRoIGVycm9yIG5hbWluZyB3aGF0IHVzZWQgdGhlbSByYXRoZXIgdGhhbiBhIGZhaWxlZCBkZXBsb3kuXG4gICAqXG4gICAqIFJhaXNlIGl0IGFmdGVyIHJhaXNpbmcgdGhlIFwiQ2FjaGUgYmVoYXZpb3JzIHBlciBkaXN0cmlidXRpb25cIiBxdW90YSBmb3JcbiAgICogeW91ciBhY2NvdW50LiBMb3dlciBpdCBieSB0aGUgYmVoYXZpb3JzIGEgc3VwcGxpZWQge0BsaW5rIGRpc3RyaWJ1dGlvbn1cbiAgICogKG9yIGBvdmVycmlkZXMuZGlzdHJpYnV0aW9uUHJvcHNgKSBhbHJlYWR5IGhhcywgd2hpY2ggYXJlIG5vdCBjb3VudGVkLlxuICAgKiBAZGVmYXVsdCA3NSAtIENsb3VkRnJvbnQncyBkZWZhdWx0IHF1b3RhXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBtYXhDYWNoZUJlaGF2aW9ycz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTYCBvciBgTmV4dGpzVHlwZS5SRUdJT05BTF9DT05UQUlORVJTYC5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGxvYWRCYWxhbmNlcj86IGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLklBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcjtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlNgLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBkaXN0cmlidXRpb24/OiBhd3NfY2xvdWRmcm9udC5EaXN0cmlidXRpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBidXQgb25seSBhcHBsaWNhYmxlIGZvciBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBjZXJ0aWZpY2F0ZT86IGF3c19jZXJ0aWZpY2F0ZW1hbmFnZXIuSUNlcnRpZmljYXRlO1xuICAvKipcbiAgICogVVJJIHBhdGggcHJlZml4IHRoZSBhcHAgaXMgc2VydmVkIGF0LlxuICAgKiBTdXJyb3VuZGluZyBzbGFzaGVzIGFyZSBub3JtYWxpemVkXG4gICAqIGF3YXksIHNvIFwiL2Jhc2VcIiwgXCJiYXNlXCIgYW5kIFwiL2Jhc2UvXCIgYWxsIHByb2R1Y2UgdGhlIHNhbWUgY2FjaGUgYmVoYXZpb3JzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgYmFzZVBhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgYXBwJ3Mgb3duIGBhc3NldFByZWZpeGAuXG4gICAqIE5leHQuanMgZW1pdHMgYDxhc3NldFByZWZpeD4vX25leHQvc3RhdGljLy4uLmBcbiAgICogZm9yIGV2ZXJ5IGJ1bmRsZSB3aGlsZSB0aGUgb2JqZWN0cyBzdGF5IGF0IGA8YmFzZVBhdGg+L19uZXh0L3N0YXRpYy8uLi5gIGluXG4gICAqIFMzLCBzbyB0aGUgcHJlZml4J3MgcGF0aCBnZXRzIGEgY2FjaGUgYmVoYXZpb3Igb2YgaXRzIG93biB0aGF0IHJld3JpdGVzIGl0XG4gICAqIGF3YXkuXG4gICAqXG4gICAqIEVpdGhlciBmb3JtIGlzIGFjY2VwdGVkOiBhIHBhdGggKFwiL2NkblwiKSwgb3IgYW4gYWJzb2x1dGUgVVJMLCBpbiB3aGljaCBjYXNlXG4gICAqIG9ubHkgaXRzIHBhdGggY291bnRzIChcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tL2NkblwiIGJlaGF2ZXMgYXMgXCIvY2RuXCIsIGFuZFxuICAgKiBcImh0dHBzOi8vY2RuLmV4YW1wbGUuY29tXCIgbmVlZHMgbm8gYmVoYXZpb3IgYXQgYWxsKS4gQW4gYWJzb2x1dGUgcHJlZml4J3MgcGF0aFxuICAgKiBtYXR0ZXJzIGJlY2F1c2UgYG5leHQgYnVpbGRgIGNvbXBpbGVzIGEgYC9jZG4vX25leHQvOnBhdGgrYCByZXdyaXRlIG9mIGl0c1xuICAgKiBvd24sIHNvIGBuZXh0IHN0YXJ0YCBzZXJ2ZXMgZXZlcnkgYnVuZGxlIHVuZGVyIGl0IOKAlCBhIENETiBmcm9udGluZyB0aGlzXG4gICAqIGRpc3RyaWJ1dGlvbiB0aGVyZSBoYXMgdG8gYmUgYW5zd2VyZWQgdG9vLlxuICAgKlxuICAgKiBBcHBsaWVkIG9uIHRvcCBvZiBgYmFzZVBhdGhgLCBub3QgdW5kZXIgaXQsIGJlY2F1c2UgdGhhdCBpcyBob3cgTmV4dC5qc1xuICAgKiBidWlsZHMgdGhlIFVSTC5cbiAgICogQGRlZmF1bHQgLSBub25lOyBwYXNzIGBOZXh0anNCdWlsZC5uZXh0Q29uZmlnQXNzZXRQcmVmaXhQYXRoYFxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRQcmVmaXg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBFbnRyaWVzIChmaWxlcy9kaXJlY3Rvcmllcykgd2l0aGluIE5leHQuanMgYXBwJ3MgcHVibGljIGRpcmVjdG9yeS4gVXNlZCB0byBhZGQgc3RhdGljIGJlaGF2aW9ycyB0byBkaXN0cmlidXRpb24uXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNEaXJFbnRyaWVzPzogQXJyYXk8UHVibGljRGlyRW50cnk+O1xuICAvKipcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IG5leHRqc1R5cGU/OiBOZXh0anNUeXBlO1xuICAvKipcbiAgICogQnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0cy5cbiAgICogTXVzdCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0byBzZXJ2ZSBzdGF0aWMgZmlsZXMuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBhc3NldHNCdWNrZXQ/OiBhd3NfczMuSUJ1Y2tldDtcbn1cbiJdfQ==
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBBIENsb3VkRnJvbnQgS2V5VmFsdWVTdG9yZSBhc3NvY2lhdGVkIHdpdGggZXZlcnkgdmlld2VyLXJlcXVlc3QgZnVuY3Rpb24ge0BsaW5rIHZpZXdlclJlcXVlc3RGdW5jdGlvbkNvZGV9IGlzIGNvcGllZCBpbnRvICh1cCB0byB0aHJlZSwgb25lIHBlciBraW5kIG9mIGJlaGF2aW9yKSwgc28gdmFsdWVzIGl0IHJlYWRzIOKAlCBCYXNpYyBhdXRoIGNyZWRlbnRpYWxzLCBhbiBhbGxvd2xpc3Qg4oCUIGxpdmUgb3V0c2lkZSB0aGUgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUgYW5kIGNoYW5nZSB3aXRob3V0IGEgZGVwbG95LlxuICAgKiBSZWFkIGl0IHdpdGggYGNmLmt2cygpYCwgbm8gSUQgbmVlZGVkLlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHZpZXdlclJlcXVlc3RLZXlWYWx1ZVN0b3JlPzogYXdzX2Nsb3VkZnJvbnQuSUtleVZhbHVlU3RvcmU7XG4gIC8qKlxuICAgKiBDbG91ZEZyb250IEZ1bmN0aW9uIGNvZGUgcnVuIGZpcnN0IG9uIGV2ZXJ5IHZpZXdlciByZXF1ZXN0LCBvbiBldmVyeSBiZWhhdmlvciBjZGstbmV4dGpzIGFkZHMsIHN0YXRpYyBhc3NldHMgaW5jbHVkZWQg4oCUIEhUVFAgQmFzaWMgYXV0aCBvbiBhIHByZS1sYXVuY2ggc2l0ZSwgZ2VvLWdhdGluZy5cbiAgICogSXQgbXVzdCBkZWZpbmUgYHZpZXdlclJlcXVlc3QoZXZlbnQpYCAoYSBmdW5jdGlvbiwgc3luYyBvciBhc3luYywgb3IgYVxuICAgKiBgdmFyYC9gbGV0YC9gY29uc3RgKTogcmV0dXJuIGEgcmVzcG9uc2UgdG8gYW5zd2VyIHRoZSB2aWV3ZXIsIG9yIHRoZVxuICAgKiByZXF1ZXN0IChvciBub3RoaW5nKSB0byBjYXJyeSBvbi4gSXQgaXMgc3BsaWNlZCBpbnRvIGNkay1uZXh0anMncyBvd25cbiAgICogdmlld2VyLXJlcXVlc3QgZnVuY3Rpb25zLCBhaGVhZCBvZiB0aGVpciBsb2dpYywgc28gaXQgbWF5IG5vdCB1c2UgdGhlXG4gICAqIG5hbWUgYGhhbmRsZXJgLCBhbmQgdGhlIGNvbWJpbmVkIGZ1bmN0aW9uIG11c3QgZml0IENsb3VkRnJvbnQncyAxMCBLQi5cbiAgICogSXQgcnVucyBvbiBgY2xvdWRmcm9udC1qcy0yLjBgLCBzbyBpdCBtYXkgYmUgYXN5bmMgYW5kIHJlYWRcbiAgICoge0BsaW5rIHZpZXdlclJlcXVlc3RLZXlWYWx1ZVN0b3JlfSB3aXRoIGBjZi5rdnMoKWAuIEEgYnJpbmcteW91ci1vd25cbiAgICoge0BsaW5rIGRpc3RyaWJ1dGlvbn0ncyBkZWZhdWx0IGJlaGF2aW9yIGlzbid0IGNvdmVyZWQuXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgdmlld2VyUmVxdWVzdEZ1bmN0aW9uQ29kZT86IGF3c19jbG91ZGZyb250LkZ1bmN0aW9uQ29kZTtcbiAgLyoqXG4gICAqIFRoZSBtb3N0IGNhY2hlIGJlaGF2aW9ycyB0aGUgZGlzdHJpYnV0aW9uIG1heSBoYXZlLCB0aGUgZGVmYXVsdCBvbmUgaW5jbHVkZWQuXG4gICAqIGNkay1uZXh0anMgY291bnRzIHdoYXQgaXQgYWRkcyBhZ2FpbnN0IHRoaXMgYXQgc3ludGgsIHNvIHJ1bm5pbmdcbiAgICogb3V0IGlzIGEgc3ludGggZXJyb3IgbmFtaW5nIHdoYXQgdXNlZCB0aGVtIHJhdGhlciB0aGFuIGEgZmFpbGVkIGRlcGxveS5cbiAgICpcbiAgICogUmFpc2UgaXQgYWZ0ZXIgcmFpc2luZyB0aGUgXCJDYWNoZSBiZWhhdmlvcnMgcGVyIGRpc3RyaWJ1dGlvblwiIHF1b3RhIGZvclxuICAgKiB5b3VyIGFjY291bnQuIExvd2VyIGl0IGJ5IHRoZSBiZWhhdmlvcnMgYSBzdXBwbGllZCB7QGxpbmsgZGlzdHJpYnV0aW9ufVxuICAgKiAob3IgYG92ZXJyaWRlcy5kaXN0cmlidXRpb25Qcm9wc2ApIGFscmVhZHkgaGFzLCB3aGljaCBhcmUgbm90IGNvdW50ZWQuXG4gICAqIEBkZWZhdWx0IDc1IC0gQ2xvdWRGcm9udCdzIGRlZmF1bHQgcXVvdGFcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IG1heENhY2hlQmVoYXZpb3JzPzogbnVtYmVyO1xuICAvKipcbiAgICogUmVxdWlyZWQgaWYgYE5leHRqc1R5cGUuR0xPQkFMX0NPTlRBSU5FUlNgIG9yIGBOZXh0anNUeXBlLlJFR0lPTkFMX0NPTlRBSU5FUlNgLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyPzogYXdzX2VsYXN0aWNsb2FkYmFsYW5jaW5ndjIuSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyO1xuICAvKipcbiAgICogUmVxdWlyZWQgaWYgYE5leHRqc1R5cGUuR0xPQkFMX0ZVTkNUSU9OU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvblVybD86IGF3c19sYW1iZGEuSUZ1bmN0aW9uVXJsO1xuICAvKipcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbj86IGF3c19jbG91ZGZyb250LkRpc3RyaWJ1dGlvbjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGJ1dCBvbmx5IGFwcGxpY2FibGUgZm9yIGBOZXh0anNUeXBlLkdMT0JBTF9DT05UQUlORVJTYC5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGNlcnRpZmljYXRlPzogYXdzX2NlcnRpZmljYXRlbWFuYWdlci5JQ2VydGlmaWNhdGU7XG4gIC8qKlxuICAgKiBVUkkgcGF0aCBwcmVmaXggdGhlIGFwcCBpcyBzZXJ2ZWQgYXQuXG4gICAqIFN1cnJvdW5kaW5nIHNsYXNoZXMgYXJlIG5vcm1hbGl6ZWRcbiAgICogYXdheSwgc28gXCIvYmFzZVwiLCBcImJhc2VcIiBhbmQgXCIvYmFzZS9cIiBhbGwgcHJvZHVjZSB0aGUgc2FtZSBjYWNoZSBiZWhhdmlvcnMuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBiYXNlUGF0aD86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBhcHAncyBvd24gYGFzc2V0UHJlZml4YC5cbiAgICogTmV4dC5qcyBlbWl0cyBgPGFzc2V0UHJlZml4Pi9fbmV4dC9zdGF0aWMvLi4uYFxuICAgKiBmb3IgZXZlcnkgYnVuZGxlIHdoaWxlIHRoZSBvYmplY3RzIHN0YXkgYXQgYDxiYXNlUGF0aD4vX25leHQvc3RhdGljLy4uLmAgaW5cbiAgICogUzMsIHNvIHRoZSBwcmVmaXgncyBwYXRoIGdldHMgYSBjYWNoZSBiZWhhdmlvciBvZiBpdHMgb3duIHRoYXQgcmV3cml0ZXMgaXRcbiAgICogYXdheS5cbiAgICpcbiAgICogRWl0aGVyIGZvcm0gaXMgYWNjZXB0ZWQ6IGEgcGF0aCAoXCIvY2RuXCIpLCBvciBhbiBhYnNvbHV0ZSBVUkwsIGluIHdoaWNoIGNhc2VcbiAgICogb25seSBpdHMgcGF0aCBjb3VudHMgKFwiaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vY2RuXCIgYmVoYXZlcyBhcyBcIi9jZG5cIiwgYW5kXG4gICAqIFwiaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb21cIiBuZWVkcyBubyBiZWhhdmlvciBhdCBhbGwpLiBBbiBhYnNvbHV0ZSBwcmVmaXgncyBwYXRoXG4gICAqIG1hdHRlcnMgYmVjYXVzZSBgbmV4dCBidWlsZGAgY29tcGlsZXMgYSBgL2Nkbi9fbmV4dC86cGF0aCtgIHJld3JpdGUgb2YgaXRzXG4gICAqIG93biwgc28gYG5leHQgc3RhcnRgIHNlcnZlcyBldmVyeSBidW5kbGUgdW5kZXIgaXQg4oCUIGEgQ0ROIGZyb250aW5nIHRoaXNcbiAgICogZGlzdHJpYnV0aW9uIHRoZXJlIGhhcyB0byBiZSBhbnN3ZXJlZCB0b28uXG4gICAqXG4gICAqIEFwcGxpZWQgb24gdG9wIG9mIGBiYXNlUGF0aGAsIG5vdCB1bmRlciBpdCwgYmVjYXVzZSB0aGF0IGlzIGhvdyBOZXh0LmpzXG4gICAqIGJ1aWxkcyB0aGUgVVJMLlxuICAgKiBAZGVmYXVsdCAtIG5vbmU7IHBhc3MgYE5leHRqc0J1aWxkLm5leHRDb25maWdBc3NldFByZWZpeFBhdGhgXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBhc3NldFByZWZpeD86IHN0cmluZztcbiAgLyoqXG4gICAqIEVudHJpZXMgKGZpbGVzL2RpcmVjdG9yaWVzKSB3aXRoaW4gTmV4dC5qcyBhcHAncyBwdWJsaWMgZGlyZWN0b3J5LiBVc2VkIHRvIGFkZCBzdGF0aWMgYmVoYXZpb3JzIHRvIGRpc3RyaWJ1dGlvbi5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHB1YmxpY0RpckVudHJpZXM/OiBBcnJheTxQdWJsaWNEaXJFbnRyeT47XG4gIC8qKlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgbmV4dGpzVHlwZT86IE5leHRqc1R5cGU7XG4gIC8qKlxuICAgKiBCdWNrZXQgY29udGFpbmluZyBzdGF0aWMgYXNzZXRzLlxuICAgKiBNdXN0IGJlIHByb3ZpZGVkIGlmIHlvdSB3YW50IHRvIHNlcnZlIHN0YXRpYyBmaWxlcy5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGFzc2V0c0J1Y2tldD86IGF3c19zMy5JQnVja2V0O1xufVxuIl19
package/lib/nextjs-api.js CHANGED
@@ -22,7 +22,7 @@ const API_PATH_PART = /^[a-zA-Z0-9:._\-$]+$/;
22
22
  * Creates an API Gateway REST API for Next.js applications
23
23
  */
24
24
  class NextjsApi extends constructs_1.Construct {
25
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsApi", version: "0.7.11" };
25
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsApi", version: "0.7.13" };
26
26
  /**
27
27
  * The API Gateway REST API
28
28
  */
@@ -66,7 +66,7 @@ function deploymentArchitecture(props) {
66
66
  * @link https://nextjs.org/docs/pages/api-reference/next-config-js/output
67
67
  */
68
68
  class NextjsBuild extends constructs_1.Construct {
69
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsBuild", version: "0.7.11" };
69
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsBuild", version: "0.7.13" };
70
70
  /**
71
71
  * Unique id for this deployment. Used to partition cache storage and as
72
72
  * metadata for static assets in S3 bucket.
@@ -86,7 +86,7 @@ function sizeOfDirectory(dir) {
86
86
  * Next.js Cache construct providing unified S3 and DynamoDB cache management.
87
87
  */
88
88
  class NextjsCache extends constructs_1.Construct {
89
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsCache", version: "0.7.11" };
89
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsCache", version: "0.7.13" };
90
90
  cacheBucket;
91
91
  revalidationTable;
92
92
  buildId;
@@ -19,7 +19,7 @@ const constants_1 = require("../constants");
19
19
  * Fargate.
20
20
  */
21
21
  class NextjsContainers extends constructs_1.Construct {
22
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsContainers", version: "0.7.11" };
22
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsContainers", version: "0.7.13" };
23
23
  albFargateService;
24
24
  ecsCluster;
25
25
  url;
@@ -23,7 +23,7 @@ const zip_directory_1 = require("../utils/zip-directory");
23
23
  * `awslambda.streamifyResponse` directly.
24
24
  */
25
25
  class NextjsFunctions extends constructs_1.Construct {
26
- static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsFunctions", version: "0.7.11" };
26
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-nextjs.NextjsFunctions", version: "0.7.13" };
27
27
  /**
28
28
  * The `default` group's function: the one the distribution's default behavior
29
29
  * targets, and the only one at all unless `functionGroups` is used.
@@ -1,5 +1,5 @@
1
1
  import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
2
- import { AddBehaviorOptions, CachePolicyProps, Distribution, ResponseHeadersPolicyProps } from "aws-cdk-lib/aws-cloudfront";
2
+ import { AddBehaviorOptions, CachePolicyProps, Distribution, FunctionCode, IKeyValueStore, ResponseHeadersPolicyProps } from "aws-cdk-lib/aws-cloudfront";
3
3
  import { FunctionUrlOriginWithOACProps, VpcOriginWithEndpointProps } from "aws-cdk-lib/aws-cloudfront-origins";
4
4
  import { IApplicationLoadBalancer } from "aws-cdk-lib/aws-elasticloadbalancingv2";
5
5
  import { IFunctionUrl } from "aws-cdk-lib/aws-lambda";
@@ -101,6 +101,34 @@ export interface NextjsDistributionProps {
101
101
  * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions
102
102
  */
103
103
  readonly maxCacheBehaviors?: number;
104
+ /**
105
+ * CloudFront Function code run first on every viewer request, on every
106
+ * behavior cdk-nextjs adds, static assets included — HTTP Basic auth on a
107
+ * pre-launch site, geo-gating.
108
+ *
109
+ * It must define `viewerRequest(event)` (a function, sync or async, or a
110
+ * `var`/`let`/`const`): return a response to answer the viewer, or the
111
+ * request (or nothing) to carry on. It is spliced into cdk-nextjs's own
112
+ * viewer-request functions, ahead of their logic, so it may not use the
113
+ * name `handler`, and the combined function must fit CloudFront's 10 KB.
114
+ * It runs on `cloudfront-js-2.0`, so it may be async and read
115
+ * {@link viewerRequestKeyValueStore} with `cf.kvs()`. A bring-your-own
116
+ * {@link distribution}'s default behavior isn't covered.
117
+ *
118
+ * @default - none
119
+ * @see https://github.com/cdklabs/cdk-nextjs#running-code-on-every-viewer-request
120
+ */
121
+ readonly viewerRequestFunctionCode?: FunctionCode;
122
+ /**
123
+ * A CloudFront KeyValueStore associated with every viewer-request function
124
+ * {@link viewerRequestFunctionCode} is copied into (up to three, one per kind
125
+ * of behavior), so values it reads — Basic auth credentials, an allowlist —
126
+ * live outside the CloudFormation template and change without a deploy.
127
+ * Read it with `cf.kvs()`, no ID needed.
128
+ * @default - none
129
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-custom-methods.html
130
+ */
131
+ readonly viewerRequestKeyValueStore?: IKeyValueStore;
104
132
  }
105
133
  /** A non-default function group and the origin its routes must reach. */
106
134
  export interface NextjsDistributionFunctionGroup {
@@ -134,6 +162,18 @@ export declare class NextjsDistribution extends Construct {
134
162
  private dynamicOrigin;
135
163
  private dynamicOriginResponsePolicy;
136
164
  private dynamicCloudFrontFunctionAssociations;
165
+ /**
166
+ * `viewerRequestFunctionCode`, rendered and checked once, since
167
+ * `FunctionCode.fromFile` reads the file on every render.
168
+ */
169
+ private viewerRequestCode?;
170
+ /**
171
+ * The viewer-request function `viewerRequestFunctionCode` adds to behaviors
172
+ * with no viewer-request logic of their own, shared by all of them, so the
173
+ * `assetPrefix` behavior, which has a viewer-request function of its own,
174
+ * can tell it from an override's.
175
+ */
176
+ private passThroughFunction?;
137
177
  private isFunctionCompute;
138
178
  private staticBehaviorOptions;
139
179
  private dynamicBehaviorOptions;
@@ -168,11 +208,40 @@ export declare class NextjsDistribution extends Construct {
168
208
  * @see https://open-next.js.org/advanced/workaround#workaround-set-x-forwarded-host-header-aws-specific
169
209
  */
170
210
  private createDynamicCloudFrontFunctionAssociations;
211
+ /**
212
+ * The function a behavior with no viewer-request logic of its own gets when
213
+ * `viewerRequestFunctionCode` is set, created on first use.
214
+ */
215
+ private getPassThroughFunction;
216
+ /**
217
+ * The code, runtime and KeyValueStore of a function whose `handler` is
218
+ * cdk-nextjs's, with `viewerRequestFunctionCode` spliced in
219
+ * ({@link spliceViewerRequest}) and checked against CloudFront's size limit.
220
+ *
221
+ * Every one runs on `cloudfront-js-2.0`, the runtime AWS recommends and the
222
+ * one with `async` and KeyValueStores, so the handlers are all `async`
223
+ * whether or not there is user code to await.
224
+ */
225
+ private viewerRequestFunctionProps;
226
+ /**
227
+ * `viewerRequestFunctionCode`, rendered once, since `FunctionCode.fromFile`
228
+ * reads the file on every render, and checked
229
+ * ({@link checkViewerRequestCode}).
230
+ */
231
+ private renderViewerRequestCode;
232
+ /**
233
+ * CloudFront allows one function per event type per behavior, so an
234
+ * override's viewer-request association and one cdk-nextjs needs can't both
235
+ * be kept. Thrown at synth, where both halves are known, rather than left to
236
+ * a deploy that names neither.
237
+ */
238
+ private assertViewerRequestUnclaimed;
171
239
  private createStaticBehaviorOptions;
172
240
  private createDynamicBehaviorOptions;
173
241
  /**
174
242
  * The behavior's function associations: an override's, plus the viewer-request
175
- * function Global Functions depends on.
243
+ * function Global Functions depends on, or the one `viewerRequestFunctionCode`
244
+ * adds on Global Containers.
176
245
  *
177
246
  * Spreading the override's `functionAssociations` over ours would silently
178
247
  * drop that function, and with it the only thing standing between a viewer's