sst 2.0.0-rc.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/bootstrap.d.ts +2 -4
  2. package/bootstrap.js +208 -61
  3. package/bus.d.ts +3 -3
  4. package/bus.js +1 -1
  5. package/cache.js +1 -1
  6. package/cdk/cloudformation-deployments-wrapper.d.ts +3 -0
  7. package/cdk/cloudformation-deployments-wrapper.js +117 -0
  8. package/cdk/cloudformation-deployments.d.ts +19 -4
  9. package/cdk/deploy-stack.d.ts +17 -2
  10. package/cdk/deploy-stack.js +6 -1
  11. package/cli/colors.d.ts +28 -0
  12. package/cli/colors.js +27 -0
  13. package/cli/commands/bind.d.ts +4 -0
  14. package/cli/commands/bind.js +10 -7
  15. package/cli/commands/bootstrap.d.ts +13 -0
  16. package/cli/commands/bootstrap.js +11 -0
  17. package/cli/commands/build.d.ts +6 -2
  18. package/cli/commands/build.js +13 -8
  19. package/cli/commands/console.d.ts +5 -1
  20. package/cli/commands/console.js +8 -6
  21. package/cli/commands/deploy.d.ts +4 -2
  22. package/cli/commands/deploy.js +69 -29
  23. package/cli/commands/dev.d.ts +5 -1
  24. package/cli/commands/dev.js +157 -79
  25. package/cli/commands/diff.d.ts +15 -0
  26. package/cli/commands/diff.js +61 -0
  27. package/cli/commands/env.d.ts +5 -1
  28. package/cli/commands/env.js +14 -15
  29. package/cli/commands/plugins/kysely.js +13 -5
  30. package/cli/commands/plugins/pothos.js +9 -4
  31. package/cli/commands/remove.d.ts +4 -0
  32. package/cli/commands/remove.js +26 -18
  33. package/cli/commands/secrets/get.d.ts +7 -3
  34. package/cli/commands/secrets/get.js +11 -24
  35. package/cli/commands/secrets/list.d.ts +6 -2
  36. package/cli/commands/secrets/list.js +15 -7
  37. package/cli/commands/secrets/remove.d.ts +8 -4
  38. package/cli/commands/secrets/remove.js +18 -16
  39. package/cli/commands/secrets/secrets.js +3 -3
  40. package/cli/commands/secrets/set.d.ts +8 -6
  41. package/cli/commands/secrets/set.js +16 -33
  42. package/cli/commands/telemetry.d.ts +15 -0
  43. package/cli/commands/telemetry.js +17 -0
  44. package/cli/commands/transform.d.ts +15 -0
  45. package/cli/commands/transform.js +55 -0
  46. package/cli/commands/update.d.ts +6 -2
  47. package/cli/commands/update.js +41 -33
  48. package/cli/commands/version.d.ts +13 -0
  49. package/cli/commands/version.js +7 -0
  50. package/cli/local/router.d.ts +6 -6
  51. package/cli/local/router.js +3 -3
  52. package/cli/local/server.d.ts +5 -3
  53. package/cli/local/server.js +21 -14
  54. package/cli/program.d.ts +5 -1
  55. package/cli/program.js +29 -5
  56. package/cli/spinner.js +2 -0
  57. package/cli/sst.js +35 -23
  58. package/cli/telemetry/environment.d.ts +1 -1
  59. package/cli/telemetry/environment.js +1 -1
  60. package/cli/terminal.d.ts +1 -0
  61. package/cli/terminal.js +8 -0
  62. package/cli/ui/deploy.d.ts +3 -2
  63. package/cli/ui/deploy.js +106 -106
  64. package/cli/ui/functions.d.ts +2 -0
  65. package/cli/ui/functions.js +132 -0
  66. package/cli/ui/header.d.ts +5 -0
  67. package/cli/ui/header.js +16 -0
  68. package/cli/ui/stack.d.ts +1 -0
  69. package/cli/ui/stack.js +6 -0
  70. package/config.d.ts +1 -1
  71. package/config.js +8 -8
  72. package/constructs/Api.d.ts +3 -71
  73. package/constructs/Api.js +3 -42
  74. package/constructs/ApiGatewayV1Api.d.ts +3 -3
  75. package/constructs/ApiGatewayV1Api.js +4 -3
  76. package/constructs/App.d.ts +2 -22
  77. package/constructs/App.js +12 -25
  78. package/constructs/AppSyncApi.d.ts +4 -5
  79. package/constructs/AppSyncApi.js +8 -5
  80. package/constructs/AstroSite.d.ts +2 -3
  81. package/constructs/AstroSite.js +43 -53
  82. package/constructs/Auth.js +27 -16
  83. package/constructs/BaseSite.d.ts +10 -10
  84. package/constructs/BaseSite.js +2 -2
  85. package/constructs/Cognito.js +28 -28
  86. package/constructs/EdgeFunction.d.ts +6 -4
  87. package/constructs/EdgeFunction.js +56 -59
  88. package/constructs/EventBus.js +1 -1
  89. package/constructs/Function.d.ts +4 -44
  90. package/constructs/Function.js +14 -50
  91. package/constructs/FunctionalStack.d.ts +2 -2
  92. package/constructs/Job.d.ts +23 -63
  93. package/constructs/Job.js +11 -32
  94. package/constructs/Metadata.d.ts +18 -20
  95. package/constructs/NextjsSite.d.ts +21 -5
  96. package/constructs/NextjsSite.js +67 -101
  97. package/constructs/Queue.js +10 -10
  98. package/constructs/RDS.d.ts +1 -1
  99. package/constructs/RDS.js +1 -1
  100. package/constructs/RemixSite.d.ts +0 -2
  101. package/constructs/RemixSite.js +20 -20
  102. package/constructs/Script.js +1 -1
  103. package/constructs/Secret.js +5 -3
  104. package/constructs/SolidStartSite.d.ts +2 -3
  105. package/constructs/SolidStartSite.js +42 -52
  106. package/constructs/SsrFunction.d.ts +22 -0
  107. package/constructs/SsrFunction.js +113 -0
  108. package/constructs/SsrSite.d.ts +104 -104
  109. package/constructs/SsrSite.js +196 -217
  110. package/constructs/Stack.d.ts +1 -20
  111. package/constructs/Stack.js +3 -65
  112. package/constructs/StaticSite.d.ts +33 -53
  113. package/constructs/StaticSite.js +92 -118
  114. package/constructs/Table.d.ts +1 -1
  115. package/constructs/Table.js +4 -4
  116. package/constructs/Topic.js +1 -1
  117. package/constructs/cdk/certificate-base.d.ts +18 -0
  118. package/constructs/cdk/certificate-base.js +26 -0
  119. package/constructs/cdk/dns-validated-certificate.d.ts +77 -0
  120. package/constructs/cdk/dns-validated-certificate.js +125 -0
  121. package/constructs/cdk/website-redirect.d.ts +53 -0
  122. package/constructs/cdk/website-redirect.js +77 -0
  123. package/constructs/deferred_task.d.ts +1 -1
  124. package/constructs/deprecated/NextjsSite.js +8 -6
  125. package/constructs/index.d.ts +0 -6
  126. package/constructs/index.js +0 -6
  127. package/constructs/util/apiGatewayV1AccessLog.d.ts +1 -1
  128. package/constructs/util/apiGatewayV2AccessLog.js +4 -4
  129. package/constructs/util/apiGatewayV2Domain.js +9 -2
  130. package/constructs/util/appSyncApiDomain.d.ts +1 -1
  131. package/constructs/util/appSyncApiDomain.js +9 -15
  132. package/constructs/util/duration.d.ts +1 -1
  133. package/constructs/util/functionBinding.js +1 -1
  134. package/constructs/util/permission.d.ts +3 -3
  135. package/constructs/util/permission.js +16 -18
  136. package/constructs/util/size.d.ts +1 -1
  137. package/constructs/util/warning.js +2 -2
  138. package/context/context.d.ts +2 -2
  139. package/context/context.js +4 -4
  140. package/context/handler.d.ts +1 -1
  141. package/credentials.d.ts +1 -1
  142. package/credentials.js +42 -6
  143. package/index.d.ts +1 -0
  144. package/index.js +1 -0
  145. package/iot.js +6 -2
  146. package/logger.js +3 -1
  147. package/node/api/index.d.ts +2 -3
  148. package/node/api/index.js +8 -2
  149. package/node/auth/adapter/adapter.d.ts +1 -1
  150. package/node/auth/adapter/facebook.js +1 -1
  151. package/node/auth/adapter/github.js +4 -4
  152. package/node/auth/adapter/google.d.ts +1 -1
  153. package/node/auth/adapter/google.js +2 -2
  154. package/node/auth/adapter/twitch.js +1 -1
  155. package/node/auth/session.d.ts +1 -1
  156. package/node/config/index.d.ts +2 -2
  157. package/node/config/index.js +3 -8
  158. package/node/job/index.d.ts +2 -2
  159. package/node/site/index.js +3 -5
  160. package/package.json +26 -21
  161. package/pothos.js +1 -0
  162. package/project.d.ts +47 -0
  163. package/{app.js → project.js} +60 -53
  164. package/runtime/handlers/dotnet.d.ts +1 -1
  165. package/runtime/handlers/dotnet.js +4 -4
  166. package/runtime/handlers/go.d.ts +1 -1
  167. package/runtime/handlers/go.js +3 -3
  168. package/runtime/handlers/java.d.ts +1 -1
  169. package/runtime/handlers/java.js +4 -4
  170. package/runtime/handlers/node.d.ts +1 -1
  171. package/runtime/handlers/node.js +60 -39
  172. package/runtime/handlers/python.d.ts +1 -1
  173. package/runtime/handlers/python.js +3 -3
  174. package/runtime/handlers.js +15 -12
  175. package/runtime/iot.js +3 -0
  176. package/runtime/runtime.d.ts +4 -0
  177. package/runtime/server.d.ts +3 -3
  178. package/runtime/server.js +11 -5
  179. package/runtime/workers.d.ts +4 -2
  180. package/runtime/workers.js +13 -3
  181. package/site-env.js +2 -1
  182. package/sst.mjs +6357 -20848
  183. package/stacks/app-metadata.d.ts +7 -0
  184. package/stacks/app-metadata.js +78 -0
  185. package/stacks/assembly.d.ts +1 -0
  186. package/stacks/assembly.js +4 -0
  187. package/stacks/build.d.ts +1 -1
  188. package/stacks/build.js +41 -48
  189. package/stacks/deploy.d.ts +1 -0
  190. package/stacks/deploy.js +128 -7
  191. package/stacks/diff.d.ts +8 -0
  192. package/stacks/diff.js +62 -0
  193. package/stacks/index.d.ts +3 -0
  194. package/stacks/index.js +3 -0
  195. package/stacks/metadata.d.ts +2 -0
  196. package/stacks/metadata.js +14 -12
  197. package/stacks/monitor.d.ts +8 -3
  198. package/stacks/monitor.js +38 -4
  199. package/stacks/remove.js +0 -4
  200. package/stacks/synth.d.ts +1 -0
  201. package/stacks/synth.js +27 -13
  202. package/support/base-site-archiver.mjs +1 -1
  203. package/support/bootstrap-metadata-function/index.mjs +68740 -0
  204. package/support/bridge/bridge.mjs +28 -28
  205. package/support/certificate-requestor/index.js +549 -0
  206. package/support/custom-resources/index.mjs +3824 -26567
  207. package/support/dotnet6-bootstrap/release/dotnet-bootstrap.deps.json +1 -1
  208. package/support/dotnet6-bootstrap/release/dotnet-bootstrap.runtimeconfig.json +1 -1
  209. package/support/edge-function/edge-lambda.mjs +2 -2
  210. package/support/job-invoker/index.mjs +26 -0
  211. package/support/nodejs-runtime/index.mjs +75 -72
  212. package/support/rds-migrator/index.mjs +22 -23
  213. package/support/remix-site-function/edge-server.js +1 -1
  214. package/support/script-function/index.mjs +30485 -0
  215. package/support/{edge-function-code-replacer → sls-nextjs-site-function-code-replacer}/lambda-code-updater.py +0 -0
  216. package/support/ssr-site-function-archiver.mjs +96 -0
  217. package/watcher.js +1 -1
  218. package/app.d.ts +0 -36
  219. package/constructs/DebugApp.d.ts +0 -49
  220. package/constructs/DebugApp.js +0 -63
  221. package/constructs/DebugStack.d.ts +0 -34
  222. package/constructs/DebugStack.js +0 -132
  223. package/constructs/GraphQLApi.d.ts +0 -98
  224. package/constructs/GraphQLApi.js +0 -80
  225. package/constructs/ReactStaticSite.d.ts +0 -20
  226. package/constructs/ReactStaticSite.js +0 -54
  227. package/constructs/Script/cfn-response.d.ts +0 -19
  228. package/constructs/Script/cfn-response.js +0 -77
  229. package/constructs/Script/index.d.ts +0 -1
  230. package/constructs/Script/index.js +0 -78
  231. package/constructs/Script/outbound.d.ts +0 -10
  232. package/constructs/Script/outbound.js +0 -42
  233. package/constructs/Script/util.d.ts +0 -2
  234. package/constructs/Script/util.js +0 -11
  235. package/constructs/ViteStaticSite.d.ts +0 -32
  236. package/constructs/ViteStaticSite.js +0 -66
  237. package/support/astro-site-html-stub/index.html +0 -99
  238. package/support/base-site-archiver.cjs +0 -116
  239. package/support/nextjs-site-html-stub/index.html +0 -99
  240. package/support/remix-site-html-stub/index.html +0 -99
  241. package/support/solid-start-site-html-stub/index.html +0 -99
  242. package/support/static-site-stub/index.html +0 -90
@@ -7,22 +7,23 @@ import { Construct } from "constructs";
7
7
  import { Token, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
8
8
  import * as s3 from "aws-cdk-lib/aws-s3";
9
9
  import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
10
- import * as acm from "aws-cdk-lib/aws-certificatemanager";
11
10
  import * as iam from "aws-cdk-lib/aws-iam";
12
11
  import * as lambda from "aws-cdk-lib/aws-lambda";
13
12
  import * as route53 from "aws-cdk-lib/aws-route53";
14
- import * as route53Patterns from "aws-cdk-lib/aws-route53-patterns";
15
13
  import * as route53Targets from "aws-cdk-lib/aws-route53-targets";
16
14
  import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
17
15
  import * as cfOrigins from "aws-cdk-lib/aws-cloudfront-origins";
18
16
  import { AwsCliLayer } from "aws-cdk-lib/lambda-layer-awscli";
19
17
  import { Stack } from "./Stack.js";
20
18
  import { getBuildCmdEnvironment, buildErrorResponsesFor404ErrorPage, buildErrorResponsesForRedirectToIndex, } from "./BaseSite.js";
19
+ import { HttpsRedirect } from "./cdk/website-redirect.js";
20
+ import { DnsValidatedCertificate } from "./cdk/dns-validated-certificate.js";
21
21
  import { isCDKConstruct } from "./Construct.js";
22
22
  import { ENVIRONMENT_PLACEHOLDER, getParameterPath, } from "./util/functionBinding.js";
23
23
  import { gray } from "colorette";
24
- import { useProject } from "../app.js";
24
+ import { useProject } from "../project.js";
25
25
  import { SiteEnv } from "../site-env.js";
26
+ import { VisibleError } from "../error.js";
26
27
  const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
27
28
  /////////////////////
28
29
  // Construct
@@ -44,49 +45,53 @@ const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
44
45
  */
45
46
  export class StaticSite extends Construct {
46
47
  id;
47
- cdk;
48
48
  props;
49
- isPlaceholder;
50
- assets;
51
- filenamesAsset;
52
- awsCliLayer;
49
+ doNotDeploy;
50
+ bucket;
51
+ distribution;
52
+ hostedZone;
53
+ certificate;
53
54
  constructor(scope, id, props) {
54
- super(scope, props.cdk?.id || id);
55
+ super(scope, props?.cdk?.id || id);
56
+ const app = scope.node.root;
55
57
  this.id = id;
56
- const root = scope.node.root;
57
- // Local development or skip build => stub asset
58
- this.isPlaceholder =
59
- (root.local || root.skipBuild) && !props.disablePlaceholder;
60
- const fileSizeLimit = root.isRunningSSTTest()
61
- ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
62
- // @ts-ignore: "sstTestFileSizeLimitOverride" not exposed in props
63
- props.sstTestFileSizeLimitOverride || 200
64
- : 200;
65
- this.props = props;
66
- this.cdk = {};
67
- this.awsCliLayer = new AwsCliLayer(this, "AwsCliLayer");
68
- this.registerSiteEnvironment();
69
- // Validate input
58
+ this.props = {
59
+ path: ".",
60
+ waitForInvalidation: false,
61
+ ...props,
62
+ };
63
+ this.doNotDeploy = (app.local || app.skipBuild) && !this.props.dev?.deploy;
70
64
  this.validateCustomDomainSettings();
71
- // Generate Vite types
65
+ this.registerSiteEnvironment();
72
66
  this.generateViteTypes();
67
+ if (this.doNotDeploy) {
68
+ // @ts-ignore
69
+ this.bucket = this.distribution = null;
70
+ return;
71
+ }
72
+ const cliLayer = new AwsCliLayer(this, "AwsCliLayer");
73
73
  // Build app
74
+ const fileSizeLimit = app.isRunningSSTTest()
75
+ ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
76
+ // @ts-ignore: "sstTestFileSizeLimitOverride" not exposed in props
77
+ this.props.sstTestFileSizeLimitOverride || 200
78
+ : 200;
74
79
  this.buildApp();
75
- this.assets = this.bundleAssets(fileSizeLimit);
76
- this.filenamesAsset = this.bundleFilenamesAsset();
80
+ const assets = this.bundleAssets(fileSizeLimit);
81
+ const filenamesAsset = this.bundleFilenamesAsset();
77
82
  // Create Bucket
78
- this.cdk.bucket = this.createS3Bucket();
83
+ this.bucket = this.createS3Bucket();
79
84
  // Create Custom Domain
80
- this.cdk.hostedZone = this.lookupHostedZone();
81
- this.cdk.certificate = this.createCertificate();
85
+ this.hostedZone = this.lookupHostedZone();
86
+ this.certificate = this.createCertificate();
82
87
  // Create S3 Deployment
83
- const s3deployCR = this.createS3Deployment();
88
+ const s3deployCR = this.createS3Deployment(cliLayer, assets, filenamesAsset);
84
89
  // Create CloudFront
85
- this.cdk.distribution = this.createCfDistribution();
86
- this.cdk.distribution.node.addDependency(s3deployCR);
90
+ this.distribution = this.createCfDistribution();
91
+ this.distribution.node.addDependency(s3deployCR);
87
92
  // Invalidate CloudFront
88
- const invalidationCR = this.createCloudFrontInvalidation();
89
- invalidationCR.node.addDependency(this.cdk.distribution);
93
+ const invalidationCR = this.createCloudFrontInvalidation(cliLayer, assets);
94
+ invalidationCR.node.addDependency(this.distribution);
90
95
  // Connect Custom Domain to CloudFront Distribution
91
96
  this.createRoute53Records();
92
97
  }
@@ -94,12 +99,18 @@ export class StaticSite extends Construct {
94
99
  * The CloudFront URL of the website.
95
100
  */
96
101
  get url() {
97
- return `https://${this.cdk.distribution.distributionDomainName}`;
102
+ if (this.doNotDeploy) {
103
+ return;
104
+ }
105
+ return `https://${this.distribution.distributionDomainName}`;
98
106
  }
99
107
  /**
100
108
  * If the custom domain is enabled, this is the URL of the website with the custom domain.
101
109
  */
102
110
  get customDomainUrl() {
111
+ if (this.doNotDeploy) {
112
+ return;
113
+ }
103
114
  const { customDomain } = this.props;
104
115
  if (!customDomain) {
105
116
  return;
@@ -112,34 +123,23 @@ export class StaticSite extends Construct {
112
123
  }
113
124
  }
114
125
  /**
115
- * The ARN of the internally created S3 Bucket.
116
- */
117
- get bucketArn() {
118
- return this.cdk.bucket.bucketArn;
119
- }
120
- /**
121
- * The name of the internally created S3 Bucket.
126
+ * The internally created CDK resources.
122
127
  */
123
- get bucketName() {
124
- return this.cdk.bucket.bucketName;
125
- }
126
- /**
127
- * The ID of the internally created CloudFront Distribution.
128
- */
129
- get distributionId() {
130
- return this.cdk.distribution.distributionId;
131
- }
132
- /**
133
- * The domain name of the internally created CloudFront Distribution.
134
- */
135
- get distributionDomain() {
136
- return this.cdk.distribution.distributionDomainName;
128
+ get cdk() {
129
+ if (this.doNotDeploy) {
130
+ throw new VisibleError(`Cannot access CDK resources for the "${this.node.id}" site in dev mode`);
131
+ }
132
+ return {
133
+ bucket: this.bucket,
134
+ distribution: this.distribution,
135
+ hostedZone: this.hostedZone,
136
+ certificate: this.certificate,
137
+ };
137
138
  }
138
139
  getConstructMetadata() {
139
140
  return {
140
141
  type: "StaticSite",
141
142
  data: {
142
- distributionId: this.cdk.distribution.distributionId,
143
143
  customDomainUrl: this.customDomainUrl,
144
144
  },
145
145
  };
@@ -155,13 +155,13 @@ export class StaticSite extends Construct {
155
155
  // depend on the Site. B/c often the site depends on the Api, causing
156
156
  // a CloudFormation circular dependency if the Api and the Site belong
157
157
  // to different stacks.
158
- environment: ENVIRONMENT_PLACEHOLDER,
158
+ environment: this.doNotDeploy ? "" : ENVIRONMENT_PLACEHOLDER,
159
159
  parameter: this.customDomainUrl || this.url,
160
160
  },
161
161
  },
162
162
  permissions: {
163
163
  "ssm:GetParameters": [
164
- `arn:aws:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
164
+ `arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
165
165
  ],
166
166
  },
167
167
  };
@@ -195,9 +195,6 @@ interface ImportMeta {
195
195
  fs.writeFileSync(filePath, content);
196
196
  }
197
197
  buildApp() {
198
- if (this.isPlaceholder) {
199
- return;
200
- }
201
198
  const { path: sitePath, buildCommand } = this.props;
202
199
  // validate site path exists
203
200
  if (!fs.existsSync(sitePath)) {
@@ -222,13 +219,6 @@ interface ImportMeta {
222
219
  }
223
220
  }
224
221
  bundleAssets(fileSizeLimit) {
225
- if (this.isPlaceholder) {
226
- return [
227
- new s3Assets.Asset(this, "Asset", {
228
- path: path.resolve(__dirname, "../support/static-site-stub"),
229
- }),
230
- ];
231
- }
232
222
  const { path: sitePath } = this.props;
233
223
  const buildOutput = this.props.buildOutput || ".";
234
224
  // validate buildOutput exists
@@ -237,7 +227,7 @@ interface ImportMeta {
237
227
  throw new Error(`No build output found at "${siteOutputPath}" for the "${this.node.id}" StaticSite.`);
238
228
  }
239
229
  // create zip files
240
- const script = path.join(__dirname, "../support/base-site-archiver.cjs");
230
+ const script = path.join(__dirname, "../support/base-site-archiver.mjs");
241
231
  const zipPath = path.resolve(path.join(useProject().paths.artifacts, `StaticSite-${this.node.id}-${this.node.addr}`));
242
232
  // clear zip path to ensure no partX.zip remain from previous build
243
233
  fs.rmSync(zipPath, {
@@ -268,9 +258,6 @@ interface ImportMeta {
268
258
  return assets;
269
259
  }
270
260
  bundleFilenamesAsset() {
271
- if (this.isPlaceholder) {
272
- return;
273
- }
274
261
  if (this.props.purgeFiles === false) {
275
262
  return;
276
263
  }
@@ -307,7 +294,7 @@ interface ImportMeta {
307
294
  });
308
295
  }
309
296
  }
310
- createS3Deployment() {
297
+ createS3Deployment(cliLayer, assets, filenamesAsset) {
311
298
  const fileOptions = this.props.fileOptions || [
312
299
  {
313
300
  exclude: "*",
@@ -323,18 +310,18 @@ interface ImportMeta {
323
310
  // Create a Lambda function that will be doing the uploading
324
311
  const uploader = new lambda.Function(this, "S3Uploader", {
325
312
  code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
326
- layers: [this.awsCliLayer],
313
+ layers: [cliLayer],
327
314
  runtime: lambda.Runtime.PYTHON_3_7,
328
315
  handler: "s3-upload.handler",
329
316
  timeout: Duration.minutes(15),
330
317
  memorySize: 1024,
331
318
  });
332
- this.cdk.bucket.grantReadWrite(uploader);
333
- this.assets.forEach((asset) => asset.grantRead(uploader));
319
+ this.bucket.grantReadWrite(uploader);
320
+ assets.forEach((asset) => asset.grantRead(uploader));
334
321
  // Create the custom resource function
335
322
  const handler = new lambda.Function(this, "S3Handler", {
336
323
  code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
337
- layers: [this.awsCliLayer],
324
+ layers: [cliLayer],
338
325
  runtime: lambda.Runtime.PYTHON_3_7,
339
326
  handler: "s3-handler.handler",
340
327
  timeout: Duration.minutes(15),
@@ -343,22 +330,22 @@ interface ImportMeta {
343
330
  UPLOADER_FUNCTION_NAME: uploader.functionName,
344
331
  },
345
332
  });
346
- this.cdk.bucket.grantReadWrite(handler);
347
- this.filenamesAsset?.grantRead(handler);
333
+ this.bucket.grantReadWrite(handler);
334
+ filenamesAsset?.grantRead(handler);
348
335
  uploader.grantInvoke(handler);
349
336
  // Create custom resource
350
337
  return new CustomResource(this, "S3Deployment", {
351
338
  serviceToken: handler.functionArn,
352
339
  resourceType: "Custom::SSTBucketDeployment",
353
340
  properties: {
354
- Sources: this.assets.map((asset) => ({
341
+ Sources: assets.map((asset) => ({
355
342
  BucketName: asset.s3BucketName,
356
343
  ObjectKey: asset.s3ObjectKey,
357
344
  })),
358
- DestinationBucketName: this.cdk.bucket.bucketName,
359
- Filenames: this.filenamesAsset && {
360
- BucketName: this.filenamesAsset.s3BucketName,
361
- ObjectKey: this.filenamesAsset.s3ObjectKey,
345
+ DestinationBucketName: this.bucket.bucketName,
346
+ Filenames: filenamesAsset && {
347
+ BucketName: filenamesAsset.s3BucketName,
348
+ ObjectKey: filenamesAsset.s3ObjectKey,
362
349
  },
363
350
  FileOptions: (fileOptions || []).map(({ exclude, include, cacheControl }) => {
364
351
  if (typeof exclude === "string") {
@@ -411,17 +398,9 @@ interface ImportMeta {
411
398
  }
412
399
  }
413
400
  // Build errorResponses
414
- let errorResponses;
415
- // case: sst start => showing stub site, and redirect all routes to the index page
416
- if (this.isPlaceholder) {
417
- errorResponses = buildErrorResponsesForRedirectToIndex(indexPage);
418
- }
419
- else {
420
- errorResponses =
421
- errorPage === "redirect_to_index_page" || errorPage === undefined
422
- ? buildErrorResponsesForRedirectToIndex(indexPage)
423
- : buildErrorResponsesFor404ErrorPage(errorPage);
424
- }
401
+ const errorResponses = errorPage === "redirect_to_index_page" || errorPage === undefined
402
+ ? buildErrorResponsesForRedirectToIndex(indexPage)
403
+ : buildErrorResponsesFor404ErrorPage(errorPage);
425
404
  // Create CloudFront distribution
426
405
  return new cloudfront.Distribution(this, "Distribution", {
427
406
  // these values can be overwritten by cfDistributionProps
@@ -430,19 +409,19 @@ interface ImportMeta {
430
409
  ...cdk?.distribution,
431
410
  // these values can NOT be overwritten by cfDistributionProps
432
411
  domainNames,
433
- certificate: this.cdk.certificate,
412
+ certificate: this.certificate,
434
413
  defaultBehavior: {
435
- origin: new cfOrigins.S3Origin(this.cdk.bucket),
414
+ origin: new cfOrigins.S3Origin(this.bucket),
436
415
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
437
416
  ...cdk?.distribution?.defaultBehavior,
438
417
  },
439
418
  });
440
419
  }
441
- createCloudFrontInvalidation() {
420
+ createCloudFrontInvalidation(cliLayer, assets) {
442
421
  // Create a Lambda function that will be doing the invalidation
443
422
  const invalidator = new lambda.Function(this, "CloudFrontInvalidator", {
444
423
  code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
445
- layers: [this.awsCliLayer],
424
+ layers: [cliLayer],
446
425
  runtime: lambda.Runtime.PYTHON_3_7,
447
426
  handler: "cf-invalidate.handler",
448
427
  timeout: Duration.minutes(15),
@@ -460,22 +439,17 @@ interface ImportMeta {
460
439
  // Need the AssetHash field so the CR gets updated on each deploy
461
440
  const assetsHash = crypto
462
441
  .createHash("md5")
463
- .update(this.assets.map(({ assetHash }) => assetHash).join(""))
442
+ .update(assets.map(({ assetHash }) => assetHash).join(""))
464
443
  .digest("hex");
465
444
  // Create custom resource
466
- const waitForInvalidation = this.isPlaceholder
467
- ? false
468
- : this.props.waitForInvalidation === false
469
- ? false
470
- : true;
471
445
  return new CustomResource(this, "CloudFrontInvalidation", {
472
446
  serviceToken: invalidator.functionArn,
473
447
  resourceType: "Custom::SSTCloudFrontInvalidation",
474
448
  properties: {
475
449
  AssetsHash: assetsHash,
476
- DistributionId: this.cdk.distribution.distributionId,
450
+ DistributionId: this.distribution.distributionId,
477
451
  DistributionPaths: ["/*"],
478
- WaitForInvalidation: waitForInvalidation,
452
+ WaitForInvalidation: this.props.waitForInvalidation,
479
453
  },
480
454
  });
481
455
  }
@@ -543,11 +517,11 @@ interface ImportMeta {
543
517
  }
544
518
  let acmCertificate;
545
519
  // HostedZone is set for Route 53 domains
546
- if (this.cdk.hostedZone) {
520
+ if (this.hostedZone) {
547
521
  if (typeof customDomain === "string") {
548
- acmCertificate = new acm.DnsValidatedCertificate(this, "Certificate", {
522
+ acmCertificate = new DnsValidatedCertificate(this, "Certificate", {
549
523
  domainName: customDomain,
550
- hostedZone: this.cdk.hostedZone,
524
+ hostedZone: this.hostedZone,
551
525
  region: "us-east-1",
552
526
  });
553
527
  }
@@ -555,9 +529,9 @@ interface ImportMeta {
555
529
  acmCertificate = customDomain.cdk.certificate;
556
530
  }
557
531
  else {
558
- acmCertificate = new acm.DnsValidatedCertificate(this, "Certificate", {
532
+ acmCertificate = new DnsValidatedCertificate(this, "Certificate", {
559
533
  domainName: customDomain.domainName,
560
- hostedZone: this.cdk.hostedZone,
534
+ hostedZone: this.hostedZone,
561
535
  region: "us-east-1",
562
536
  });
563
537
  }
@@ -572,7 +546,7 @@ interface ImportMeta {
572
546
  }
573
547
  createRoute53Records() {
574
548
  const { customDomain } = this.props;
575
- if (!customDomain || !this.cdk.hostedZone) {
549
+ if (!customDomain || !this.hostedZone) {
576
550
  return;
577
551
  }
578
552
  let recordName;
@@ -587,15 +561,15 @@ interface ImportMeta {
587
561
  // Create DNS record
588
562
  const recordProps = {
589
563
  recordName,
590
- zone: this.cdk.hostedZone,
591
- target: route53.RecordTarget.fromAlias(new route53Targets.CloudFrontTarget(this.cdk.distribution)),
564
+ zone: this.hostedZone,
565
+ target: route53.RecordTarget.fromAlias(new route53Targets.CloudFrontTarget(this.distribution)),
592
566
  };
593
567
  new route53.ARecord(this, "AliasRecord", recordProps);
594
568
  new route53.AaaaRecord(this, "AliasRecordAAAA", recordProps);
595
569
  // Create Alias redirect record
596
570
  if (domainAlias) {
597
- new route53Patterns.HttpsRedirect(this, "Redirect", {
598
- zone: this.cdk.hostedZone,
571
+ new HttpsRedirect(this, "Redirect", {
572
+ zone: this.hostedZone,
599
573
  recordNames: [domainAlias],
600
574
  targetDomain: recordName,
601
575
  });
@@ -80,7 +80,7 @@ export interface TableGlobalIndexProps {
80
80
  index?: Omit<dynamodb.GlobalSecondaryIndexProps, "indexName" | "partitionKey" | "sortKey">;
81
81
  };
82
82
  }
83
- declare type TableFieldType = Lowercase<keyof typeof dynamodb.AttributeType>;
83
+ type TableFieldType = Lowercase<keyof typeof dynamodb.AttributeType>;
84
84
  export interface TableProps {
85
85
  /**
86
86
  * An object defining the fields of the table. Key is the name of the field and the value is the type.
@@ -269,7 +269,7 @@ export class Table extends Construct {
269
269
  return {
270
270
  clientPackage: "table",
271
271
  variables: {
272
- "tableName": {
272
+ tableName: {
273
273
  environment: this.tableName,
274
274
  parameter: this.tableName,
275
275
  },
@@ -368,11 +368,11 @@ export class Table extends Construct {
368
368
  fn.addEventSource(eventSource);
369
369
  // set filter pattern
370
370
  if (filters && filters.length > 0) {
371
- const cfnEventSource = fn.node.children.find(c => c instanceof lambda.EventSourceMapping)?.node.defaultChild;
371
+ const cfnEventSource = fn.node.children.find((c) => c instanceof lambda.EventSourceMapping)?.node.defaultChild;
372
372
  cfnEventSource.addPropertyOverride("FilterCriteria", {
373
- Filters: filters.map(filter => ({
373
+ Filters: filters.map((filter) => ({
374
374
  Pattern: JSON.stringify(filter),
375
- }))
375
+ })),
376
376
  });
377
377
  }
378
378
  // attach permissions
@@ -197,7 +197,7 @@ export class Topic extends Construct {
197
197
  return {
198
198
  clientPackage: "topic",
199
199
  variables: {
200
- "topicArn": {
200
+ topicArn: {
201
201
  environment: this.topicArn,
202
202
  parameter: this.topicArn,
203
203
  },
@@ -0,0 +1,18 @@
1
+ import { Metric, MetricOptions } from "aws-cdk-lib/aws-cloudwatch";
2
+ import { Resource } from "aws-cdk-lib";
3
+ import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
4
+ /**
5
+ * Shared implementation details of ICertificate implementations.
6
+ *
7
+ * @internal
8
+ */
9
+ export declare abstract class CertificateBase extends Resource implements ICertificate {
10
+ abstract readonly certificateArn: string;
11
+ /**
12
+ * If the certificate is provisionned in a different region than the
13
+ * containing stack, this should be the region in which the certificate lives
14
+ * so we can correctly create `Metric` instances.
15
+ */
16
+ protected readonly region?: string;
17
+ metricDaysToExpiry(props?: MetricOptions): Metric;
18
+ }
@@ -0,0 +1,26 @@
1
+ import { Metric, Stats } from "aws-cdk-lib/aws-cloudwatch";
2
+ import { Duration, Resource } from "aws-cdk-lib";
3
+ /**
4
+ * Shared implementation details of ICertificate implementations.
5
+ *
6
+ * @internal
7
+ */
8
+ export class CertificateBase extends Resource {
9
+ /**
10
+ * If the certificate is provisionned in a different region than the
11
+ * containing stack, this should be the region in which the certificate lives
12
+ * so we can correctly create `Metric` instances.
13
+ */
14
+ region;
15
+ metricDaysToExpiry(props) {
16
+ return new Metric({
17
+ period: Duration.days(1),
18
+ ...props,
19
+ dimensionsMap: { CertificateArn: this.certificateArn },
20
+ metricName: "DaysToExpiry",
21
+ namespace: "AWS/CertificateManager",
22
+ region: this.region,
23
+ statistic: Stats.MINIMUM,
24
+ });
25
+ }
26
+ }
@@ -0,0 +1,77 @@
1
+ import { Construct } from "constructs";
2
+ import { ITaggable, TagManager, RemovalPolicy } from "aws-cdk-lib";
3
+ import { CertificateProps, ICertificate } from "aws-cdk-lib/aws-certificatemanager";
4
+ import * as iam from "aws-cdk-lib/aws-iam";
5
+ import * as route53 from "aws-cdk-lib/aws-route53";
6
+ import { CertificateBase } from "./certificate-base.js";
7
+ /**
8
+ * Properties to create a DNS validated certificate managed by AWS Certificate Manager
9
+ *
10
+ */
11
+ export interface DnsValidatedCertificateProps extends CertificateProps {
12
+ /**
13
+ * Route 53 Hosted Zone used to perform DNS validation of the request. The zone
14
+ * must be authoritative for the domain name specified in the Certificate Request.
15
+ */
16
+ readonly hostedZone: route53.IHostedZone;
17
+ /**
18
+ * AWS region that will host the certificate. This is needed especially
19
+ * for certificates used for CloudFront distributions, which require the region
20
+ * to be us-east-1.
21
+ *
22
+ * @default the region the stack is deployed in.
23
+ */
24
+ readonly region?: string;
25
+ /**
26
+ * An endpoint of Route53 service, which is not necessary as AWS SDK could figure
27
+ * out the right endpoints for most regions, but for some regions such as those in
28
+ * aws-cn partition, the default endpoint is not working now, hence the right endpoint
29
+ * need to be specified through this prop.
30
+ *
31
+ * Route53 is not been officially launched in China, it is only available for AWS
32
+ * internal accounts now. To make DnsValidatedCertificate work for internal accounts
33
+ * now, a special endpoint needs to be provided.
34
+ *
35
+ * @default - The AWS SDK will determine the Route53 endpoint to use based on region
36
+ */
37
+ readonly route53Endpoint?: string;
38
+ /**
39
+ * Role to use for the custom resource that creates the validated certificate
40
+ *
41
+ * @default - A new role will be created
42
+ */
43
+ readonly customResourceRole?: iam.IRole;
44
+ /**
45
+ * When set to true, when the DnsValidatedCertificate is deleted,
46
+ * the associated Route53 validation records are removed.
47
+ *
48
+ * CAUTION: If multiple certificates share the same domains (and same validation records),
49
+ * this can cause the other certificates to fail renewal and/or not validate.
50
+ * Not recommended for production use.
51
+ *
52
+ * @default false
53
+ */
54
+ readonly cleanupRoute53Records?: boolean;
55
+ }
56
+ /**
57
+ * A certificate managed by AWS Certificate Manager. Will be automatically
58
+ * validated using DNS validation against the specified Route 53 hosted zone.
59
+ *
60
+ * @resource AWS::CertificateManager::Certificate
61
+ */
62
+ export declare class DnsValidatedCertificate extends CertificateBase implements ICertificate, ITaggable {
63
+ readonly certificateArn: string;
64
+ /**
65
+ * Resource Tags.
66
+ * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-certificate.html#cfn-certificatemanager-certificate-tags
67
+ */
68
+ readonly tags: TagManager;
69
+ protected readonly region?: string;
70
+ private normalizedZoneName;
71
+ private hostedZoneId;
72
+ private domainName;
73
+ private _removalPolicy?;
74
+ constructor(scope: Construct, id: string, props: DnsValidatedCertificateProps);
75
+ applyRemovalPolicy(policy: RemovalPolicy): void;
76
+ private validateDnsValidatedCertificate;
77
+ }