cdk-nextjs 0.7.12 → 0.7.14

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 +346 -100
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +208 -0
  4. package/README.md +115 -100
  5. package/docs/breaking-changes.md +4 -2
  6. package/docs/development-guide.md +10 -0
  7. package/docs/harness-coverage.md +16 -6
  8. package/docs/next-build-output-guide.md +1 -1
  9. package/lib/adapter/adapter.mjs +4 -1
  10. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +6 -0
  11. package/lib/generated-structs/OptionalNextjsApiProps.js +1 -1
  12. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +27 -0
  13. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  14. package/lib/nextjs-api.d.ts +11 -0
  15. package/lib/nextjs-api.js +63 -9
  16. package/lib/nextjs-api.test.js +127 -1
  17. package/lib/nextjs-build/nextjs-build.js +1 -1
  18. package/lib/nextjs-cache.js +1 -1
  19. package/lib/nextjs-compute/nextjs-containers.js +1 -1
  20. package/lib/nextjs-compute/nextjs-functions.js +1 -1
  21. package/lib/nextjs-distribution.d.ts +92 -2
  22. package/lib/nextjs-distribution.js +223 -109
  23. package/lib/nextjs-distribution.test.js +492 -12
  24. package/lib/nextjs-post-deploy.js +1 -1
  25. package/lib/nextjs-static-assets.js +1 -1
  26. package/lib/nextjs-static-assets.test.js +19 -7
  27. package/lib/root-constructs/nextjs-base-construct.d.ts +7 -0
  28. package/lib/root-constructs/nextjs-base-construct.js +14 -2
  29. package/lib/root-constructs/nextjs-global-containers.d.ts +16 -1
  30. package/lib/root-constructs/nextjs-global-containers.js +5 -2
  31. package/lib/root-constructs/nextjs-global-functions.d.ts +16 -1
  32. package/lib/root-constructs/nextjs-global-functions.js +5 -2
  33. package/lib/root-constructs/nextjs-regional-containers.js +1 -1
  34. package/lib/root-constructs/nextjs-regional-functions.js +3 -2
  35. package/lib/runtime/lambda.mjs +4 -1
  36. package/lib/runtime/server.mjs +4 -1
  37. package/lib/utils/viewer-request-functions.d.ts +53 -0
  38. package/lib/utils/viewer-request-functions.js +172 -0
  39. package/lib/utils/viewer-request-functions.test.d.ts +1 -0
  40. package/lib/utils/viewer-request-functions.test.js +43 -0
  41. package/package.json +4 -1
  42. package/scripts/e2e-harness/README.md +10 -8
  43. package/scripts/e2e-harness/app.js +7 -2
  44. package/scripts/render-diagrams.mjs +121 -0
package/README.md CHANGED
@@ -36,6 +36,17 @@ Deploy [Next.js](https://nextjs.org/) apps on [AWS](https://aws.amazon.com/) wit
36
36
  - [Bring Your Own Resources](#bring-your-own-resources) — import existing AWS resources (CloudFront distributions, ECS clusters, ALBs, S3 buckets, DynamoDB tables).
37
37
  - [AWS GovCloud (US)](https://aws.amazon.com/govcloud-us) compatible with `NextjsRegionalFunctions` and `NextjsRegionalContainers`.
38
38
 
39
+ ## Why
40
+
41
+ The simplest path to deploy Next.js is on [Vercel](https://vercel.com/) - the Platform-as-a-Service company behind Next.js. However, deploying to Vercel can be expensive and some developers want all of their workloads running _directly_ on AWS. Developers can deploy Next.js on AWS through [AWS Amplify Hosting](https://docs.aws.amazon.com/amplify/latest/userguide/ssr-Amplifysupport.html), but Amplify does not support all Next.js features and manages AWS resources for you so they cannot be customized. If Amplify meets your requirements we recommend you use it, but if you want to use all Next.js features or want more visibility into the AWS resources then this construct is for you.
42
+
43
+ ## Design Principles
44
+
45
+ - Integrate through Next.js's official interfaces. Build on the [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters) API and [`@next/routing`](https://www.npmjs.com/package/@next/routing) rather than Next.js internals, so new Next.js versions rarely break this construct. Where no public interface exists yet, the dependency is listed in [Next.js private APIs](docs/nextjs-private-apis.md).
46
+ - Security first.
47
+ - One architecture does not fit all.
48
+ - Enable customization everywhere.
49
+
39
50
  ## Prerequisites
40
51
 
41
52
  - Next.js app running v16.3 or higher (`next build` fails on older versions). If you don't have one yet - follow [these steps](https://nextjs.org/docs/getting-started) to create one.
@@ -102,6 +113,34 @@ new WebStack(app, "web-stack");
102
113
 
103
114
  See [examples/](./examples/) for more usage examples.
104
115
 
116
+ ## Architecture
117
+
118
+ How requests are served inside the compute — the adapter runtime, and where it deliberately differs from `next start` — is in [docs/adapter-runtime.md](./docs/adapter-runtime.md).
119
+
120
+ ### `NextjsGlobalFunctions`
121
+
122
+ Architecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this construct when you have unpredictable traffic, can afford occasional latency (i.e. cold starts - [typically 1% of production traffic](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/)), and/or want the most granular pricing model. ([code](./src/root-constructs/nextjs-global-functions.ts))
123
+
124
+ ![NextjsGlobalFunctions architecture: User to CloudFront, which serves S3 static assets and forwards to a Lambda function backed by a DynamoDB table and S3 cache bucket](https://raw.githubusercontent.com/cdklabs/cdk-nextjs/main/docs/diagrams/nextjs-global-functions.svg)
125
+
126
+ ### `NextjsGlobalContainers`
127
+
128
+ Architecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this option when you have predictable traffic, need the lowest latency, and/or can afford a less granular pricing model. ([code](./src/root-constructs/nextjs-global-containers.ts))
129
+
130
+ ![NextjsGlobalContainers architecture: User to CloudFront, which serves S3 static assets and forwards to an Application Load Balancer and ECS Fargate containers in a VPC, backed by a DynamoDB table and S3 cache bucket](https://raw.githubusercontent.com/cdklabs/cdk-nextjs/main/docs/diagrams/nextjs-global-containers.svg)
131
+
132
+ ### `NextjsRegionalContainers`
133
+
134
+ Architecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) to regionally serve requests. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-containers.ts#L41))
135
+
136
+ ![NextjsRegionalContainers architecture: User to an Application Load Balancer and ECS Fargate containers in a VPC, backed by a DynamoDB table and S3 cache bucket](https://raw.githubusercontent.com/cdklabs/cdk-nextjs/main/docs/diagrams/nextjs-regional-containers.svg)
137
+
138
+ ### `NextjsRegionalFunctions`
139
+
140
+ Architecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) to regionally serve requests and distribute static assets. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-functions.ts))
141
+
142
+ ![NextjsRegionalFunctions architecture: User to an API Gateway REST API, which serves S3 static assets and forwards to a Lambda function backed by a DynamoDB table and S3 cache bucket](https://raw.githubusercontent.com/cdklabs/cdk-nextjs/main/docs/diagrams/nextjs-regional-functions.svg)
143
+
105
144
  ## Configuration
106
145
 
107
146
  The variables below are read at runtime by the cache handler inside your deployed
@@ -415,114 +454,90 @@ Notes:
415
454
  - Per-group `overrides` let you size each function independently:
416
455
  `{ name: "reports", routes: [...], overrides: { functionProps: { memorySize: 2048 } } }`.
417
456
 
418
- ## Architecture
457
+ ## Running Code on Every Viewer Request
419
458
 
420
- How requests are served inside the compute — the adapter runtime, and where it deliberately differs from `next start` — is in [docs/adapter-runtime.md](./docs/adapter-runtime.md).
421
-
422
- ### `NextjsGlobalFunctions`
423
-
424
- Architecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this construct when you have unpredictable traffic, can afford occasional latency (i.e. cold starts - [typically 1% of production traffic](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/)), and/or want the most granular pricing model. ([code](./src/root-constructs/nextjs-global-functions.ts))
425
-
426
- ```mermaid
427
- architecture-beta
428
- group aws(cloud)[AWS Cloud]
429
- group cache[Cache Layer] in aws
430
-
431
- service user(internet)[User]
432
- service cloudfront(server)[CloudFront Distribution] in aws
433
- service s3static(disk)[S3 Static Assets] in aws
434
- service lambda(server)[Lambda Function] in aws
435
- service dynamodb(database)[DynamoDB Table] in cache
436
- service s3cache(disk)[S3 Cache Bucket] in cache
437
-
438
- user:R --> L:cloudfront
439
- cloudfront:R --> L:s3static
440
- cloudfront:R --> L:lambda
441
- lambda:R --> L:dynamodb
442
- lambda:R --> L:s3cache
443
- ```
444
-
445
- ### `NextjsGlobalContainers`
446
-
447
- Architecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) Distribution to globally serve requests and distribute static assets. Use this option when you have predictable traffic, need the lowest latency, and/or can afford a less granular pricing model. ([code](./src/root-constructs/nextjs-global-containers.ts))
448
-
449
- ```mermaid
450
- architecture-beta
451
- group aws(cloud)[AWS Cloud]
452
- group vpc[VPC] in aws
453
- group cache[Cache Layer] in aws
454
-
455
- service user(internet)[User]
456
- service cloudfront(server)[CloudFront Distribution] in aws
457
- service s3static(disk)[S3 Static Assets] in aws
458
- service alb(server)[Application Load Balancer] in vpc
459
- service fargate(server)[ECS Fargate Containers] in vpc
460
- service dynamodb(database)[DynamoDB Table] in cache
461
- service s3cache(disk)[S3 Cache Bucket] in cache
462
-
463
- user:R --> L:cloudfront
464
- cloudfront:R --> L:s3static
465
- cloudfront:R --> L:alb
466
- alb:R --> L:fargate
467
- fargate:R --> L:dynamodb
468
- fargate:R --> L:s3cache
469
- ```
470
-
471
- ### `NextjsRegionalContainers`
459
+ `NextjsGlobalFunctions` and `NextjsGlobalContainers` take a
460
+ `viewerRequestFunctionCode` prop: CloudFront Function code that runs first on
461
+ every request, on every behavior cdk-nextjs adds — pages, API routes,
462
+ `_next/image`, `_next/static` and `public/` files alike. It's the place for a
463
+ gate the whole site has to pass, such as HTTP Basic auth before launch:
472
464
 
473
- Architecture includes [ECS Fargate](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) containers to respond to dynamic requests and [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) to regionally serve requests. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-containers.ts#L41))
465
+ ```ts
466
+ import { FunctionCode, KeyValueStore } from "aws-cdk-lib/aws-cloudfront";
474
467
 
475
- ```mermaid
476
- architecture-beta
477
- group aws(cloud)[AWS Cloud]
478
- group vpc[VPC] in aws
479
- group cache[Cache Layer] in aws
480
-
481
- service user(internet)[User]
482
- service alb(server)[Application Load Balancer] in vpc
483
- service fargate(server)[ECS Fargate Containers] in vpc
484
- service dynamodb(database)[DynamoDB Table] in cache
485
- service s3cache(disk)[S3 Cache Bucket] in cache
486
-
487
- user:R --> L:alb
488
- alb:R --> L:fargate
489
- fargate:R --> L:dynamodb
490
- fargate:R --> L:s3cache
468
+ const credentials = new KeyValueStore(this, "Credentials");
469
+ new NextjsGlobalFunctions(this, "Nextjs", {
470
+ buildDirectory: join(import.meta.dirname),
471
+ viewerRequestKeyValueStore: credentials,
472
+ viewerRequestFunctionCode: FunctionCode.fromInline(`
473
+ import cf from "cloudfront";
474
+ const kvs = cf.kvs();
475
+ async function viewerRequest(event) {
476
+ const auth = event.request.headers.authorization;
477
+ try {
478
+ if (auth && auth.value === "Basic " + (await kvs.get("basic-auth"))) {
479
+ // verified: don't pass the site's credentials on to the origin
480
+ delete event.request.headers.authorization;
481
+ return;
482
+ }
483
+ } catch (e) {
484
+ // no "basic-auth" key yet: stay locked
485
+ }
486
+ return {
487
+ statusCode: 401,
488
+ statusDescription: "Unauthorized",
489
+ headers: { "www-authenticate": { value: 'Basic realm="preview"' } },
490
+ };
491
+ }
492
+ `),
493
+ });
491
494
  ```
492
495
 
493
- ### `NextjsRegionalFunctions`
496
+ Then put the credentials in the store, outside the template:
494
497
 
495
- Architecture includes [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) Functions to respond to dynamic requests and [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) to regionally serve requests and distribute static assets. Use this options when you cannot use Amazon CloudFront (i.e. [AWS GovCloud](https://aws.amazon.com/govcloud-us/?whats-new.sort-by=item.additionalFields.postDateTime&whats-new.sort-order=desc)). ([code](./src/root-constructs/nextjs-regional-functions.ts))
496
-
497
- ```mermaid
498
- architecture-beta
499
- group aws(cloud)[AWS Cloud]
500
- group cache[Cache Layer] in aws
501
-
502
- service user(internet)[User]
503
- service apigateway(server)[API Gateway REST API] in aws
504
- service s3static(disk)[S3 Static Assets] in aws
505
- service lambda(server)[Lambda Function] in aws
506
- service dynamodb(database)[DynamoDB Table] in cache
507
- service s3cache(disk)[S3 Cache Bucket] in cache
508
-
509
- user:R --> L:apigateway
510
- apigateway:R --> L:s3static
511
- apigateway:R --> L:lambda
512
- lambda:R --> L:dynamodb
513
- lambda:R --> L:s3cache
498
+ ```sh
499
+ KVS_ARN=... # the store's ARN
500
+ aws cloudfront-keyvaluestore put-key --kvs-arn "$KVS_ARN" \
501
+ --key basic-auth --value "$(printf 'user:pass' | base64 | tr -d '\n')" \
502
+ --if-match "$(aws cloudfront-keyvaluestore describe-key-value-store \
503
+ --kvs-arn "$KVS_ARN" --query ETag --output text)"
514
504
  ```
515
505
 
516
- ## Why
517
-
518
- The simplest path to deploy Next.js is on [Vercel](https://vercel.com/) - the Platform-as-a-Service company behind Next.js. However, deploying to Vercel can be expensive and some developers want all of their workloads running _directly_ on AWS. Developers can deploy Next.js on AWS through [AWS Amplify Hosting](https://docs.aws.amazon.com/amplify/latest/userguide/ssr-Amplifysupport.html), but Amplify does not support all Next.js features and manages AWS resources for you so they cannot be customized. If Amplify meets your requirements we recommend you use it, but if you want to use all Next.js features or want more visibility into the AWS resources then this construct is for you.
519
-
520
- ## Design Principles
521
-
522
- - Integrate through Next.js's official interfaces. Build on the [Deployment Adapter](https://nextjs.org/docs/app/guides/deployment-adapters) API and [`@next/routing`](https://www.npmjs.com/package/@next/routing) rather than Next.js internals, so new Next.js versions rarely break this construct. Where no public interface exists yet, the dependency is listed in [Next.js private APIs](docs/nextjs-private-apis.md).
523
- - Security first.
524
- - One architecture does not fit all.
525
- - Enable customization everywhere.
506
+ The code must define `viewerRequest(event)`, as a function (`async` or not)
507
+ or a `var`/`let`/`const`. It's a CloudFront Function handler in all but name:
508
+ return a response to answer the viewer, or the request (or nothing) to carry
509
+ on.
510
+
511
+ Why not a function of your own on viewer-request? CloudFront allows one per
512
+ event type per behavior, and on Global Functions cdk-nextjs's own one
513
+ overwrites `X-Forwarded-Host` and redirects repeated slashes. So your code is
514
+ spliced into that function, ahead of cdk-nextjs's logic, which still runs after
515
+ it, so your code can't undo the `X-Forwarded-Host` overwrite. Middleware can't
516
+ do this instead: on Global Functions CloudFront signs the request to the
517
+ Function URL with the `Authorization` header, and static assets never reach the
518
+ server at all.
519
+
520
+ - cdk-nextjs's CloudFront Functions run on `cloudfront-js-2.0`, so your code
521
+ can be `async`, and `import cf from "cloudfront"` works when it comes first,
522
+ as it does above.
523
+ - `viewerRequestKeyValueStore` is associated with every viewer-request function
524
+ your code is copied into (up to three, one per kind of behavior), so
525
+ `cf.kvs()` reads it with no ID wherever the code runs. Credentials written
526
+ inline in the code instead end up in the CloudFormation template.
527
+ - The combined function, cdk-nextjs's code included, must fit CloudFront's
528
+ 10 KB limit; synth fails if it doesn't (or warns, if the code contains a
529
+ CDK token, whose size isn't known until deploy).
530
+ - Your code shares the file with cdk-nextjs's `handler`, so it can't use the
531
+ name `handler` at all, even in a comment or a string; synth refuses it.
532
+ - A viewer-request association in `overrides.*BehaviorOptions.functionAssociations`
533
+ on a behavior this covers is refused at synth; put that logic in
534
+ `viewerRequestFunctionCode` instead. So is
535
+ `overrides.distributionProps.defaultBehavior` without a `basePath`, since it
536
+ would replace the default behavior the code runs on; customize it through
537
+ `overrides.dynamicBehaviorOptions`.
538
+ - A bring-your-own `distribution`'s default behavior is yours, so it isn't
539
+ covered. Only the behaviors cdk-nextjs adds are; under a `basePath`, those
540
+ include the ones that stand in for the default behavior.
526
541
 
527
542
  ## Bring Your Own Resources
528
543
 
@@ -447,8 +447,10 @@ absolute URLs, cached for other viewers). Now:
447
447
 
448
448
  - associations on other event types (viewer-response, say) are added next to it;
449
449
  - an association on viewer-request throws at synth, since CloudFront allows one
450
- function per event type per behavior. Move that logic to viewer-response or
451
- into middleware.
450
+ function per event type per behavior. Move that logic into the
451
+ `viewerRequestFunctionCode` prop, which runs it inside cdk-nextjs's own
452
+ viewer-request function on every behavior, static assets included (see
453
+ [Running Code on Every Viewer Request](../README.md#running-code-on-every-viewer-request)).
452
454
 
453
455
  The runtime trusts `X-Forwarded-Host` only on a request Lambda reports as
454
456
  IAM-authenticated, so a Function URL overridden to `authType: NONE` builds its
@@ -66,3 +66,13 @@ Both `build` and `dev` chain it explicitly (`npm run sync-cdk-nextjs && next …
66
66
  For iterative development, just run `pnpm build` from the root to rebuild the adapter, then `pnpm build` in the example app—the sync step will copy the latest version.
67
67
 
68
68
  Note that `pnpm install` recreates the `link:../..` symlink, so always go through `pnpm build` / `pnpm dev`. Invoking `next build` or `next dev` directly skips the sync and Turbopack then fails on the symlinked path, e.g. `FileSystemPath("app-playground").join("./../../lib/adapter/cache-handler.mjs") leaves the filesystem root`.
69
+
70
+ ## Architecture Diagrams
71
+
72
+ The README's architecture diagrams are Mermaid [`architecture-beta`](https://mermaid.js.org/syntax/architecture.html) sources in [`docs/diagrams/`](./diagrams/), rendered to SVG with AWS icons from the Iconify [`logos`](https://icon-sets.iconify.design/logos/?keyword=aws) set (`logos:aws-lambda`, `logos:aws-cloudfront`, ...). After editing a `.mmd` file:
73
+
74
+ ```bash
75
+ pnpm diagrams
76
+ ```
77
+
78
+ Commit the `.mmd` and the regenerated `.svg` together. `pnpm test` fails if an SVG is stale against its source. The README links the SVGs on `main`, so a PR's README preview shows the old diagrams until it merges; open the SVG in the PR's files view to see the new one.
@@ -39,8 +39,8 @@ verify, which every e2e-harness run does in shard 1).
39
39
  | edge-free (the hard ceiling) | 1009 |
40
40
  | candidates after every screen | **165** |
41
41
  | deployed and screened | 472 |
42
- | in `rules.include` | 421 |
43
- | plus, per-case, in `suites` | 14 |
42
+ | in `rules.include` | 419 |
43
+ | plus, per-case, in `suites` | 16 |
44
44
 
45
45
  16.4 reopened the candidate pool. next.js replaced most `skipDeployment: true`
46
46
  calls with `// @force-gate !deploy` pragmas, and in doing so dropped the deploy
@@ -57,7 +57,7 @@ included files passing on each scheduled run.
57
57
 
58
58
  | Verdict | Files |
59
59
  | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
60
- | pass | 421 whole files, plus the passing cases of the 14 `suites` files |
60
+ | pass | 419 whole files, plus the passing cases of the 16 `suites` files |
61
61
  | fixed | the defects in the table below |
62
62
  | bug | none open |
63
63
  | upstream | 2 — `rewrites-destination-query-array`, `incremental-cache-path-traversal` |
@@ -136,9 +136,10 @@ The list is the manifest's `rules.include`; it is not duplicated here. Notes wor
136
136
  having when one of them goes red:
137
137
 
138
138
  - **Retry passes.** `app-dir/router-autoscroll`, `app-dir/bfcache-regression` and
139
- `app-dir/third-parties` each failed attempt 0 once on their own scroll or embed
140
- assertions, with no cdk-nextjs error, and passed on retry 1. The harness runs
141
- `--retries 1`. Suspect these first if a run goes red for no other reason.
139
+ `app-dir/third-parties` (now in `suites`) each failed attempt 0 once on their
140
+ own scroll or embed assertions, with no cdk-nextjs error, and passed on retry 1.
141
+ The harness runs `--retries 1`. Suspect these first if a run goes red for no
142
+ other reason.
142
143
  - **Slowest file:** `instrumentation-client-hook`, ~677s.
143
144
  - **Weakest coverage:** the three `chrome-devtools-workspace` files assert only
144
145
  `status: 404` in deploy mode (the dev-only endpoint must not be reachable in
@@ -178,6 +179,15 @@ verdict below.
178
179
  | `app-dir/metadata-streaming-parallel-routes` | 4 / 6 | 2 `should only bundle the selected metadata resolution implementation` — no signal (`@gate !deploy` inversion) |
179
180
  | `app-dir/segment-cache/metadata` | 2 / 3 | `requests only the head when the page segments are cached` — no signal (`@gate !deploy` inversion) |
180
181
  | `app-dir/segment-cache/cached-navigations` | 19 / 20 | `caches a fully static on-demand param for repeated navigations` — unsupported (`next start` serving) |
182
+ | `third-parties` (+ `app-dir/third-parties/basic`) | 3 / 4 each | `renders GTM` — no signal (counts Google's live `dataLayer` events) |
183
+
184
+ Both `third-parties` files' `renders GTM` expects `window.dataLayer` to hold
185
+ exactly the entry the page pushes. Around 2026-10-08 googletagmanager.com started
186
+ answering the fixtures' `GTM-XYZ` with a 200 instead of a 404, so Google's script
187
+ runs and adds its own events; the length came back 3 on every NextjsType, both
188
+ attempts, in the 2026-10-13 scheduled run. Upstream rewrote both cases to look for
189
+ its own entries after v16.4.0 (vercel/next.js#99896). Drop the entries once the
190
+ pin includes that change.
181
191
 
182
192
  The `next-form` case submits right after the page loads and waits for the loading
183
193
  state the router prefetched; where the prefetch has not landed, `#loading` never
@@ -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. 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.
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. S3 can't send the `Service-Worker-Allowed` header Next.js adds for a service worker (the app's `basePath`, or `/`), which lets it register at a scope above its own directory, so a build with service workers gets a `_next/static/service-worker/*` cache behavior (CloudFront, one more against the behavior quota) or resource (API Gateway) that sends it. `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.12",
954
+ version: "0.7.14",
952
955
  packageManager: "pnpm@10.32.1",
953
956
  jest: {
954
957
  coverageProvider: "v8",
@@ -20,6 +20,12 @@ export interface OptionalNextjsApiProps {
20
20
  * @stability stable
21
21
  */
22
22
  readonly staticAssetsKeyPrefix?: string;
23
+ /**
24
+ * The `Service-Worker-Allowed` header for `_next/static/service-worker/*`, which Next.js sends so a compiled service worker can register at a scope wider than its own directory, such as `/`. S3 can't send an arbitrary header, so setting this adds a resource for those files whose integration response does. Next.js uses the app's `basePath`, or `/` for none.
25
+ * @default - no resource; the build has no service worker
26
+ * @stability stable
27
+ */
28
+ readonly serviceWorkerAllowed?: string;
23
29
  /**
24
30
  * Required if `NextjsRegionalFunctions`.
25
31
  * The Lambda function for server-side rendering
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNBcGlQcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0FwaVByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2VjMiwgYXdzX2xhbWJkYSwgYXdzX3MzIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHR5cGUgeyBQdWJsaWNEaXJFbnRyeSB9IGZyb20gJy4uLyc7XG5cbi8qKlxuICogT3B0aW9uYWxOZXh0anNBcGlQcm9wc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbmFsTmV4dGpzQXBpUHJvcHMge1xuICAvKipcbiAgICogW0Z1dHVyZV0gUmVxdWlyZWQgaWYgYE5leHRqc1JlZ2lvbmFsQ29udGFpbmVyc2AuXG4gICAqIFZQQyB0byBjcmVhdGUgVlBDIExpbmsgYW5kIEVDUyBTZXJ2aWNlIERpc2NvdmVyeVxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogYXdzX2VjMi5JVnBjO1xuICAvKipcbiAgICogUzMga2V5IHByZWZpeCB0aGUgc3RhdGljIGFzc2V0cyB3ZXJlIHVwbG9hZGVkIHVuZGVyLCBpLmUuIGBOZXh0anNTdGF0aWNBc3NldHMua2V5UHJlZml4YCwgd2hpY2ggbmFtZXNwYWNlcyBhIHNoYXJlZCBidWNrZXQuXG4gICAqIEluZGVwZW5kZW50IG9mIGBiYXNlUGF0aGAgYWJvdmU6IHRoYXQgb25lIGlzIHRoZSBVUkwgcHJlZml4IHRoZSBSRVNUIEFQSVxuICAgKiBzZXJ2ZXMgdGhlIGFwcCBhdCAoY29tbW9ubHkgdGhlIEFQSSBHYXRld2F5IHN0YWdlKSwgd2hpbGUgdGhpcyBvbmUgaXMgd2hlcmVcbiAgICogdGhlIG9iamVjdHMgbGl2ZSBpbiB0aGUgYnVja2V0LiBgX25leHQvc3RhdGljYCBhbmQgcHVibGljIGRpcmVjdG9yeVxuICAgKiByZXF1ZXN0cyBhcmUgbWFwcGVkIHRvIFMzIGtleXMgZGlyZWN0bHksIHNvIHRoZXkgNDA0IHVubGVzcyB0aGlzIHByZWZpeCBpc1xuICAgKiBhcHBsaWVkLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzS2V5UHJlZml4Pzogc3RyaW5nO1xuICAvKipcbiAgICogUmVxdWlyZWQgaWYgYE5leHRqc1JlZ2lvbmFsRnVuY3Rpb25zYC5cbiAgICogVGhlIExhbWJkYSBmdW5jdGlvbiBmb3Igc2VydmVyLXNpZGUgcmVuZGVyaW5nXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJGdW5jdGlvbj86IGF3c19sYW1iZGEuSUZ1bmN0aW9uO1xuICAvKipcbiAgICogRGVwbG95IHRoZSBzdGFnZSBhZ2FpbiBvbmNlIGVhY2ggc3RhY2sgdXBkYXRlIGhhcyBmaW5pc2hlZCwgc28gaXQgc2VydmVzIHRoZSBBUEkgYXMgaXQgaXMgYWZ0ZXIgdGhlIHVwZGF0ZS5cbiAgICogQ2xvdWRGb3JtYXRpb24gc25hcHNob3RzIHRoZSBBUEkgaW50byBhIG5ldyBkZXBsb3ltZW50IHdoaWxlIHJlc291cmNlc1xuICAgKiByZW1vdmVkIGZyb20gdGhlIHRlbXBsYXRlIHN0aWxsIGV4aXN0IOKAlCBpdCBkZWxldGVzIHRoZW0gb25seSBkdXJpbmdcbiAgICogY2xlYW51cCDigJQgc28gdGhlIHN0YWdlIGtlZXBzIHNlcnZpbmcgdGhlbS4gQWZ0ZXIgcmVtb3ZpbmcgYSBmdW5jdGlvblxuICAgKiBncm91cCwgaXRzIHJvdXRlcyB0aGVuIHBvaW50IGF0IGEgZGVsZXRlZCBMYW1iZGEgYW5kIGFuc3dlciA1MDAgdW50aWwgdGhlXG4gICAqIG5leHQgZGVwbG95bWVudC4gQW4gRXZlbnRCcmlkZ2UgcnVsZSBvbiB0aGlzIHN0YWNrJ3MgYFVQREFURV9DT01QTEVURWBcbiAgICogKGFuZCBgVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFYCkgaW52b2tlcyBhIHNtYWxsIGZ1bmN0aW9uIHRoYXQgZGVwbG95cyB0aGVcbiAgICogc3RhZ2UgZnJvbSB0aGUgbGl2ZSBBUEkgYW5kIGRlbGV0ZXMgdGhlIGRlcGxveW1lbnRzIGl0cyBlYXJsaWVyIHJ1bnMgbWFkZS5cbiAgICpcbiAgICogSWdub3JlZCB3aGVuIGBvdmVycmlkZXMucmVzdEFwaVByb3BzLmRlcGxveWAgaXMgYGZhbHNlYDogdGhlcmUgaXMgbm8gc3RhZ2UuXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHJlZGVwbG95QWZ0ZXJVcGRhdGU/OiBib29sZWFuO1xuICAvKipcbiAgICogT3B0aW9uYWwgYmFzZSBwYXRoIGZvciB0aGUgYXBwbGljYXRpb24uXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBiYXNlUGF0aD86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBTMyBidWNrZXQgY29udGFpbmluZyBzdGF0aWMgYXNzZXRzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzQnVja2V0PzogYXdzX3MzLklCdWNrZXQ7XG4gIC8qKlxuICAgKiBQYXRoIHRvIGRpcmVjdG9yeSBvZiBOZXh0LmpzIGFwcCdzIHB1YmxpYyBkaXJlY3RvcnkuIFVzZWQgdG8gYWRkIHJlc291cmNlcyB0byBBUEkgR2F0ZXdheSBSRVNUIEFQSSBmb3IgcHVibGljIGRpcmVjdG9yeSB0byBnbyBkaXJlY3RseSB0byBTMy5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHB1YmxpY0RpckVudHJpZXM/OiBBcnJheTxQdWJsaWNEaXJFbnRyeT47XG59XG4iXX0=
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNBcGlQcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0FwaVByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2VjMiwgYXdzX2xhbWJkYSwgYXdzX3MzIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHR5cGUgeyBQdWJsaWNEaXJFbnRyeSB9IGZyb20gJy4uLyc7XG5cbi8qKlxuICogT3B0aW9uYWxOZXh0anNBcGlQcm9wc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbmFsTmV4dGpzQXBpUHJvcHMge1xuICAvKipcbiAgICogW0Z1dHVyZV0gUmVxdWlyZWQgaWYgYE5leHRqc1JlZ2lvbmFsQ29udGFpbmVyc2AuXG4gICAqIFZQQyB0byBjcmVhdGUgVlBDIExpbmsgYW5kIEVDUyBTZXJ2aWNlIERpc2NvdmVyeVxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogYXdzX2VjMi5JVnBjO1xuICAvKipcbiAgICogUzMga2V5IHByZWZpeCB0aGUgc3RhdGljIGFzc2V0cyB3ZXJlIHVwbG9hZGVkIHVuZGVyLCBpLmUuIGBOZXh0anNTdGF0aWNBc3NldHMua2V5UHJlZml4YCwgd2hpY2ggbmFtZXNwYWNlcyBhIHNoYXJlZCBidWNrZXQuXG4gICAqIEluZGVwZW5kZW50IG9mIGBiYXNlUGF0aGAgYWJvdmU6IHRoYXQgb25lIGlzIHRoZSBVUkwgcHJlZml4IHRoZSBSRVNUIEFQSVxuICAgKiBzZXJ2ZXMgdGhlIGFwcCBhdCAoY29tbW9ubHkgdGhlIEFQSSBHYXRld2F5IHN0YWdlKSwgd2hpbGUgdGhpcyBvbmUgaXMgd2hlcmVcbiAgICogdGhlIG9iamVjdHMgbGl2ZSBpbiB0aGUgYnVja2V0LiBgX25leHQvc3RhdGljYCBhbmQgcHVibGljIGRpcmVjdG9yeVxuICAgKiByZXF1ZXN0cyBhcmUgbWFwcGVkIHRvIFMzIGtleXMgZGlyZWN0bHksIHNvIHRoZXkgNDA0IHVubGVzcyB0aGlzIHByZWZpeCBpc1xuICAgKiBhcHBsaWVkLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGljQXNzZXRzS2V5UHJlZml4Pzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGBTZXJ2aWNlLVdvcmtlci1BbGxvd2VkYCBoZWFkZXIgZm9yIGBfbmV4dC9zdGF0aWMvc2VydmljZS13b3JrZXIvKmAsIHdoaWNoIE5leHQuanMgc2VuZHMgc28gYSBjb21waWxlZCBzZXJ2aWNlIHdvcmtlciBjYW4gcmVnaXN0ZXIgYXQgYSBzY29wZSB3aWRlciB0aGFuIGl0cyBvd24gZGlyZWN0b3J5LCBzdWNoIGFzIGAvYC4gUzMgY2FuJ3Qgc2VuZCBhbiBhcmJpdHJhcnkgaGVhZGVyLCBzbyBzZXR0aW5nIHRoaXMgYWRkcyBhIHJlc291cmNlIGZvciB0aG9zZSBmaWxlcyB3aG9zZSBpbnRlZ3JhdGlvbiByZXNwb25zZSBkb2VzLiBOZXh0LmpzIHVzZXMgdGhlIGFwcCdzIGBiYXNlUGF0aGAsIG9yIGAvYCBmb3Igbm9uZS5cbiAgICogQGRlZmF1bHQgLSBubyByZXNvdXJjZTsgdGhlIGJ1aWxkIGhhcyBubyBzZXJ2aWNlIHdvcmtlclxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZVdvcmtlckFsbG93ZWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzUmVnaW9uYWxGdW5jdGlvbnNgLlxuICAgKiBUaGUgTGFtYmRhIGZ1bmN0aW9uIGZvciBzZXJ2ZXItc2lkZSByZW5kZXJpbmdcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHNlcnZlckZ1bmN0aW9uPzogYXdzX2xhbWJkYS5JRnVuY3Rpb247XG4gIC8qKlxuICAgKiBEZXBsb3kgdGhlIHN0YWdlIGFnYWluIG9uY2UgZWFjaCBzdGFjayB1cGRhdGUgaGFzIGZpbmlzaGVkLCBzbyBpdCBzZXJ2ZXMgdGhlIEFQSSBhcyBpdCBpcyBhZnRlciB0aGUgdXBkYXRlLlxuICAgKiBDbG91ZEZvcm1hdGlvbiBzbmFwc2hvdHMgdGhlIEFQSSBpbnRvIGEgbmV3IGRlcGxveW1lbnQgd2hpbGUgcmVzb3VyY2VzXG4gICAqIHJlbW92ZWQgZnJvbSB0aGUgdGVtcGxhdGUgc3RpbGwgZXhpc3Qg4oCUIGl0IGRlbGV0ZXMgdGhlbSBvbmx5IGR1cmluZ1xuICAgKiBjbGVhbnVwIOKAlCBzbyB0aGUgc3RhZ2Uga2VlcHMgc2VydmluZyB0aGVtLiBBZnRlciByZW1vdmluZyBhIGZ1bmN0aW9uXG4gICAqIGdyb3VwLCBpdHMgcm91dGVzIHRoZW4gcG9pbnQgYXQgYSBkZWxldGVkIExhbWJkYSBhbmQgYW5zd2VyIDUwMCB1bnRpbCB0aGVcbiAgICogbmV4dCBkZXBsb3ltZW50LiBBbiBFdmVudEJyaWRnZSBydWxlIG9uIHRoaXMgc3RhY2sncyBgVVBEQVRFX0NPTVBMRVRFYFxuICAgKiAoYW5kIGBVUERBVEVfUk9MTEJBQ0tfQ09NUExFVEVgKSBpbnZva2VzIGEgc21hbGwgZnVuY3Rpb24gdGhhdCBkZXBsb3lzIHRoZVxuICAgKiBzdGFnZSBmcm9tIHRoZSBsaXZlIEFQSSBhbmQgZGVsZXRlcyB0aGUgZGVwbG95bWVudHMgaXRzIGVhcmxpZXIgcnVucyBtYWRlLlxuICAgKlxuICAgKiBJZ25vcmVkIHdoZW4gYG92ZXJyaWRlcy5yZXN0QXBpUHJvcHMuZGVwbG95YCBpcyBgZmFsc2VgOiB0aGVyZSBpcyBubyBzdGFnZS5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVkZXBsb3lBZnRlclVwZGF0ZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBPcHRpb25hbCBiYXNlIHBhdGggZm9yIHRoZSBhcHBsaWNhdGlvbi5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGJhc2VQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIFMzIGJ1Y2tldCBjb250YWluaW5nIHN0YXRpYyBhc3NldHMuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBzdGF0aWNBc3NldHNCdWNrZXQ/OiBhd3NfczMuSUJ1Y2tldDtcbiAgLyoqXG4gICAqIFBhdGggdG8gZGlyZWN0b3J5IG9mIE5leHQuanMgYXBwJ3MgcHVibGljIGRpcmVjdG9yeS4gVXNlZCB0byBhZGQgcmVzb3VyY2VzIHRvIEFQSSBHYXRld2F5IFJFU1QgQVBJIGZvciBwdWJsaWMgZGlyZWN0b3J5IHRvIGdvIGRpcmVjdGx5IHRvIFMzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgcHVibGljRGlyRW50cmllcz86IEFycmF5PFB1YmxpY0RpckVudHJ5Pjtcbn1cbiJdfQ==
@@ -4,6 +4,33 @@ 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;
28
+ /**
29
+ * The `Service-Worker-Allowed` header for `_next/static/service-worker/*`, which Next.js sends so a compiled service worker can register at a scope wider than its own directory, such as `/`. S3 can't send an arbitrary header, so setting this adds a behavior for those files whose response headers policy does. Next.js uses the app's `basePath`, or `/` for none.
30
+ * @default - no behavior; the build has no service worker
31
+ * @stability stable
32
+ */
33
+ readonly serviceWorkerAllowed?: string;
7
34
  /**
8
35
  * The most cache behaviors the distribution may have, the default one included.
9
36
  * 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+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBBIENsb3VkRnJvbnQgS2V5VmFsdWVTdG9yZSBhc3NvY2lhdGVkIHdpdGggZXZlcnkgdmlld2VyLXJlcXVlc3QgZnVuY3Rpb24ge0BsaW5rIHZpZXdlclJlcXVlc3RGdW5jdGlvbkNvZGV9IGlzIGNvcGllZCBpbnRvICh1cCB0byB0aHJlZSwgb25lIHBlciBraW5kIG9mIGJlaGF2aW9yKSwgc28gdmFsdWVzIGl0IHJlYWRzIOKAlCBCYXNpYyBhdXRoIGNyZWRlbnRpYWxzLCBhbiBhbGxvd2xpc3Qg4oCUIGxpdmUgb3V0c2lkZSB0aGUgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUgYW5kIGNoYW5nZSB3aXRob3V0IGEgZGVwbG95LlxuICAgKiBSZWFkIGl0IHdpdGggYGNmLmt2cygpYCwgbm8gSUQgbmVlZGVkLlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHZpZXdlclJlcXVlc3RLZXlWYWx1ZVN0b3JlPzogYXdzX2Nsb3VkZnJvbnQuSUtleVZhbHVlU3RvcmU7XG4gIC8qKlxuICAgKiBDbG91ZEZyb250IEZ1bmN0aW9uIGNvZGUgcnVuIGZpcnN0IG9uIGV2ZXJ5IHZpZXdlciByZXF1ZXN0LCBvbiBldmVyeSBiZWhhdmlvciBjZGstbmV4dGpzIGFkZHMsIHN0YXRpYyBhc3NldHMgaW5jbHVkZWQg4oCUIEhUVFAgQmFzaWMgYXV0aCBvbiBhIHByZS1sYXVuY2ggc2l0ZSwgZ2VvLWdhdGluZy5cbiAgICogSXQgbXVzdCBkZWZpbmUgYHZpZXdlclJlcXVlc3QoZXZlbnQpYCAoYSBmdW5jdGlvbiwgc3luYyBvciBhc3luYywgb3IgYVxuICAgKiBgdmFyYC9gbGV0YC9gY29uc3RgKTogcmV0dXJuIGEgcmVzcG9uc2UgdG8gYW5zd2VyIHRoZSB2aWV3ZXIsIG9yIHRoZVxuICAgKiByZXF1ZXN0IChvciBub3RoaW5nKSB0byBjYXJyeSBvbi4gSXQgaXMgc3BsaWNlZCBpbnRvIGNkay1uZXh0anMncyBvd25cbiAgICogdmlld2VyLXJlcXVlc3QgZnVuY3Rpb25zLCBhaGVhZCBvZiB0aGVpciBsb2dpYywgc28gaXQgbWF5IG5vdCB1c2UgdGhlXG4gICAqIG5hbWUgYGhhbmRsZXJgLCBhbmQgdGhlIGNvbWJpbmVkIGZ1bmN0aW9uIG11c3QgZml0IENsb3VkRnJvbnQncyAxMCBLQi5cbiAgICogSXQgcnVucyBvbiBgY2xvdWRmcm9udC1qcy0yLjBgLCBzbyBpdCBtYXkgYmUgYXN5bmMgYW5kIHJlYWRcbiAgICoge0BsaW5rIHZpZXdlclJlcXVlc3RLZXlWYWx1ZVN0b3JlfSB3aXRoIGBjZi5rdnMoKWAuIEEgYnJpbmcteW91ci1vd25cbiAgICoge0BsaW5rIGRpc3RyaWJ1dGlvbn0ncyBkZWZhdWx0IGJlaGF2aW9yIGlzbid0IGNvdmVyZWQuXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgdmlld2VyUmVxdWVzdEZ1bmN0aW9uQ29kZT86IGF3c19jbG91ZGZyb250LkZ1bmN0aW9uQ29kZTtcbiAgLyoqXG4gICAqIFRoZSBgU2VydmljZS1Xb3JrZXItQWxsb3dlZGAgaGVhZGVyIGZvciBgX25leHQvc3RhdGljL3NlcnZpY2Utd29ya2VyLypgLCB3aGljaCBOZXh0LmpzIHNlbmRzIHNvIGEgY29tcGlsZWQgc2VydmljZSB3b3JrZXIgY2FuIHJlZ2lzdGVyIGF0IGEgc2NvcGUgd2lkZXIgdGhhbiBpdHMgb3duIGRpcmVjdG9yeSwgc3VjaCBhcyBgL2AuIFMzIGNhbid0IHNlbmQgYW4gYXJiaXRyYXJ5IGhlYWRlciwgc28gc2V0dGluZyB0aGlzIGFkZHMgYSBiZWhhdmlvciBmb3IgdGhvc2UgZmlsZXMgd2hvc2UgcmVzcG9uc2UgaGVhZGVycyBwb2xpY3kgZG9lcy4gTmV4dC5qcyB1c2VzIHRoZSBhcHAncyBgYmFzZVBhdGhgLCBvciBgL2AgZm9yIG5vbmUuXG4gICAqIEBkZWZhdWx0IC0gbm8gYmVoYXZpb3I7IHRoZSBidWlsZCBoYXMgbm8gc2VydmljZSB3b3JrZXJcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VXb3JrZXJBbGxvd2VkPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIG1vc3QgY2FjaGUgYmVoYXZpb3JzIHRoZSBkaXN0cmlidXRpb24gbWF5IGhhdmUsIHRoZSBkZWZhdWx0IG9uZSBpbmNsdWRlZC5cbiAgICogY2RrLW5leHRqcyBjb3VudHMgd2hhdCBpdCBhZGRzIGFnYWluc3QgdGhpcyBhdCBzeW50aCwgc28gcnVubmluZ1xuICAgKiBvdXQgaXMgYSBzeW50aCBlcnJvciBuYW1pbmcgd2hhdCB1c2VkIHRoZW0gcmF0aGVyIHRoYW4gYSBmYWlsZWQgZGVwbG95LlxuICAgKlxuICAgKiBSYWlzZSBpdCBhZnRlciByYWlzaW5nIHRoZSBcIkNhY2hlIGJlaGF2aW9ycyBwZXIgZGlzdHJpYnV0aW9uXCIgcXVvdGEgZm9yXG4gICAqIHlvdXIgYWNjb3VudC4gTG93ZXIgaXQgYnkgdGhlIGJlaGF2aW9ycyBhIHN1cHBsaWVkIHtAbGluayBkaXN0cmlidXRpb259XG4gICAqIChvciBgb3ZlcnJpZGVzLmRpc3RyaWJ1dGlvblByb3BzYCkgYWxyZWFkeSBoYXMsIHdoaWNoIGFyZSBub3QgY291bnRlZC5cbiAgICogQGRlZmF1bHQgNzUgLSBDbG91ZEZyb250J3MgZGVmYXVsdCBxdW90YVxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgbWF4Q2FjaGVCZWhhdmlvcnM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2Agb3IgYE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI/OiBhd3NfZWxhc3RpY2xvYWRiYWxhbmNpbmd2Mi5JQXBwbGljYXRpb25Mb2FkQmFsYW5jZXI7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzVHlwZS5HTE9CQUxfRlVOQ1RJT05TYC5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uVXJsPzogYXdzX2xhbWJkYS5JRnVuY3Rpb25Vcmw7XG4gIC8qKlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgZGlzdHJpYnV0aW9uPzogYXdzX2Nsb3VkZnJvbnQuRGlzdHJpYnV0aW9uO1xuICAvKipcbiAgICogT3B0aW9uYWwgYnV0IG9ubHkgYXBwbGljYWJsZSBmb3IgYE5leHRqc1R5cGUuR0xPQkFMX0NPTlRBSU5FUlNgLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgY2VydGlmaWNhdGU/OiBhd3NfY2VydGlmaWNhdGVtYW5hZ2VyLklDZXJ0aWZpY2F0ZTtcbiAgLyoqXG4gICAqIFVSSSBwYXRoIHByZWZpeCB0aGUgYXBwIGlzIHNlcnZlZCBhdC5cbiAgICogU3Vycm91bmRpbmcgc2xhc2hlcyBhcmUgbm9ybWFsaXplZFxuICAgKiBhd2F5LCBzbyBcIi9iYXNlXCIsIFwiYmFzZVwiIGFuZCBcIi9iYXNlL1wiIGFsbCBwcm9kdWNlIHRoZSBzYW1lIGNhY2hlIGJlaGF2aW9ycy5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGJhc2VQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGFwcCdzIG93biBgYXNzZXRQcmVmaXhgLlxuICAgKiBOZXh0LmpzIGVtaXRzIGA8YXNzZXRQcmVmaXg+L19uZXh0L3N0YXRpYy8uLi5gXG4gICAqIGZvciBldmVyeSBidW5kbGUgd2hpbGUgdGhlIG9iamVjdHMgc3RheSBhdCBgPGJhc2VQYXRoPi9fbmV4dC9zdGF0aWMvLi4uYCBpblxuICAgKiBTMywgc28gdGhlIHByZWZpeCdzIHBhdGggZ2V0cyBhIGNhY2hlIGJlaGF2aW9yIG9mIGl0cyBvd24gdGhhdCByZXdyaXRlcyBpdFxuICAgKiBhd2F5LlxuICAgKlxuICAgKiBFaXRoZXIgZm9ybSBpcyBhY2NlcHRlZDogYSBwYXRoIChcIi9jZG5cIiksIG9yIGFuIGFic29sdXRlIFVSTCwgaW4gd2hpY2ggY2FzZVxuICAgKiBvbmx5IGl0cyBwYXRoIGNvdW50cyAoXCJodHRwczovL2Nkbi5leGFtcGxlLmNvbS9jZG5cIiBiZWhhdmVzIGFzIFwiL2NkblwiLCBhbmRcbiAgICogXCJodHRwczovL2Nkbi5leGFtcGxlLmNvbVwiIG5lZWRzIG5vIGJlaGF2aW9yIGF0IGFsbCkuIEFuIGFic29sdXRlIHByZWZpeCdzIHBhdGhcbiAgICogbWF0dGVycyBiZWNhdXNlIGBuZXh0IGJ1aWxkYCBjb21waWxlcyBhIGAvY2RuL19uZXh0LzpwYXRoK2AgcmV3cml0ZSBvZiBpdHNcbiAgICogb3duLCBzbyBgbmV4dCBzdGFydGAgc2VydmVzIGV2ZXJ5IGJ1bmRsZSB1bmRlciBpdCDigJQgYSBDRE4gZnJvbnRpbmcgdGhpc1xuICAgKiBkaXN0cmlidXRpb24gdGhlcmUgaGFzIHRvIGJlIGFuc3dlcmVkIHRvby5cbiAgICpcbiAgICogQXBwbGllZCBvbiB0b3Agb2YgYGJhc2VQYXRoYCwgbm90IHVuZGVyIGl0LCBiZWNhdXNlIHRoYXQgaXMgaG93IE5leHQuanNcbiAgICogYnVpbGRzIHRoZSBVUkwuXG4gICAqIEBkZWZhdWx0IC0gbm9uZTsgcGFzcyBgTmV4dGpzQnVpbGQubmV4dENvbmZpZ0Fzc2V0UHJlZml4UGF0aGBcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGFzc2V0UHJlZml4Pzogc3RyaW5nO1xuICAvKipcbiAgICogRW50cmllcyAoZmlsZXMvZGlyZWN0b3JpZXMpIHdpdGhpbiBOZXh0LmpzIGFwcCdzIHB1YmxpYyBkaXJlY3RvcnkuIFVzZWQgdG8gYWRkIHN0YXRpYyBiZWhhdmlvcnMgdG8gZGlzdHJpYnV0aW9uLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgcHVibGljRGlyRW50cmllcz86IEFycmF5PFB1YmxpY0RpckVudHJ5PjtcbiAgLyoqXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBuZXh0anNUeXBlPzogTmV4dGpzVHlwZTtcbiAgLyoqXG4gICAqIEJ1Y2tldCBjb250YWluaW5nIHN0YXRpYyBhc3NldHMuXG4gICAqIE11c3QgYmUgcHJvdmlkZWQgaWYgeW91IHdhbnQgdG8gc2VydmUgc3RhdGljIGZpbGVzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRzQnVja2V0PzogYXdzX3MzLklCdWNrZXQ7XG59XG4iXX0=
@@ -51,6 +51,15 @@ export interface NextjsApiProps {
51
51
  * applied.
52
52
  */
53
53
  readonly staticAssetsKeyPrefix?: string;
54
+ /**
55
+ * The `Service-Worker-Allowed` header for `_next/static/service-worker/*`,
56
+ * which Next.js sends so a compiled service worker can register at a scope
57
+ * wider than its own directory, such as `/`. S3 can't send an arbitrary
58
+ * header, so setting this adds a resource for those files whose integration
59
+ * response does. Next.js uses the app's `basePath`, or `/` for none.
60
+ * @default - no resource; the build has no service worker
61
+ */
62
+ readonly serviceWorkerAllowed?: string;
54
63
  /**
55
64
  * [Future] Required if `NextjsRegionalContainers`. VPC to create VPC Link and ECS Service Discovery
56
65
  */
@@ -155,8 +164,10 @@ export declare class NextjsApi extends Construct {
155
164
  * Maps API request to S3 request.
156
165
  * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-parameter-mapping-sources.html
157
166
  * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html#api-items-in-folder-as-s3-objects-in-bucket
167
+ * @param headers fixed response headers, sent with a 200 and a 304
158
168
  */
159
169
  private createS3Integration;
170
+ /** @param headers the fixed headers `createS3Integration` was given */
160
171
  private getStaticMethodOptions;
161
172
  /**
162
173
  * One resource subtree per function group pattern.