cdk-nextjs 0.5.16 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.jsii +290 -183
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +244 -4
  4. package/README.md +2 -2
  5. package/docs/breaking-changes.md +53 -0
  6. package/docs/development-guide.md +6 -4
  7. package/lib/adapter/adapter.mjs +1 -1
  8. package/lib/adapter/cache-handler.mjs +1 -1
  9. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +3 -0
  10. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  11. package/lib/image-optimization/handler-utils.d.ts +7 -5
  12. package/lib/image-optimization/handler-utils.js +17 -11
  13. package/lib/image-optimization/handler-utils.test.js +42 -6
  14. package/lib/image-optimization/handler.mjs +20 -6
  15. package/lib/nextjs-api.d.ts +26 -0
  16. package/lib/nextjs-api.js +41 -13
  17. package/lib/nextjs-api.test.d.ts +1 -0
  18. package/lib/nextjs-api.test.js +144 -0
  19. package/lib/nextjs-build/nextjs-build.d.ts +8 -0
  20. package/lib/nextjs-build/nextjs-build.js +12 -2
  21. package/lib/nextjs-cache.js +1 -1
  22. package/lib/nextjs-compute/nextjs-containers.js +1 -1
  23. package/lib/nextjs-compute/nextjs-functions.js +1 -1
  24. package/lib/nextjs-compute/nextjs-image-function.d.ts +10 -0
  25. package/lib/nextjs-compute/nextjs-image-function.js +3 -2
  26. package/lib/nextjs-distribution.d.ts +11 -0
  27. package/lib/nextjs-distribution.js +16 -10
  28. package/lib/nextjs-post-deploy.js +1 -1
  29. package/lib/nextjs-static-assets.d.ts +18 -0
  30. package/lib/nextjs-static-assets.js +33 -6
  31. package/lib/nextjs-static-assets.test.d.ts +1 -0
  32. package/lib/nextjs-static-assets.test.js +58 -0
  33. package/lib/root-constructs/nextjs-base-construct.d.ts +38 -1
  34. package/lib/root-constructs/nextjs-base-construct.js +41 -3
  35. package/lib/root-constructs/nextjs-global-containers.d.ts +6 -1
  36. package/lib/root-constructs/nextjs-global-containers.js +11 -5
  37. package/lib/root-constructs/nextjs-global-functions.d.ts +5 -0
  38. package/lib/root-constructs/nextjs-global-functions.js +10 -4
  39. package/lib/root-constructs/nextjs-regional-containers.js +1 -1
  40. package/lib/root-constructs/nextjs-regional-functions.js +5 -5
  41. package/lib/utils/base-path.d.ts +40 -0
  42. package/lib/utils/base-path.js +123 -0
  43. package/lib/utils/base-path.test.d.ts +1 -0
  44. package/lib/utils/base-path.test.js +163 -0
  45. package/package.json +1 -1
package/API.md CHANGED
@@ -124,6 +124,7 @@ Any object.
124
124
  | --- | --- | --- |
125
125
  | <code><a href="#cdk-nextjs.NextjsApi.property.node">node</a></code> | <code>constructs.Node</code> | The tree node. |
126
126
  | <code><a href="#cdk-nextjs.NextjsApi.property.api">api</a></code> | <code>aws-cdk-lib.aws_apigateway.RestApi</code> | The API Gateway REST API. |
127
+ | <code><a href="#cdk-nextjs.NextjsApi.property.url">url</a></code> | <code>string</code> | Public URL of the app, including every path segment the API nests it under. |
127
128
 
128
129
  ---
129
130
 
@@ -151,6 +152,25 @@ The API Gateway REST API.
151
152
 
152
153
  ---
153
154
 
155
+ ##### `url`<sup>Required</sup> <a name="url" id="cdk-nextjs.NextjsApi.property.url"></a>
156
+
157
+ ```typescript
158
+ public readonly url: string;
159
+ ```
160
+
161
+ - *Type:* string
162
+
163
+ Public URL of the app, including every path segment the API nests it under.
164
+
165
+ Prefers a custom domain configured through `overrides.restApiProps.domainName`
166
+ over the execute-api endpoint.
167
+
168
+ A domain attached after this construct is created (`api.addDomainName()`) is
169
+ still used for the host, but CDK keeps its base path mappings private, so a
170
+ mapping added that way won't show up here.
171
+
172
+ ---
173
+
154
174
 
155
175
  ### NextjsBaseConstruct <a name="NextjsBaseConstruct" id="cdk-nextjs.NextjsBaseConstruct"></a>
156
176
 
@@ -466,6 +486,7 @@ Any object.
466
486
  | <code><a href="#cdk-nextjs.NextjsBuild.property.buildId">buildId</a></code> | <code>string</code> | Unique id for Next.js build. Used to partition cache storage and as metadata for static assets in S3 bucket. |
467
487
  | <code><a href="#cdk-nextjs.NextjsBuild.property.dotNextPath">dotNextPath</a></code> | <code>string</code> | Absolute path to the .next directory containing Next.js build artifacts. |
468
488
  | <code><a href="#cdk-nextjs.NextjsBuild.property.initCacheDir">initCacheDir</a></code> | <code>string</code> | Absolute path to the init cache directory. |
489
+ | <code><a href="#cdk-nextjs.NextjsBuild.property.nextConfigBasePath">nextConfigBasePath</a></code> | <code>string</code> | The Next.js app's own `basePath` — the URL prefix it generates its links and asset hrefs under — read out of the build's `required-server-files.json`. Normalized to a bare path segment, empty when the app sets none. Exposed so root constructs can reconcile it with the CDK `basePath` prop, which is a distinct thing; see `resolveBasePath`. |
469
490
  | <code><a href="#cdk-nextjs.NextjsBuild.property.publicDirEntries">publicDirEntries</a></code> | <code><a href="#cdk-nextjs.PublicDirEntry">PublicDirEntry</a>[]</code> | Absolute path to public. |
470
491
  | <code><a href="#cdk-nextjs.NextjsBuild.property.relativePathToEntrypoint">relativePathToEntrypoint</a></code> | <code>string</code> | The entrypoint JavaScript file used as an argument for Node.js to run the Next.js standalone server relative to the standalone directory. |
471
492
  | <code><a href="#cdk-nextjs.NextjsBuild.property.relativePathToPackage">relativePathToPackage</a></code> | <code>string</code> | Relative path from the standalone directory to the package containing the Next.js app. This is automatically detected from the standalone build output. |
@@ -528,6 +549,18 @@ Absolute path to the init cache directory.
528
549
  ```
529
550
 
530
551
 
552
+ ##### `nextConfigBasePath`<sup>Required</sup> <a name="nextConfigBasePath" id="cdk-nextjs.NextjsBuild.property.nextConfigBasePath"></a>
553
+
554
+ ```typescript
555
+ public readonly nextConfigBasePath: string;
556
+ ```
557
+
558
+ - *Type:* string
559
+
560
+ The Next.js app's own `basePath` — the URL prefix it generates its links and asset hrefs under — read out of the build's `required-server-files.json`. Normalized to a bare path segment, empty when the app sets none. Exposed so root constructs can reconcile it with the CDK `basePath` prop, which is a distinct thing; see `resolveBasePath`.
561
+
562
+ ---
563
+
531
564
  ##### `publicDirEntries`<sup>Required</sup> <a name="publicDirEntries" id="cdk-nextjs.NextjsBuild.property.publicDirEntries"></a>
532
565
 
533
566
  ```typescript
@@ -1408,7 +1441,7 @@ Any object.
1408
1441
  | **Name** | **Type** | **Description** |
1409
1442
  | --- | --- | --- |
1410
1443
  | <code><a href="#cdk-nextjs.NextjsGlobalContainers.property.node">node</a></code> | <code>constructs.Node</code> | The tree node. |
1411
- | <code><a href="#cdk-nextjs.NextjsGlobalContainers.property.url">url</a></code> | <code>string</code> | *No description.* |
1444
+ | <code><a href="#cdk-nextjs.NextjsGlobalContainers.property.url">url</a></code> | <code>string</code> | Public URL of the app, including `basePath` — the app only answers under that prefix, and it's derived from the app's own `basePath` when the prop is left unset, so it's there whether or not you asked for it. |
1412
1445
  | <code><a href="#cdk-nextjs.NextjsGlobalContainers.property.nextjsBuild">nextjsBuild</a></code> | <code><a href="#cdk-nextjs.NextjsBuild">NextjsBuild</a></code> | *No description.* |
1413
1446
  | <code><a href="#cdk-nextjs.NextjsGlobalContainers.property.nextjsCache">nextjsCache</a></code> | <code><a href="#cdk-nextjs.NextjsCache">NextjsCache</a></code> | *No description.* |
1414
1447
  | <code><a href="#cdk-nextjs.NextjsGlobalContainers.property.nextjsStaticAssets">nextjsStaticAssets</a></code> | <code><a href="#cdk-nextjs.NextjsStaticAssets">NextjsStaticAssets</a></code> | *No description.* |
@@ -1438,6 +1471,8 @@ public readonly url: string;
1438
1471
 
1439
1472
  - *Type:* string
1440
1473
 
1474
+ Public URL of the app, including `basePath` — the app only answers under that prefix, and it's derived from the app's own `basePath` when the prop is left unset, so it's there whether or not you asked for it.
1475
+
1441
1476
  ---
1442
1477
 
1443
1478
  ##### `nextjsBuild`<sup>Required</sup> <a name="nextjsBuild" id="cdk-nextjs.NextjsGlobalContainers.property.nextjsBuild"></a>
@@ -1622,7 +1657,7 @@ Any object.
1622
1657
  | **Name** | **Type** | **Description** |
1623
1658
  | --- | --- | --- |
1624
1659
  | <code><a href="#cdk-nextjs.NextjsGlobalFunctions.property.node">node</a></code> | <code>constructs.Node</code> | The tree node. |
1625
- | <code><a href="#cdk-nextjs.NextjsGlobalFunctions.property.url">url</a></code> | <code>string</code> | *No description.* |
1660
+ | <code><a href="#cdk-nextjs.NextjsGlobalFunctions.property.url">url</a></code> | <code>string</code> | Public URL of the app, including `basePath` — the app only answers under that prefix, and it's derived from the app's own `basePath` when the prop is left unset, so it's there whether or not you asked for it. |
1626
1661
  | <code><a href="#cdk-nextjs.NextjsGlobalFunctions.property.nextjsBuild">nextjsBuild</a></code> | <code><a href="#cdk-nextjs.NextjsBuild">NextjsBuild</a></code> | *No description.* |
1627
1662
  | <code><a href="#cdk-nextjs.NextjsGlobalFunctions.property.nextjsCache">nextjsCache</a></code> | <code><a href="#cdk-nextjs.NextjsCache">NextjsCache</a></code> | *No description.* |
1628
1663
  | <code><a href="#cdk-nextjs.NextjsGlobalFunctions.property.nextjsStaticAssets">nextjsStaticAssets</a></code> | <code><a href="#cdk-nextjs.NextjsStaticAssets">NextjsStaticAssets</a></code> | *No description.* |
@@ -1653,6 +1688,8 @@ public readonly url: string;
1653
1688
 
1654
1689
  - *Type:* string
1655
1690
 
1691
+ Public URL of the app, including `basePath` — the app only answers under that prefix, and it's derived from the app's own `basePath` when the prop is left unset, so it's there whether or not you asked for it.
1692
+
1656
1693
  ---
1657
1694
 
1658
1695
  ##### `nextjsBuild`<sup>Required</sup> <a name="nextjsBuild" id="cdk-nextjs.NextjsGlobalFunctions.property.nextjsBuild"></a>
@@ -2609,6 +2646,7 @@ Any object.
2609
2646
  | **Name** | **Type** | **Description** |
2610
2647
  | --- | --- | --- |
2611
2648
  | <code><a href="#cdk-nextjs.NextjsStaticAssets.property.node">node</a></code> | <code>constructs.Node</code> | The tree node. |
2649
+ | <code><a href="#cdk-nextjs.NextjsStaticAssets.property.keyPrefix">keyPrefix</a></code> | <code>string</code> | S3 key prefix the assets are actually uploaded under, normalized to a bare path segment (empty when they live at the bucket root). |
2612
2650
  | <code><a href="#cdk-nextjs.NextjsStaticAssets.property.bucket">bucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | *No description.* |
2613
2651
  | <code><a href="#cdk-nextjs.NextjsStaticAssets.property.deployment">deployment</a></code> | <code>aws-cdk-lib.aws_s3_deployment.BucketDeployment</code> | *No description.* |
2614
2652
 
@@ -2626,6 +2664,23 @@ The tree node.
2626
2664
 
2627
2665
  ---
2628
2666
 
2667
+ ##### `keyPrefix`<sup>Required</sup> <a name="keyPrefix" id="cdk-nextjs.NextjsStaticAssets.property.keyPrefix"></a>
2668
+
2669
+ ```typescript
2670
+ public readonly keyPrefix: string;
2671
+ ```
2672
+
2673
+ - *Type:* string
2674
+
2675
+ S3 key prefix the assets are actually uploaded under, normalized to a bare path segment (empty when they live at the bucket root).
2676
+
2677
+ Consumers that read assets back out of the bucket (the image optimization
2678
+ Lambda, `NextjsApi`'s S3 integrations) must use this rather than the
2679
+ `basePath` prop, since `overrides.bucketDeploymentProps` can replace the
2680
+ prefix outright.
2681
+
2682
+ ---
2683
+
2629
2684
  ##### `bucket`<sup>Required</sup> <a name="bucket" id="cdk-nextjs.NextjsStaticAssets.property.bucket"></a>
2630
2685
 
2631
2686
  ```typescript
@@ -2741,6 +2796,7 @@ const nextjsApiProps: NextjsApiProps = { ... }
2741
2796
  | <code><a href="#cdk-nextjs.NextjsApiProps.property.imageFunction">imageFunction</a></code> | <code>aws-cdk-lib.aws_lambda.IFunction</code> | Dedicated image optimization Lambda for the `_next/image` route. |
2742
2797
  | <code><a href="#cdk-nextjs.NextjsApiProps.property.overrides">overrides</a></code> | <code><a href="#cdk-nextjs.NextjsApiOverrides">NextjsApiOverrides</a></code> | Override props for every construct. |
2743
2798
  | <code><a href="#cdk-nextjs.NextjsApiProps.property.serverFunction">serverFunction</a></code> | <code>aws-cdk-lib.aws_lambda.IFunction</code> | Required if `NextjsRegionalFunctions`. |
2799
+ | <code><a href="#cdk-nextjs.NextjsApiProps.property.staticAssetsKeyPrefix">staticAssetsKeyPrefix</a></code> | <code>string</code> | S3 key prefix the static assets were uploaded under, i.e. `NextjsStaticAssets.keyPrefix`, which namespaces a shared bucket. |
2744
2800
  | <code><a href="#cdk-nextjs.NextjsApiProps.property.vpc">vpc</a></code> | <code>aws-cdk-lib.aws_ec2.IVpc</code> | [Future] Required if `NextjsRegionalContainers`. |
2745
2801
 
2746
2802
  ---
@@ -2830,6 +2886,24 @@ The Lambda function for server-side rendering
2830
2886
 
2831
2887
  ---
2832
2888
 
2889
+ ##### `staticAssetsKeyPrefix`<sup>Optional</sup> <a name="staticAssetsKeyPrefix" id="cdk-nextjs.NextjsApiProps.property.staticAssetsKeyPrefix"></a>
2890
+
2891
+ ```typescript
2892
+ public readonly staticAssetsKeyPrefix: string;
2893
+ ```
2894
+
2895
+ - *Type:* string
2896
+
2897
+ S3 key prefix the static assets were uploaded under, i.e. `NextjsStaticAssets.keyPrefix`, which namespaces a shared bucket.
2898
+
2899
+ Independent of `basePath` above: that one is the URL prefix the REST API
2900
+ serves the app at (commonly the API Gateway stage), while this one is where
2901
+ the objects live in the bucket. `_next/static` and public directory
2902
+ requests are mapped to S3 keys directly, so they 404 unless this prefix is
2903
+ applied.
2904
+
2905
+ ---
2906
+
2833
2907
  ##### `vpc`<sup>Optional</sup> <a name="vpc" id="cdk-nextjs.NextjsApiProps.property.vpc"></a>
2834
2908
 
2835
2909
  ```typescript
@@ -2978,6 +3052,29 @@ public readonly basePath: string;
2978
3052
 
2979
3053
  Prefix to the URI path the app will be served at.
2980
3054
 
3055
+ Also namespaces the
3056
+ static assets in S3, so it doubles as a way to host multiple apps or
3057
+ branches out of one bucket.
3058
+
3059
+ How this relates to the `basePath` in your app's `next.config.js` depends
3060
+ on the construct, and synth fails on a combination that can't serve the
3061
+ app:
3062
+
3063
+ - `NextjsGlobalFunctions`/`NextjsGlobalContainers`: leave this unset and it
3064
+ follows your app's `basePath`, which is what you want — CloudFront serves
3065
+ static assets from S3 using the request path as the object key, so the two
3066
+ have to be identical and a mismatch 404s all of them. Setting a different
3067
+ value throws.
3068
+ - `NextjsRegionalFunctions`: if you set this, the app's `basePath` must end
3069
+ with it — either equal to it, or prefixed by the stage or base path
3070
+ mapping API Gateway strips before matching resources (`basePath:
3071
+ "/prod/base"` with this set to `"/base"`). Leaving it unset while the app
3072
+ sets one is correct and common — an app served at the default `prod` stage
3073
+ sets `basePath: "/prod"` and leaves this alone.
3074
+ - `NextjsRegionalContainers`: only namespaces the S3 bucket. The ALB sends
3075
+ every path to the container, which serves its own static assets, so this
3076
+ is unconstrained.
3077
+
2981
3078
  ---
2982
3079
 
2983
3080
  *Example*
@@ -3213,6 +3310,29 @@ public readonly basePath: string;
3213
3310
 
3214
3311
  Prefix to the URI path the app will be served at.
3215
3312
 
3313
+ Also namespaces the
3314
+ static assets in S3, so it doubles as a way to host multiple apps or
3315
+ branches out of one bucket.
3316
+
3317
+ How this relates to the `basePath` in your app's `next.config.js` depends
3318
+ on the construct, and synth fails on a combination that can't serve the
3319
+ app:
3320
+
3321
+ - `NextjsGlobalFunctions`/`NextjsGlobalContainers`: leave this unset and it
3322
+ follows your app's `basePath`, which is what you want — CloudFront serves
3323
+ static assets from S3 using the request path as the object key, so the two
3324
+ have to be identical and a mismatch 404s all of them. Setting a different
3325
+ value throws.
3326
+ - `NextjsRegionalFunctions`: if you set this, the app's `basePath` must end
3327
+ with it — either equal to it, or prefixed by the stage or base path
3328
+ mapping API Gateway strips before matching resources (`basePath:
3329
+ "/prod/base"` with this set to `"/base"`). Leaving it unset while the app
3330
+ sets one is correct and common — an app served at the default `prod` stage
3331
+ sets `basePath: "/prod"` and leaves this alone.
3332
+ - `NextjsRegionalContainers`: only namespaces the S3 bucket. The ALB sends
3333
+ every path to the container, which serves its own static assets, so this
3334
+ is unconstrained.
3335
+
3216
3336
  ---
3217
3337
 
3218
3338
  *Example*
@@ -4032,7 +4152,7 @@ const nextjsDistributionProps: NextjsDistributionProps = { ... }
4032
4152
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.assetsBucket">assetsBucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | Bucket containing static assets. |
4033
4153
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.nextjsType">nextjsType</a></code> | <code><a href="#cdk-nextjs.NextjsType">NextjsType</a></code> | *No description.* |
4034
4154
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.publicDirEntries">publicDirEntries</a></code> | <code><a href="#cdk-nextjs.PublicDirEntry">PublicDirEntry</a>[]</code> | Entries (files/directories) within Next.js app's public directory. Used to add static behaviors to distribution. |
4035
- | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.basePath">basePath</a></code> | <code>string</code> | *No description.* |
4155
+ | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.basePath">basePath</a></code> | <code>string</code> | URI path prefix the app is served at. |
4036
4156
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.certificate">certificate</a></code> | <code>aws-cdk-lib.aws_certificatemanager.ICertificate</code> | Optional but only applicable for `NextjsType.GLOBAL_CONTAINERS`. |
4037
4157
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.distribution">distribution</a></code> | <code>aws-cdk-lib.aws_cloudfront.Distribution</code> | *No description.* |
4038
4158
  | <code><a href="#cdk-nextjs.NextjsDistributionProps.property.functionUrl">functionUrl</a></code> | <code>aws-cdk-lib.aws_lambda.IFunctionUrl</code> | Required if `NextjsType.GLOBAL_FUNCTIONS`. |
@@ -4086,6 +4206,11 @@ public readonly basePath: string;
4086
4206
 
4087
4207
  - *Type:* string
4088
4208
 
4209
+ URI path prefix the app is served at.
4210
+
4211
+ Surrounding slashes are normalized
4212
+ away, so "/base", "base" and "/base/" all produce the same cache behaviors.
4213
+
4089
4214
  ---
4090
4215
 
4091
4216
  ##### `certificate`<sup>Optional</sup> <a name="certificate" id="cdk-nextjs.NextjsDistributionProps.property.certificate"></a>
@@ -4662,6 +4787,29 @@ public readonly basePath: string;
4662
4787
 
4663
4788
  Prefix to the URI path the app will be served at.
4664
4789
 
4790
+ Also namespaces the
4791
+ static assets in S3, so it doubles as a way to host multiple apps or
4792
+ branches out of one bucket.
4793
+
4794
+ How this relates to the `basePath` in your app's `next.config.js` depends
4795
+ on the construct, and synth fails on a combination that can't serve the
4796
+ app:
4797
+
4798
+ - `NextjsGlobalFunctions`/`NextjsGlobalContainers`: leave this unset and it
4799
+ follows your app's `basePath`, which is what you want — CloudFront serves
4800
+ static assets from S3 using the request path as the object key, so the two
4801
+ have to be identical and a mismatch 404s all of them. Setting a different
4802
+ value throws.
4803
+ - `NextjsRegionalFunctions`: if you set this, the app's `basePath` must end
4804
+ with it — either equal to it, or prefixed by the stage or base path
4805
+ mapping API Gateway strips before matching resources (`basePath:
4806
+ "/prod/base"` with this set to `"/base"`). Leaving it unset while the app
4807
+ sets one is correct and common — an app served at the default `prod` stage
4808
+ sets `basePath: "/prod"` and leaves this alone.
4809
+ - `NextjsRegionalContainers`: only namespaces the S3 bucket. The ALB sends
4810
+ every path to the container, which serves its own static assets, so this
4811
+ is unconstrained.
4812
+
4665
4813
  ---
4666
4814
 
4667
4815
  *Example*
@@ -5101,6 +5249,29 @@ public readonly basePath: string;
5101
5249
 
5102
5250
  Prefix to the URI path the app will be served at.
5103
5251
 
5252
+ Also namespaces the
5253
+ static assets in S3, so it doubles as a way to host multiple apps or
5254
+ branches out of one bucket.
5255
+
5256
+ How this relates to the `basePath` in your app's `next.config.js` depends
5257
+ on the construct, and synth fails on a combination that can't serve the
5258
+ app:
5259
+
5260
+ - `NextjsGlobalFunctions`/`NextjsGlobalContainers`: leave this unset and it
5261
+ follows your app's `basePath`, which is what you want — CloudFront serves
5262
+ static assets from S3 using the request path as the object key, so the two
5263
+ have to be identical and a mismatch 404s all of them. Setting a different
5264
+ value throws.
5265
+ - `NextjsRegionalFunctions`: if you set this, the app's `basePath` must end
5266
+ with it — either equal to it, or prefixed by the stage or base path
5267
+ mapping API Gateway strips before matching resources (`basePath:
5268
+ "/prod/base"` with this set to `"/base"`). Leaving it unset while the app
5269
+ sets one is correct and common — an app served at the default `prod` stage
5270
+ sets `basePath: "/prod"` and leaves this alone.
5271
+ - `NextjsRegionalContainers`: only namespaces the S3 bucket. The ALB sends
5272
+ every path to the container, which serves its own static assets, so this
5273
+ is unconstrained.
5274
+
5104
5275
  ---
5105
5276
 
5106
5277
  *Example*
@@ -5290,6 +5461,7 @@ const nextjsImageFunctionProps: NextjsImageFunctionProps = { ... }
5290
5461
  | <code><a href="#cdk-nextjs.NextjsImageFunctionProps.property.nextjsType">nextjsType</a></code> | <code><a href="#cdk-nextjs.NextjsType">NextjsType</a></code> | *No description.* |
5291
5462
  | <code><a href="#cdk-nextjs.NextjsImageFunctionProps.property.staticAssetsBucket">staticAssetsBucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | S3 bucket containing static assets, read by the handler to serve non-absolute image URLs. |
5292
5463
  | <code><a href="#cdk-nextjs.NextjsImageFunctionProps.property.overrides">overrides</a></code> | <code><a href="#cdk-nextjs.NextjsImageFunctionOverrides">NextjsImageFunctionOverrides</a></code> | Override props of any construct. |
5464
+ | <code><a href="#cdk-nextjs.NextjsImageFunctionProps.property.staticAssetsKeyPrefix">staticAssetsKeyPrefix</a></code> | <code>string</code> | S3 key prefix the static assets were uploaded under, i.e. `NextjsStaticAssets.keyPrefix`, which namespaces a shared bucket. |
5293
5465
  | <code><a href="#cdk-nextjs.NextjsImageFunctionProps.property.vpc">vpc</a></code> | <code>aws-cdk-lib.aws_ec2.IVpc</code> | *No description.* |
5294
5466
 
5295
5467
  ---
@@ -5342,6 +5514,23 @@ Override props of any construct.
5342
5514
 
5343
5515
  ---
5344
5516
 
5517
+ ##### `staticAssetsKeyPrefix`<sup>Optional</sup> <a name="staticAssetsKeyPrefix" id="cdk-nextjs.NextjsImageFunctionProps.property.staticAssetsKeyPrefix"></a>
5518
+
5519
+ ```typescript
5520
+ public readonly staticAssetsKeyPrefix: string;
5521
+ ```
5522
+
5523
+ - *Type:* string
5524
+
5525
+ S3 key prefix the static assets were uploaded under, i.e. `NextjsStaticAssets.keyPrefix`, which namespaces a shared bucket.
5526
+
5527
+ Threaded through explicitly rather than read from the app's bundled config,
5528
+ because it's distinct from the app's own `basePath` (which next-image-loader
5529
+ bakes into hrefs) — the two diverge when the app's `basePath` comes from
5530
+ elsewhere, e.g. an API Gateway stage under `NextjsRegionalFunctions`.
5531
+
5532
+ ---
5533
+
5345
5534
  ##### `vpc`<sup>Optional</sup> <a name="vpc" id="cdk-nextjs.NextjsImageFunctionProps.property.vpc"></a>
5346
5535
 
5347
5536
  ```typescript
@@ -5745,6 +5934,29 @@ public readonly basePath: string;
5745
5934
 
5746
5935
  Prefix to the URI path the app will be served at.
5747
5936
 
5937
+ Also namespaces the
5938
+ static assets in S3, so it doubles as a way to host multiple apps or
5939
+ branches out of one bucket.
5940
+
5941
+ How this relates to the `basePath` in your app's `next.config.js` depends
5942
+ on the construct, and synth fails on a combination that can't serve the
5943
+ app:
5944
+
5945
+ - `NextjsGlobalFunctions`/`NextjsGlobalContainers`: leave this unset and it
5946
+ follows your app's `basePath`, which is what you want — CloudFront serves
5947
+ static assets from S3 using the request path as the object key, so the two
5948
+ have to be identical and a mismatch 404s all of them. Setting a different
5949
+ value throws.
5950
+ - `NextjsRegionalFunctions`: if you set this, the app's `basePath` must end
5951
+ with it — either equal to it, or prefixed by the stage or base path
5952
+ mapping API Gateway strips before matching resources (`basePath:
5953
+ "/prod/base"` with this set to `"/base"`). Leaving it unset while the app
5954
+ sets one is correct and common — an app served at the default `prod` stage
5955
+ sets `basePath: "/prod"` and leaves this alone.
5956
+ - `NextjsRegionalContainers`: only namespaces the S3 bucket. The ALB sends
5957
+ every path to the container, which serves its own static assets, so this
5958
+ is unconstrained.
5959
+
5748
5960
  ---
5749
5961
 
5750
5962
  *Example*
@@ -6168,6 +6380,29 @@ public readonly basePath: string;
6168
6380
 
6169
6381
  Prefix to the URI path the app will be served at.
6170
6382
 
6383
+ Also namespaces the
6384
+ static assets in S3, so it doubles as a way to host multiple apps or
6385
+ branches out of one bucket.
6386
+
6387
+ How this relates to the `basePath` in your app's `next.config.js` depends
6388
+ on the construct, and synth fails on a combination that can't serve the
6389
+ app:
6390
+
6391
+ - `NextjsGlobalFunctions`/`NextjsGlobalContainers`: leave this unset and it
6392
+ follows your app's `basePath`, which is what you want — CloudFront serves
6393
+ static assets from S3 using the request path as the object key, so the two
6394
+ have to be identical and a mismatch 404s all of them. Setting a different
6395
+ value throws.
6396
+ - `NextjsRegionalFunctions`: if you set this, the app's `basePath` must end
6397
+ with it — either equal to it, or prefixed by the stage or base path
6398
+ mapping API Gateway strips before matching resources (`basePath:
6399
+ "/prod/base"` with this set to `"/base"`). Leaving it unset while the app
6400
+ sets one is correct and common — an app served at the default `prod` stage
6401
+ sets `basePath: "/prod"` and leaves this alone.
6402
+ - `NextjsRegionalContainers`: only namespaces the S3 bucket. The ALB sends
6403
+ every path to the container, which serves its own static assets, so this
6404
+ is unconstrained.
6405
+
6171
6406
  ---
6172
6407
 
6173
6408
  *Example*
@@ -10899,7 +11134,7 @@ const optionalNextjsDistributionProps: OptionalNextjsDistributionProps = { ... }
10899
11134
  | **Name** | **Type** | **Description** |
10900
11135
  | --- | --- | --- |
10901
11136
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.assetsBucket">assetsBucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | Bucket containing static assets. |
10902
- | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.basePath">basePath</a></code> | <code>string</code> | *No description.* |
11137
+ | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.basePath">basePath</a></code> | <code>string</code> | URI path prefix the app is served at. |
10903
11138
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.certificate">certificate</a></code> | <code>aws-cdk-lib.aws_certificatemanager.ICertificate</code> | Optional but only applicable for `NextjsType.GLOBAL_CONTAINERS`. |
10904
11139
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.distribution">distribution</a></code> | <code>aws-cdk-lib.aws_cloudfront.Distribution</code> | *No description.* |
10905
11140
  | <code><a href="#cdk-nextjs.OptionalNextjsDistributionProps.property.functionUrl">functionUrl</a></code> | <code>aws-cdk-lib.aws_lambda.IFunctionUrl</code> | Required if `NextjsType.GLOBAL_FUNCTIONS`. |
@@ -10932,6 +11167,11 @@ public readonly basePath: string;
10932
11167
 
10933
11168
  - *Type:* string
10934
11169
 
11170
+ URI path prefix the app is served at.
11171
+
11172
+ Surrounding slashes are normalized
11173
+ away, so "/base", "base" and "/base/" all produce the same cache behaviors.
11174
+
10935
11175
  ---
10936
11176
 
10937
11177
  ##### `certificate`<sup>Optional</sup> <a name="certificate" id="cdk-nextjs.OptionalNextjsDistributionProps.property.certificate"></a>
package/README.md CHANGED
@@ -281,7 +281,7 @@ cdk-nextjs supports importing existing AWS resources instead of creating new one
281
281
  ### Resource Isolation
282
282
 
283
283
  - **Cache bucket and DynamoDB table** are isolated by `buildId` prefix. Multiple branches safely share one bucket/table with no conflicts.
284
- - **Static assets bucket** — Next.js includes content hashes in static asset filenames, so different branches deploying the same file will produce identical content. It's safe for branches to overwrite each other. If you're already using `basePath` for routing, assets will naturally be prefixed by it.
284
+ - **Static assets bucket** — Next.js includes content hashes in static asset filenames, so different branches deploying the same file will produce identical content. It's safe for branches to overwrite each other. If you're already using `basePath` for routing, assets will naturally be prefixed by it — `NextjsGlobalFunctions` and `NextjsGlobalContainers` read the `basePath` out of your Next.js build and use it as the S3 key prefix, since CloudFront serves assets from S3 by request path and the two can't differ. Set the `basePath` prop only if you want to be explicit about it; a value that disagrees with your app's fails at synth.
285
285
 
286
286
  ### Shared ALB and `removeAutoCreatedListener()`
287
287
 
@@ -345,7 +345,7 @@ Note: CloudFront distributions take several minutes to create/update, so this ar
345
345
  - If using `NextjsGlobalFunctions`, when [revalidating data in Next.js](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation) (i.e. [revalidatePath](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)), the CloudFront Cache will still hold stale data. You'll need to use AWS SDK JS V3 [CreateInvalidationCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-cloudfront/Class/CreateInvalidationCommand/) to manually invalidate the path in CloudFront. See more [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html).
346
346
  - If using `NextjsGlobalFunctions`, setting an Authorization header won't work by default because of Lambda Function URL with IAM Auth is already using the Authorization header. You can use the `AWS_LWA_AUTHORIZATION_SOURCE` environment variable of [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) to set an alternative Authorization header in the client which will then be set to the Authorization header when it reaches your app.
347
347
  - `NextjsRegionalFunctions` streaming depends on whether your server Lambda supports response streaming (e.g. [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter)'s `AWS_LWA_INVOKE_MODE`) — override `overrides.nextjsApi.dynamicIntegrationProps.responseTransferMode` to `BUFFERED` if it doesn't, otherwise API Gateway returns a 500 for every request.
348
- - If using `NextjsRegionalFunctions` without a custom domain, API Gateway REST APIs require a [stage name](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-stages.html) (default: `/prod`) to be specified. This causes links to pages and static assets to break because they're not prefixed with the stage name. You can work around this issue by specifying [basePath](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath) in next.config.js as your stage name. Additionally, you'll need to add middleware logic to rewrite requests to include the stage name because API Gateway does not include the stage name in the path passed to Lambda. See [examples/app-playground/middleware.ts](./examples/app-playground/middleware.ts).
348
+ - If using `NextjsRegionalFunctions` without a custom domain, API Gateway REST APIs require a [stage name](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-stages.html) (default: `/prod`) to be specified. This causes links to pages and static assets to break because they're not prefixed with the stage name. You can work around this issue by specifying [basePath](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath) in next.config.js as your stage name — leave the construct's `basePath` prop unset when you do, since API Gateway strips the stage before matching resources. Additionally, you'll need to add middleware logic to rewrite requests to include the stage name because API Gateway does not include the stage name in the path passed to Lambda. See [examples/app-playground/middleware.ts](./examples/app-playground/middleware.ts). Mapping a custom domain at the root avoids all of this — see [examples/regional-functions/README.md](./examples/regional-functions/README.md#with-a-custom-domain-no-stage-workarounds).
349
349
 
350
350
  ## Additional Security Recommendations
351
351
 
@@ -2,6 +2,59 @@
2
2
 
3
3
  ## 0.6.0
4
4
 
5
+ ### `basePath` is reconciled with your Next.js app's own `basePath`
6
+
7
+ The `basePath` prop and the `basePath` in your app's `next.config.js` are two
8
+ different things — where the infrastructure serves the app from (and which S3 key
9
+ prefix the static assets land under) versus the prefix the app emits its own
10
+ links and asset hrefs under. They used to be set independently, which silently
11
+ 404'd static assets when they disagreed. They're now checked against each other
12
+ at synth, and derived from the app where there's only one value that can work.
13
+
14
+ - `NextjsGlobalFunctions` / `NextjsGlobalContainers`: leave the prop unset and it
15
+ now follows your app's `basePath`. CloudFront hands its S3 origin the request
16
+ path verbatim as the object key, so the two can't differ — a prop that
17
+ disagrees with your app throws at synth.
18
+ - `NextjsRegionalFunctions`: the prop is never derived (API Gateway strips the
19
+ stage before matching resources, so an app served at the `prod` stage sets
20
+ `basePath: "/prod"` and leaves the prop unset). If you do set it, your app's
21
+ `basePath` must end with it — either equal to it, or prefixed by the stage or
22
+ base path mapping API Gateway strips (`basePath: "/prod/base"` with the prop
23
+ set to `"/base"`). Anything else throws.
24
+ - `NextjsRegionalContainers`: unchanged. The ALB forwards every path to the
25
+ container, which serves its own static assets, so the prop only namespaces the
26
+ S3 bucket and is unconstrained.
27
+ - Surrounding slashes on the prop are now normalized away, so `"/base"`,
28
+ `"base"` and `"/base/"` all behave identically. Previously the prop was passed
29
+ through to `NextjsDistribution` as written, so a trailing slash produced cache
30
+ behaviors like `/base//_next/static*` against keys uploaded under
31
+ `base/_next/...`, and a missing leading slash produced `base/_next/static*`.
32
+ **If you passed `basePath` without a leading slash**, your distribution's cache
33
+ behavior path patterns change from `base/…` to `/base/…` on the next deploy.
34
+ This is an in-place update of the existing distribution, not a replacement.
35
+ - On the Global constructs, an
36
+ `overrides.nextjsStaticAssets.bucketDeploymentProps.destinationKeyPrefix` that
37
+ doesn't match `basePath` now throws: CloudFront's S3 origin has no way to ask
38
+ for the objects anywhere but the request path, so a different prefix 404s every
39
+ static request.
40
+ - `NextjsGlobalFunctions.url` and `NextjsGlobalContainers.url` now include
41
+ `basePath`, and `NextjsRegionalFunctions.url` reports the custom domain and
42
+ base path mapping when one is configured. All three previously returned a URL
43
+ the app answers with a 404 under these setups.
44
+
45
+ - **Migration:** If your app sets `basePath` and you deploy a Global construct,
46
+ either drop the `basePath` prop or set it to the same value your app uses. The
47
+ first deploy after upgrading uploads the static assets under `<basePath>/` in
48
+ S3 and adds `<basePath>/_next/static*` (and `<basePath>/*`) cache behaviors to
49
+ the distribution. If you were reading `url` and appending `basePath` yourself,
50
+ remove that — it's included now.
51
+
52
+ Note: when `.next/required-server-files.json` can't be read, cdk-nextjs assumes
53
+ your app sets no `basePath` and now warns rather than staying silent, since that
54
+ fallback is otherwise indistinguishable from an app that genuinely sets none.
55
+
56
+ ## 0.5.16
57
+
5
58
  ### Functions-only overrides moved off the Containers constructs
6
59
 
7
60
  `nextjsFunctionsProps` and `nextjsImageFunctionProps` moved from
@@ -50,17 +50,19 @@ Expanding Turbopack's root to include the entire monorepo causes it to repeatedl
50
50
 
51
51
  ### The Solution (Hack)
52
52
 
53
- The `examples/app-playground/package.json` includes a `prebuild` script that copies the necessary files directly into `node_modules` without symlinks:
53
+ The `examples/app-playground/package.json` includes a `sync-cdk-nextjs` script that copies the necessary files directly into `node_modules` without symlinks:
54
54
 
55
55
  ```json
56
- "prebuild": "rm -rf node_modules/cdk-nextjs && mkdir -p node_modules/cdk-nextjs/lib/adapter && cp ../../package.json node_modules/cdk-nextjs/package.json && cp ../../lib/adapter/adapter.mjs node_modules/cdk-nextjs/lib/adapter/adapter.mjs && cp ../../lib/adapter/cache-handler.mjs node_modules/cdk-nextjs/lib/adapter/cache-handler.mjs"
56
+ "sync-cdk-nextjs": "rm -rf node_modules/cdk-nextjs && mkdir -p node_modules/cdk-nextjs/lib/adapter && cp ../../package.json node_modules/cdk-nextjs/package.json && cp ../../lib/adapter/adapter.mjs node_modules/cdk-nextjs/lib/adapter/adapter.mjs && cp ../../lib/adapter/cache-handler.mjs node_modules/cdk-nextjs/lib/adapter/cache-handler.mjs"
57
57
  ```
58
58
 
59
- This runs automatically before `pnpm build`, ensuring fresh copies of the adapter files are present. While hacky, it:
59
+ Both `build` and `dev` chain it explicitly (`npm run sync-cdk-nextjs && next …`) so the copy happens no matter which package manager invokes them. While hacky, it:
60
60
 
61
61
  - Avoids symlink issues entirely
62
62
  - Keeps Turbopack's root narrow
63
63
  - Simulates real npm package installation
64
64
  - Enables proper package export resolution
65
65
 
66
- For iterative development, just run `pnpm build` from the root to rebuild the adapter, then `pnpm build` in the example app—prebuild will copy the latest version.
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
+
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`.
@@ -1,4 +1,4 @@
1
- const require = (await import('node:module')).createRequire(import.meta.url);
1
+ import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1,4 +1,4 @@
1
- const require = (await import('node:module')).createRequire(import.meta.url);
1
+ import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -34,6 +34,9 @@ export interface OptionalNextjsDistributionProps {
34
34
  */
35
35
  readonly certificate?: aws_certificatemanager.ICertificate;
36
36
  /**
37
+ * URI path prefix the app is served at.
38
+ * Surrounding slashes are normalized
39
+ * away, so "/base", "base" and "/base/" all produce the same cache behaviors.
37
40
  * @stability stable
38
41
  */
39
42
  readonly basePath?: string;
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2Agb3IgYE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI/OiBhd3NfZWxhc3RpY2xvYWRiYWxhbmNpbmd2Mi5JQXBwbGljYXRpb25Mb2FkQmFsYW5jZXI7XG4gIC8qKlxuICAgKiBGdW5jdGlvbiBVUkwgb2YgdGhlIGRlZGljYXRlZCBpbWFnZSBvcHRpbWl6YXRpb24gTGFtYmRhLlxuICAgKiBPbmx5IGFwcGxpY2FibGVcbiAgICogdG8gYE5leHRqc1R5cGUuR0xPQkFMX0ZVTkNUSU9OU2AsIGFuZCBvbmx5IHdoZW4gdGhlIGRlZGljYXRlZCBpbWFnZVxuICAgKiBmdW5jdGlvbiBpcyBlbmFibGVkLiBXaGVuIG9taXR0ZWQsIHRoZSBgX25leHQvaW1hZ2UqYCBiZWhhdmlvciBwb2ludHMgYXRcbiAgICogdGhlIGR5bmFtaWMgb3JpZ2luLCB3aGljaCBzZXJ2ZXMgaW1hZ2Ugb3B0aW1pemF0aW9uIGZyb20gdGhlIE5leHQuanNcbiAgICogc2VydmVyIGl0c2VsZi5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlRnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlNgLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBkaXN0cmlidXRpb24/OiBhd3NfY2xvdWRmcm9udC5EaXN0cmlidXRpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBidXQgb25seSBhcHBsaWNhYmxlIGZvciBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBjZXJ0aWZpY2F0ZT86IGF3c19jZXJ0aWZpY2F0ZW1hbmFnZXIuSUNlcnRpZmljYXRlO1xuICAvKipcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGJhc2VQYXRoPzogc3RyaW5nO1xuICAvKipcbiAgICogRW50cmllcyAoZmlsZXMvZGlyZWN0b3JpZXMpIHdpdGhpbiBOZXh0LmpzIGFwcCdzIHB1YmxpYyBkaXJlY3RvcnkuIFVzZWQgdG8gYWRkIHN0YXRpYyBiZWhhdmlvcnMgdG8gZGlzdHJpYnV0aW9uLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgcHVibGljRGlyRW50cmllcz86IEFycmF5PFB1YmxpY0RpckVudHJ5PjtcbiAgLyoqXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBuZXh0anNUeXBlPzogTmV4dGpzVHlwZTtcbiAgLyoqXG4gICAqIEJ1Y2tldCBjb250YWluaW5nIHN0YXRpYyBhc3NldHMuXG4gICAqIE11c3QgYmUgcHJvdmlkZWQgaWYgeW91IHdhbnQgdG8gc2VydmUgc3RhdGljIGZpbGVzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRzQnVja2V0PzogYXdzX3MzLklCdWNrZXQ7XG59XG4iXX0=
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2Agb3IgYE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI/OiBhd3NfZWxhc3RpY2xvYWRiYWxhbmNpbmd2Mi5JQXBwbGljYXRpb25Mb2FkQmFsYW5jZXI7XG4gIC8qKlxuICAgKiBGdW5jdGlvbiBVUkwgb2YgdGhlIGRlZGljYXRlZCBpbWFnZSBvcHRpbWl6YXRpb24gTGFtYmRhLlxuICAgKiBPbmx5IGFwcGxpY2FibGVcbiAgICogdG8gYE5leHRqc1R5cGUuR0xPQkFMX0ZVTkNUSU9OU2AsIGFuZCBvbmx5IHdoZW4gdGhlIGRlZGljYXRlZCBpbWFnZVxuICAgKiBmdW5jdGlvbiBpcyBlbmFibGVkLiBXaGVuIG9taXR0ZWQsIHRoZSBgX25leHQvaW1hZ2UqYCBiZWhhdmlvciBwb2ludHMgYXRcbiAgICogdGhlIGR5bmFtaWMgb3JpZ2luLCB3aGljaCBzZXJ2ZXMgaW1hZ2Ugb3B0aW1pemF0aW9uIGZyb20gdGhlIE5leHQuanNcbiAgICogc2VydmVyIGl0c2VsZi5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlRnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlNgLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBkaXN0cmlidXRpb24/OiBhd3NfY2xvdWRmcm9udC5EaXN0cmlidXRpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBidXQgb25seSBhcHBsaWNhYmxlIGZvciBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBjZXJ0aWZpY2F0ZT86IGF3c19jZXJ0aWZpY2F0ZW1hbmFnZXIuSUNlcnRpZmljYXRlO1xuICAvKipcbiAgICogVVJJIHBhdGggcHJlZml4IHRoZSBhcHAgaXMgc2VydmVkIGF0LlxuICAgKiBTdXJyb3VuZGluZyBzbGFzaGVzIGFyZSBub3JtYWxpemVkXG4gICAqIGF3YXksIHNvIFwiL2Jhc2VcIiwgXCJiYXNlXCIgYW5kIFwiL2Jhc2UvXCIgYWxsIHByb2R1Y2UgdGhlIHNhbWUgY2FjaGUgYmVoYXZpb3JzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgYmFzZVBhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBFbnRyaWVzIChmaWxlcy9kaXJlY3Rvcmllcykgd2l0aGluIE5leHQuanMgYXBwJ3MgcHVibGljIGRpcmVjdG9yeS4gVXNlZCB0byBhZGQgc3RhdGljIGJlaGF2aW9ycyB0byBkaXN0cmlidXRpb24uXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNEaXJFbnRyaWVzPzogQXJyYXk8UHVibGljRGlyRW50cnk+O1xuICAvKipcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IG5leHRqc1R5cGU/OiBOZXh0anNUeXBlO1xuICAvKipcbiAgICogQnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0cy5cbiAgICogTXVzdCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0byBzZXJ2ZSBzdGF0aWMgZmlsZXMuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBhc3NldHNCdWNrZXQ/OiBhd3NfczMuSUJ1Y2tldDtcbn1cbiJdfQ==
@@ -2,13 +2,15 @@ import { S3Client } from "@aws-sdk/client-s3";
2
2
  /**
3
3
  * Fetches a non-absolute (local) image referenced by an `<Image>` from S3.
4
4
  *
5
- * `NextjsStaticAssets` uploads under `basePath` as a key prefix, so every key
6
- * includes it. `url` is inconsistent: next-image-loader bakes `basePath` into
5
+ * `url` is inconsistent: next-image-loader bakes the app's own `basePath` into
7
6
  * the href for statically imported images, while plain string paths are passed
8
- * through as literally written by the app. So the prefix is normalized to
9
- * exactly one occurrence rather than simply added or removed.
7
+ * through as literally written. So `nextBasePath` (the app's config) is stripped
8
+ * off, then `staticAssetsKeyPrefix` (`NextjsStaticAssets.keyPrefix`) applied.
9
+ * The two are separate arguments because nothing requires them to be the same
10
+ * value — e.g. an app whose `basePath` is an API Gateway stage, deployed without
11
+ * the CDK `basePath` prop.
10
12
  */
11
- export declare function fetchFromS3(s3: S3Client, bucket: string, url: string, basePath: string): Promise<{
13
+ export declare function fetchFromS3(s3: S3Client, bucket: string, url: string, nextBasePath: string, staticAssetsKeyPrefix?: string): Promise<{
12
14
  buffer: Buffer;
13
15
  contentType: string | null;
14
16
  etag: string;