sst 2.22.11 → 2.23.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.
- package/bootstrap.d.ts +1 -1
- package/bootstrap.js +44 -22
- package/cli/commands/bind.d.ts +0 -2
- package/cli/commands/bind.js +175 -103
- package/cli/ui/deploy.js +32 -3
- package/constructs/AstroSite.d.ts +2 -3
- package/constructs/AstroSite.js +3 -4
- package/constructs/BaseSite.d.ts +0 -71
- package/constructs/Distribution.d.ts +143 -0
- package/constructs/Distribution.js +260 -0
- package/constructs/Metadata.d.ts +3 -1
- package/constructs/NextjsSite.d.ts +3 -2
- package/constructs/NextjsSite.js +51 -42
- package/constructs/Service.d.ts +398 -0
- package/constructs/Service.js +584 -0
- package/constructs/SsrSite.d.ts +10 -25
- package/constructs/SsrSite.js +52 -241
- package/constructs/StaticSite.d.ts +20 -16
- package/constructs/StaticSite.js +40 -224
- package/constructs/deprecated/NextjsSite.d.ts +11 -2
- package/constructs/deprecated/NextjsSite.js +13 -0
- package/constructs/index.d.ts +1 -0
- package/constructs/index.js +1 -0
- package/node/event-bus/index.d.ts +4 -1
- package/node/event-bus/index.js +1 -0
- package/package.json +2 -1
- package/project.d.ts +1 -0
- package/sst.mjs +261 -115
- package/stacks/deploy.js +4 -0
- package/stacks/metadata.d.ts +1 -0
- package/stacks/metadata.js +17 -0
- package/stacks/monitor.d.ts +1 -1
- package/stacks/monitor.js +1 -0
- package/support/nixpacks/Dockerfile +6 -0
- package/support/service-dev-function/index.js +1 -0
package/constructs/BaseSite.d.ts
CHANGED
|
@@ -1,81 +1,10 @@
|
|
|
1
|
-
import { IHostedZone } from "aws-cdk-lib/aws-route53";
|
|
2
1
|
import { ErrorResponse, DistributionProps, BehaviorOptions, IOrigin } from "aws-cdk-lib/aws-cloudfront";
|
|
3
|
-
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
|
|
4
2
|
export interface BaseSiteFileOptions {
|
|
5
3
|
exclude: string | string[];
|
|
6
4
|
include: string | string[];
|
|
7
5
|
cacheControl: string;
|
|
8
6
|
contentType?: string;
|
|
9
7
|
}
|
|
10
|
-
/**
|
|
11
|
-
* The customDomain for this website. SST supports domains that are hosted either on [Route 53](https://aws.amazon.com/route53/) or externally.
|
|
12
|
-
*
|
|
13
|
-
* Note that you can also migrate externally hosted domains to Route 53 by [following this guide](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/MigratingDNS.html).
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```js
|
|
17
|
-
* new StaticSite(this, "Site", {
|
|
18
|
-
* path: "path/to/src",
|
|
19
|
-
* customDomain: "domain.com",
|
|
20
|
-
* });
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```js
|
|
25
|
-
* new StaticSite(this, "Site", {
|
|
26
|
-
* path: "path/to/src",
|
|
27
|
-
* customDomain: {
|
|
28
|
-
* domainName: "domain.com",
|
|
29
|
-
* domainAlias: "www.domain.com",
|
|
30
|
-
* hostedZone: "domain.com",
|
|
31
|
-
* }
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export interface BaseSiteDomainProps {
|
|
36
|
-
/**
|
|
37
|
-
* The domain to be assigned to the website URL (ie. domain.com).
|
|
38
|
-
*
|
|
39
|
-
* Supports domains that are hosted either on [Route 53](https://aws.amazon.com/route53/) or externally.
|
|
40
|
-
*/
|
|
41
|
-
domainName: string;
|
|
42
|
-
/**
|
|
43
|
-
* An alternative domain to be assigned to the website URL. Visitors to the alias will be redirected to the main domain. (ie. `www.domain.com`).
|
|
44
|
-
*
|
|
45
|
-
* Use this to create a `www.` version of your domain and redirect visitors to the root domain.
|
|
46
|
-
* @default no alias configured
|
|
47
|
-
*/
|
|
48
|
-
domainAlias?: string;
|
|
49
|
-
/**
|
|
50
|
-
* The hosted zone in Route 53 that contains the domain. By default, SST will look for a hosted zone matching the domainName that's passed in.
|
|
51
|
-
*
|
|
52
|
-
* Set this option if SST cannot find the hosted zone in Route 53.
|
|
53
|
-
* @default same as the `domainName`
|
|
54
|
-
*/
|
|
55
|
-
hostedZone?: string;
|
|
56
|
-
/**
|
|
57
|
-
* Specify additional names that should route to the Cloudfront Distribution. Note, certificates for these names will not be automatically generated so the `certificate` option must be specified.
|
|
58
|
-
* @default `[]`
|
|
59
|
-
*/
|
|
60
|
-
alternateNames?: string[];
|
|
61
|
-
/**
|
|
62
|
-
* Set this option if the domain is not hosted on Amazon Route 53.
|
|
63
|
-
* @default `false`
|
|
64
|
-
*/
|
|
65
|
-
isExternalDomain?: boolean;
|
|
66
|
-
cdk?: {
|
|
67
|
-
/**
|
|
68
|
-
* Import the underlying Route 53 hosted zone.
|
|
69
|
-
*/
|
|
70
|
-
hostedZone?: IHostedZone;
|
|
71
|
-
/**
|
|
72
|
-
* Import the certificate for the domain. By default, SST will create a certificate with the domain name. The certificate will be created in the `us-east-1`(N. Virginia) region as required by AWS CloudFront.
|
|
73
|
-
*
|
|
74
|
-
* Set this option if you have an existing certificate in the `us-east-1` region in AWS Certificate Manager you want to use.
|
|
75
|
-
*/
|
|
76
|
-
certificate?: ICertificate;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
8
|
export interface BaseSiteEnvironmentOutputsInfo {
|
|
80
9
|
path: string;
|
|
81
10
|
stack: string;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Construct, IConstruct } from "constructs";
|
|
2
|
+
import { CustomResource } from "aws-cdk-lib/core";
|
|
3
|
+
import { IHostedZone } from "aws-cdk-lib/aws-route53";
|
|
4
|
+
import { DistributionProps as CdkDistributionProps, IDistribution } from "aws-cdk-lib/aws-cloudfront";
|
|
5
|
+
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
|
|
6
|
+
/**
|
|
7
|
+
* The customDomain for this website. SST supports domains that are hosted either on [Route 53](https://aws.amazon.com/route53/) or externally.
|
|
8
|
+
*
|
|
9
|
+
* Note that you can also migrate externally hosted domains to Route 53 by [following this guide](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/MigratingDNS.html).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```js
|
|
13
|
+
* new StaticSite(this, "Site", {
|
|
14
|
+
* path: "path/to/src",
|
|
15
|
+
* customDomain: "domain.com",
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```js
|
|
21
|
+
* new StaticSite(this, "Site", {
|
|
22
|
+
* path: "path/to/src",
|
|
23
|
+
* customDomain: {
|
|
24
|
+
* domainName: "domain.com",
|
|
25
|
+
* domainAlias: "www.domain.com",
|
|
26
|
+
* hostedZone: "domain.com",
|
|
27
|
+
* }
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export interface DistributionDomainProps {
|
|
32
|
+
/**
|
|
33
|
+
* The domain to be assigned to the website URL (ie. domain.com).
|
|
34
|
+
*
|
|
35
|
+
* Supports domains that are hosted either on [Route 53](https://aws.amazon.com/route53/) or externally.
|
|
36
|
+
*/
|
|
37
|
+
domainName: string;
|
|
38
|
+
/**
|
|
39
|
+
* An alternative domain to be assigned to the website URL. Visitors to the alias will be redirected to the main domain. (ie. `www.domain.com`).
|
|
40
|
+
*
|
|
41
|
+
* Use this to create a `www.` version of your domain and redirect visitors to the root domain.
|
|
42
|
+
* @default no alias configured
|
|
43
|
+
*/
|
|
44
|
+
domainAlias?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The hosted zone in Route 53 that contains the domain. By default, SST will look for a hosted zone matching the domainName that's passed in.
|
|
47
|
+
*
|
|
48
|
+
* Set this option if SST cannot find the hosted zone in Route 53.
|
|
49
|
+
* @default same as the `domainName`
|
|
50
|
+
*/
|
|
51
|
+
hostedZone?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Specify additional names that should route to the Cloudfront Distribution. Note, certificates for these names will not be automatically generated so the `certificate` option must be specified.
|
|
54
|
+
* @default `[]`
|
|
55
|
+
*/
|
|
56
|
+
alternateNames?: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Set this option if the domain is not hosted on Amazon Route 53.
|
|
59
|
+
* @default `false`
|
|
60
|
+
*/
|
|
61
|
+
isExternalDomain?: boolean;
|
|
62
|
+
cdk?: {
|
|
63
|
+
/**
|
|
64
|
+
* Import the underlying Route 53 hosted zone.
|
|
65
|
+
*/
|
|
66
|
+
hostedZone?: IHostedZone;
|
|
67
|
+
/**
|
|
68
|
+
* Import the certificate for the domain. By default, SST will create a certificate with the domain name. The certificate will be created in the `us-east-1`(N. Virginia) region as required by AWS CloudFront.
|
|
69
|
+
*
|
|
70
|
+
* Set this option if you have an existing certificate in the `us-east-1` region in AWS Certificate Manager you want to use.
|
|
71
|
+
*/
|
|
72
|
+
certificate?: ICertificate;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export interface DistributionProps {
|
|
76
|
+
/**
|
|
77
|
+
* The customDomain for this website. SST supports domains that are hosted
|
|
78
|
+
* either on [Route 53](https://aws.amazon.com/route53/) or externally.
|
|
79
|
+
*
|
|
80
|
+
* Note that you can also migrate externally hosted domains to Route 53 by
|
|
81
|
+
* [following this guide](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/MigratingDNS.html).
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```js
|
|
85
|
+
* customDomain: "domain.com",
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* ```js
|
|
89
|
+
* customDomain: {
|
|
90
|
+
* domainName: "domain.com",
|
|
91
|
+
* domainAlias: "www.domain.com",
|
|
92
|
+
* hostedZone: "domain.com"
|
|
93
|
+
* },
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
customDomain?: string | DistributionDomainProps;
|
|
97
|
+
/**
|
|
98
|
+
* The SSR function is deployed to Lambda in a single region. Alternatively, you can enable this option to deploy to Lambda@Edge.
|
|
99
|
+
* @default false
|
|
100
|
+
*/
|
|
101
|
+
/**
|
|
102
|
+
* While deploying, SST waits for the CloudFront cache invalidation process to finish. This ensures that the new content will be served once the deploy command finishes. However, this process can sometimes take more than 5 mins. For non-prod environments it might make sense to pass in `false`. That'll skip waiting for the cache to invalidate and speed up the deploy process.
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
waitForInvalidation?: boolean;
|
|
106
|
+
scopeOverride?: IConstruct;
|
|
107
|
+
cdk: {
|
|
108
|
+
distribution: CdkDistributionProps | IDistribution;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export declare class Distribution extends Construct {
|
|
112
|
+
private scope;
|
|
113
|
+
private props;
|
|
114
|
+
private distribution;
|
|
115
|
+
private hostedZone?;
|
|
116
|
+
private certificate?;
|
|
117
|
+
constructor(scope: Construct, id: string, props: DistributionProps);
|
|
118
|
+
/**
|
|
119
|
+
* The CloudFront URL of the website.
|
|
120
|
+
*/
|
|
121
|
+
get url(): string;
|
|
122
|
+
/**
|
|
123
|
+
* If the custom domain is enabled, this is the URL of the website with the
|
|
124
|
+
* custom domain.
|
|
125
|
+
*/
|
|
126
|
+
get customDomainUrl(): string | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* The internally created CDK resources.
|
|
129
|
+
*/
|
|
130
|
+
get cdk(): {
|
|
131
|
+
distribution: IDistribution;
|
|
132
|
+
hostedZone: IHostedZone | undefined;
|
|
133
|
+
certificate: ICertificate | undefined;
|
|
134
|
+
};
|
|
135
|
+
createInvalidation(buildId?: string): CustomResource;
|
|
136
|
+
private validateCloudFrontDistributionSettings;
|
|
137
|
+
private validateCustomDomainSettings;
|
|
138
|
+
private lookupHostedZone;
|
|
139
|
+
private createCertificate;
|
|
140
|
+
private createDistribution;
|
|
141
|
+
private buildDistributionDomainNames;
|
|
142
|
+
private createRoute53Records;
|
|
143
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import { CustomResource } from "aws-cdk-lib/core";
|
|
3
|
+
import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
4
|
+
import { HostedZone, ARecord, AaaaRecord, RecordTarget, } from "aws-cdk-lib/aws-route53";
|
|
5
|
+
import { Distribution as CdkDistribution, } from "aws-cdk-lib/aws-cloudfront";
|
|
6
|
+
import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
|
|
7
|
+
import { Stack } from "./Stack.js";
|
|
8
|
+
import { isCDKConstruct } from "./Construct.js";
|
|
9
|
+
import { HttpsRedirect } from "./cdk/website-redirect.js";
|
|
10
|
+
import { DnsValidatedCertificate } from "./cdk/dns-validated-certificate.js";
|
|
11
|
+
export class Distribution extends Construct {
|
|
12
|
+
scope;
|
|
13
|
+
props;
|
|
14
|
+
distribution;
|
|
15
|
+
hostedZone;
|
|
16
|
+
certificate;
|
|
17
|
+
constructor(scope, id, props) {
|
|
18
|
+
super(scope, id);
|
|
19
|
+
// Override scope
|
|
20
|
+
// note: this is intended to be used internally by SST to make constructs
|
|
21
|
+
// backwards compatible when the hirechical structure of the constructs
|
|
22
|
+
// changes. When the hirerchical structure changes, the child AWS
|
|
23
|
+
// resources' logical ID will change. And CloudFormation will recreate
|
|
24
|
+
// them.
|
|
25
|
+
this.scope = props.scopeOverride || this;
|
|
26
|
+
this.props = props;
|
|
27
|
+
const isImportedCloudFrontDistribution = (distribution) => {
|
|
28
|
+
return distribution !== undefined && isCDKConstruct(distribution);
|
|
29
|
+
};
|
|
30
|
+
// cdk.distribution is an imported construct
|
|
31
|
+
if (isImportedCloudFrontDistribution(props.cdk?.distribution)) {
|
|
32
|
+
this.distribution = props.cdk?.distribution;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.validateCustomDomainSettings();
|
|
36
|
+
this.validateCloudFrontDistributionSettings();
|
|
37
|
+
this.hostedZone = this.lookupHostedZone();
|
|
38
|
+
this.certificate = this.createCertificate();
|
|
39
|
+
this.distribution = this.createDistribution();
|
|
40
|
+
this.createRoute53Records();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The CloudFront URL of the website.
|
|
44
|
+
*/
|
|
45
|
+
get url() {
|
|
46
|
+
return `https://${this.distribution.distributionDomainName}`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* If the custom domain is enabled, this is the URL of the website with the
|
|
50
|
+
* custom domain.
|
|
51
|
+
*/
|
|
52
|
+
get customDomainUrl() {
|
|
53
|
+
const { customDomain } = this.props;
|
|
54
|
+
if (!customDomain)
|
|
55
|
+
return;
|
|
56
|
+
if (typeof customDomain === "string") {
|
|
57
|
+
return `https://${customDomain}`;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return `https://${customDomain.domainName}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The internally created CDK resources.
|
|
65
|
+
*/
|
|
66
|
+
get cdk() {
|
|
67
|
+
return {
|
|
68
|
+
distribution: this.distribution,
|
|
69
|
+
hostedZone: this.hostedZone,
|
|
70
|
+
certificate: this.certificate,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
createInvalidation(buildId) {
|
|
74
|
+
const stack = Stack.of(this);
|
|
75
|
+
const policy = new Policy(this.scope, "CloudFrontInvalidatorPolicy", {
|
|
76
|
+
statements: [
|
|
77
|
+
new PolicyStatement({
|
|
78
|
+
effect: Effect.ALLOW,
|
|
79
|
+
actions: [
|
|
80
|
+
"cloudfront:GetInvalidation",
|
|
81
|
+
"cloudfront:CreateInvalidation",
|
|
82
|
+
],
|
|
83
|
+
resources: [
|
|
84
|
+
`arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.distribution.distributionId}`,
|
|
85
|
+
],
|
|
86
|
+
}),
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
stack.customResourceHandler.role?.attachInlinePolicy(policy);
|
|
90
|
+
const resource = new CustomResource(this.scope, "CloudFrontInvalidator", {
|
|
91
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
92
|
+
resourceType: "Custom::CloudFrontInvalidator",
|
|
93
|
+
properties: {
|
|
94
|
+
buildId: buildId || Date.now().toString(),
|
|
95
|
+
distributionId: this.distribution.distributionId,
|
|
96
|
+
paths: ["/*"],
|
|
97
|
+
waitForInvalidation: this.props.waitForInvalidation,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
resource.node.addDependency(policy);
|
|
101
|
+
return resource;
|
|
102
|
+
}
|
|
103
|
+
validateCloudFrontDistributionSettings() {
|
|
104
|
+
const { cdk } = this.props;
|
|
105
|
+
if (!cdk?.distribution)
|
|
106
|
+
return;
|
|
107
|
+
if (cdk.distribution.certificate) {
|
|
108
|
+
throw new Error(`Do not configure the "cfDistribution.certificate". Use the "customDomain" to configure the domain certificate.`);
|
|
109
|
+
}
|
|
110
|
+
if (cdk.distribution.domainNames) {
|
|
111
|
+
throw new Error(`Do not configure the "cfDistribution.domainNames". Use the "customDomain" to configure the domain name.`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
validateCustomDomainSettings() {
|
|
115
|
+
const { customDomain } = this.props;
|
|
116
|
+
if (!customDomain) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (typeof customDomain === "string") {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (customDomain.isExternalDomain === true) {
|
|
123
|
+
if (!customDomain.cdk?.certificate) {
|
|
124
|
+
throw new Error(`A valid certificate is required when "isExternalDomain" is set to "true".`);
|
|
125
|
+
}
|
|
126
|
+
if (customDomain.domainAlias) {
|
|
127
|
+
throw new Error(`Domain alias is only supported for domains hosted on Amazon Route 53. Do not set the "customDomain.domainAlias" when "isExternalDomain" is enabled.`);
|
|
128
|
+
}
|
|
129
|
+
if (customDomain.hostedZone) {
|
|
130
|
+
throw new Error(`Hosted zones can only be configured for domains hosted on Amazon Route 53. Do not set the "customDomain.hostedZone" when "isExternalDomain" is enabled.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
lookupHostedZone() {
|
|
135
|
+
const { customDomain } = this.props;
|
|
136
|
+
// Skip if customDomain is not configured
|
|
137
|
+
if (!customDomain) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
let hostedZone;
|
|
141
|
+
if (typeof customDomain === "string") {
|
|
142
|
+
hostedZone = HostedZone.fromLookup(this.scope, "HostedZone", {
|
|
143
|
+
domainName: customDomain,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
else if (customDomain.cdk?.hostedZone) {
|
|
147
|
+
hostedZone = customDomain.cdk.hostedZone;
|
|
148
|
+
}
|
|
149
|
+
else if (typeof customDomain.hostedZone === "string") {
|
|
150
|
+
hostedZone = HostedZone.fromLookup(this.scope, "HostedZone", {
|
|
151
|
+
domainName: customDomain.hostedZone,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else if (typeof customDomain.domainName === "string") {
|
|
155
|
+
// Skip if domain is not a Route53 domain
|
|
156
|
+
if (customDomain.isExternalDomain === true) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
hostedZone = HostedZone.fromLookup(this.scope, "HostedZone", {
|
|
160
|
+
domainName: customDomain.domainName,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
hostedZone = customDomain.hostedZone;
|
|
165
|
+
}
|
|
166
|
+
return hostedZone;
|
|
167
|
+
}
|
|
168
|
+
createCertificate() {
|
|
169
|
+
const { customDomain } = this.props;
|
|
170
|
+
if (!customDomain) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
let acmCertificate;
|
|
174
|
+
// HostedZone is set for Route 53 domains
|
|
175
|
+
if (this.hostedZone) {
|
|
176
|
+
if (typeof customDomain === "string") {
|
|
177
|
+
acmCertificate = new DnsValidatedCertificate(this.scope, "Certificate", {
|
|
178
|
+
domainName: customDomain,
|
|
179
|
+
hostedZone: this.hostedZone,
|
|
180
|
+
region: "us-east-1",
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
else if (customDomain.cdk?.certificate) {
|
|
184
|
+
acmCertificate = customDomain.cdk.certificate;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
acmCertificate = new DnsValidatedCertificate(this.scope, "Certificate", {
|
|
188
|
+
domainName: customDomain.domainName,
|
|
189
|
+
hostedZone: this.hostedZone,
|
|
190
|
+
region: "us-east-1",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// HostedZone is NOT set for non-Route 53 domains
|
|
195
|
+
else {
|
|
196
|
+
if (typeof customDomain !== "string") {
|
|
197
|
+
acmCertificate = customDomain.cdk?.certificate;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return acmCertificate;
|
|
201
|
+
}
|
|
202
|
+
createDistribution() {
|
|
203
|
+
const { cdk } = this.props;
|
|
204
|
+
return new CdkDistribution(this.scope, "Distribution", {
|
|
205
|
+
...cdk?.distribution,
|
|
206
|
+
domainNames: this.buildDistributionDomainNames(),
|
|
207
|
+
certificate: this.certificate,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
buildDistributionDomainNames() {
|
|
211
|
+
const { customDomain } = this.props;
|
|
212
|
+
const domainNames = [];
|
|
213
|
+
if (!customDomain) {
|
|
214
|
+
// no domain
|
|
215
|
+
}
|
|
216
|
+
else if (typeof customDomain === "string") {
|
|
217
|
+
domainNames.push(customDomain);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
domainNames.push(customDomain.domainName);
|
|
221
|
+
if (customDomain.alternateNames) {
|
|
222
|
+
if (!customDomain.cdk?.certificate)
|
|
223
|
+
throw new Error("Certificates for alternate domains cannot be automatically created. Please specify certificate to use");
|
|
224
|
+
domainNames.push(...customDomain.alternateNames);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return domainNames;
|
|
228
|
+
}
|
|
229
|
+
createRoute53Records() {
|
|
230
|
+
const { customDomain } = this.props;
|
|
231
|
+
if (!customDomain || !this.hostedZone) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
let recordName;
|
|
235
|
+
let domainAlias;
|
|
236
|
+
if (typeof customDomain === "string") {
|
|
237
|
+
recordName = customDomain;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
recordName = customDomain.domainName;
|
|
241
|
+
domainAlias = customDomain.domainAlias;
|
|
242
|
+
}
|
|
243
|
+
// Create DNS record
|
|
244
|
+
const recordProps = {
|
|
245
|
+
recordName,
|
|
246
|
+
zone: this.hostedZone,
|
|
247
|
+
target: RecordTarget.fromAlias(new CloudFrontTarget(this.distribution)),
|
|
248
|
+
};
|
|
249
|
+
new ARecord(this.scope, "AliasRecord", recordProps);
|
|
250
|
+
new AaaaRecord(this.scope, "AliasRecordAAAA", recordProps);
|
|
251
|
+
// Create Alias redirect record
|
|
252
|
+
if (domainAlias) {
|
|
253
|
+
new HttpsRedirect(this.scope, "Redirect", {
|
|
254
|
+
zone: this.hostedZone,
|
|
255
|
+
recordNames: [domainAlias],
|
|
256
|
+
targetDomain: recordName,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
package/constructs/Metadata.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ import type { NextjsSite as SlsNextjsSite } from "./deprecated/NextjsSite.js";
|
|
|
27
27
|
export type SlsNextjsMetadata = ExtractMetadata<SlsNextjsSite>;
|
|
28
28
|
import type { Queue } from "./Queue.js";
|
|
29
29
|
export type QueueMetadata = ExtractMetadata<Queue>;
|
|
30
|
+
import type { Service } from "./Service.js";
|
|
31
|
+
export type ServiceMetadata = ExtractMetadata<Service>;
|
|
30
32
|
import type { StaticSite } from "./StaticSite.js";
|
|
31
33
|
export type StaticSiteMetadata = ExtractMetadata<StaticSite>;
|
|
32
34
|
import type { Table } from "./Table.js";
|
|
@@ -54,5 +56,5 @@ export type SvelteKitSiteMetadata = ExtractMetadata<SvelteKitSite>;
|
|
|
54
56
|
import type { SolidStartSite } from "./SolidStartSite.js";
|
|
55
57
|
export type SolidStartSiteMetadata = ExtractMetadata<SolidStartSite>;
|
|
56
58
|
export type SSRSiteMetadata = NextjsSiteMetadata | AstroSiteMetadata | RemixSiteMetadata | SolidStartSiteMetadata | SvelteKitSiteMetadata;
|
|
57
|
-
export type Metadata = ApiMetadata | ApiGatewayV1ApiMetadata | CognitoMetadata | AppSyncApiMetadata | BucketMetadata | CronMetadata | EventBusMetadata | FunctionMetadata | KinesisStreamMetadata | SlsNextjsMetadata | QueueMetadata | StaticSiteMetadata | TableMetadata | TopicMetadata | WebSocketApiMetadata | RDSMetadata | AuthMetadata | ScriptMetadata | JobMetadata | SSRSiteMetadata;
|
|
59
|
+
export type Metadata = ApiMetadata | ApiGatewayV1ApiMetadata | CognitoMetadata | AppSyncApiMetadata | BucketMetadata | CronMetadata | EventBusMetadata | FunctionMetadata | KinesisStreamMetadata | SlsNextjsMetadata | QueueMetadata | StaticSiteMetadata | TableMetadata | TopicMetadata | WebSocketApiMetadata | RDSMetadata | AuthMetadata | ScriptMetadata | JobMetadata | SSRSiteMetadata | ServiceMetadata;
|
|
58
60
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
2
|
import { FunctionProps } from "aws-cdk-lib/aws-lambda";
|
|
3
|
-
import {
|
|
3
|
+
import { CachePolicy } from "aws-cdk-lib/aws-cloudfront";
|
|
4
|
+
import { Distribution } from "./Distribution.js";
|
|
4
5
|
import { SsrFunction } from "./SsrFunction.js";
|
|
5
6
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
6
7
|
import { SsrSite, SsrSiteProps } from "./SsrSite.js";
|
|
@@ -60,9 +61,9 @@ export declare class NextjsSite extends SsrSite {
|
|
|
60
61
|
protected createFunctionForEdge(): EdgeFunction;
|
|
61
62
|
private createImageOptimizationFunction;
|
|
62
63
|
private createWarmer;
|
|
63
|
-
protected buildServerCachePolicy(): CachePolicy;
|
|
64
64
|
protected createCloudFrontDistributionForRegional(): Distribution;
|
|
65
65
|
protected createCloudFrontDistributionForEdge(): Distribution;
|
|
66
|
+
protected buildServerCachePolicy(): CachePolicy;
|
|
66
67
|
private buildImageBehavior;
|
|
67
68
|
protected generateBuildId(): string;
|
|
68
69
|
getConstructMetadata(): {
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -4,13 +4,14 @@ import { Fn, Duration as CdkDuration, RemovalPolicy, CustomResource, } from "aws
|
|
|
4
4
|
import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
5
5
|
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
6
6
|
import { Code, Runtime, Architecture, Function as CdkFunction, FunctionUrlAuthType, } from "aws-cdk-lib/aws-lambda";
|
|
7
|
-
import {
|
|
7
|
+
import { ViewerProtocolPolicy, AllowedMethods, CachedMethods, } from "aws-cdk-lib/aws-cloudfront";
|
|
8
8
|
import { HttpOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
|
|
9
9
|
import { Rule, Schedule } from "aws-cdk-lib/aws-events";
|
|
10
10
|
import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
|
|
11
11
|
import { Queue } from "aws-cdk-lib/aws-sqs";
|
|
12
12
|
import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
13
13
|
import { Stack } from "./Stack.js";
|
|
14
|
+
import { Distribution } from "./Distribution.js";
|
|
14
15
|
import { SsrFunction } from "./SsrFunction.js";
|
|
15
16
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
16
17
|
import { SsrSite } from "./SsrSite.js";
|
|
@@ -128,13 +129,13 @@ export class NextjsSite extends SsrSite {
|
|
|
128
129
|
timeout: CdkDuration.seconds(25),
|
|
129
130
|
architecture: Architecture.ARM_64,
|
|
130
131
|
environment: {
|
|
131
|
-
BUCKET_NAME: this.
|
|
132
|
+
BUCKET_NAME: this.bucket.bucketName,
|
|
132
133
|
BUCKET_KEY_PREFIX: "_assets",
|
|
133
134
|
},
|
|
134
135
|
initialPolicy: [
|
|
135
136
|
new PolicyStatement({
|
|
136
137
|
actions: ["s3:GetObject"],
|
|
137
|
-
resources: [this.
|
|
138
|
+
resources: [this.bucket.arnForObjects("*")],
|
|
138
139
|
}),
|
|
139
140
|
],
|
|
140
141
|
});
|
|
@@ -202,15 +203,6 @@ export class NextjsSite extends SsrSite {
|
|
|
202
203
|
});
|
|
203
204
|
resource.node.addDependency(policy);
|
|
204
205
|
}
|
|
205
|
-
buildServerCachePolicy() {
|
|
206
|
-
return super.buildServerCachePolicy([
|
|
207
|
-
"accept",
|
|
208
|
-
"rsc",
|
|
209
|
-
"next-router-prefetch",
|
|
210
|
-
"next-router-state-tree",
|
|
211
|
-
"next-url",
|
|
212
|
-
]);
|
|
213
|
-
}
|
|
214
206
|
createCloudFrontDistributionForRegional() {
|
|
215
207
|
/**
|
|
216
208
|
* Next.js requests
|
|
@@ -261,49 +253,66 @@ export class NextjsSite extends SsrSite {
|
|
|
261
253
|
* - Cache-Control: public, max-age=0, must-revalidate
|
|
262
254
|
* - x-vercel-cache: MISS
|
|
263
255
|
*/
|
|
264
|
-
const { cdk } = this.props;
|
|
256
|
+
const { customDomain, cdk } = this.props;
|
|
265
257
|
const cfDistributionProps = cdk?.distribution || {};
|
|
266
258
|
const cachePolicy = cdk?.serverCachePolicy ?? this.buildServerCachePolicy();
|
|
267
259
|
const serverBehavior = this.buildDefaultBehaviorForRegional(cachePolicy);
|
|
268
|
-
return new Distribution(this, "
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
260
|
+
return new Distribution(this, "CDN", {
|
|
261
|
+
scopeOverride: this,
|
|
262
|
+
customDomain,
|
|
263
|
+
cdk: {
|
|
264
|
+
distribution: {
|
|
265
|
+
// these values can be overwritten by cfDistributionProps
|
|
266
|
+
defaultRootObject: "",
|
|
267
|
+
// Override props.
|
|
268
|
+
...cfDistributionProps,
|
|
269
|
+
// these values can NOT be overwritten by cfDistributionProps
|
|
270
|
+
defaultBehavior: serverBehavior,
|
|
271
|
+
additionalBehaviors: {
|
|
272
|
+
"api/*": serverBehavior,
|
|
273
|
+
"_next/data/*": serverBehavior,
|
|
274
|
+
"_next/image*": this.buildImageBehavior(cachePolicy),
|
|
275
|
+
...(cfDistributionProps.additionalBehaviors || {}),
|
|
276
|
+
},
|
|
277
|
+
},
|
|
282
278
|
},
|
|
283
279
|
});
|
|
284
280
|
}
|
|
285
281
|
createCloudFrontDistributionForEdge() {
|
|
286
|
-
const { cdk } = this.props;
|
|
282
|
+
const { customDomain, cdk } = this.props;
|
|
287
283
|
const cfDistributionProps = cdk?.distribution || {};
|
|
288
284
|
const cachePolicy = cdk?.serverCachePolicy ?? this.buildServerCachePolicy();
|
|
289
285
|
const serverBehavior = this.buildDefaultBehaviorForEdge(cachePolicy);
|
|
290
|
-
return new Distribution(this, "
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
286
|
+
return new Distribution(this, "CDN", {
|
|
287
|
+
scopeOverride: this,
|
|
288
|
+
customDomain,
|
|
289
|
+
cdk: {
|
|
290
|
+
distribution: {
|
|
291
|
+
// these values can be overwritten by cfDistributionProps
|
|
292
|
+
defaultRootObject: "",
|
|
293
|
+
// Override props.
|
|
294
|
+
...cfDistributionProps,
|
|
295
|
+
// these values can NOT be overwritten by cfDistributionProps
|
|
296
|
+
defaultBehavior: serverBehavior,
|
|
297
|
+
additionalBehaviors: {
|
|
298
|
+
"api/*": serverBehavior,
|
|
299
|
+
"_next/data/*": serverBehavior,
|
|
300
|
+
"_next/image*": this.buildImageBehavior(cachePolicy),
|
|
301
|
+
...(cfDistributionProps.additionalBehaviors || {}),
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
304
|
},
|
|
305
305
|
});
|
|
306
306
|
}
|
|
307
|
+
buildServerCachePolicy() {
|
|
308
|
+
return super.buildServerCachePolicy([
|
|
309
|
+
"accept",
|
|
310
|
+
"rsc",
|
|
311
|
+
"next-router-prefetch",
|
|
312
|
+
"next-router-state-tree",
|
|
313
|
+
"next-url",
|
|
314
|
+
]);
|
|
315
|
+
}
|
|
307
316
|
buildImageBehavior(cachePolicy) {
|
|
308
317
|
const { cdk } = this.props;
|
|
309
318
|
const imageFn = this.createImageOptimizationFunction();
|