sst 2.0.0-rc.9 → 2.0.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 (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
@@ -6,26 +6,27 @@ import crypto from "crypto";
6
6
  import spawn from "cross-spawn";
7
7
  import { execSync } from "child_process";
8
8
  import { Construct } from "constructs";
9
- import { Fn, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
10
- import * as s3 from "aws-cdk-lib/aws-s3";
11
- import * as iam from "aws-cdk-lib/aws-iam";
12
- import * as lambda from "aws-cdk-lib/aws-lambda";
13
- import * as route53 from "aws-cdk-lib/aws-route53";
14
- import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
15
- import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
16
- import * as acm from "aws-cdk-lib/aws-certificatemanager";
9
+ import { Fn, Token, Duration as CdkDuration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
10
+ import { Bucket } from "aws-cdk-lib/aws-s3";
11
+ import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
12
+ import { Function, Code, Runtime, FunctionUrlAuthType, } from "aws-cdk-lib/aws-lambda";
13
+ import { HostedZone, ARecord, AaaaRecord, RecordTarget, } from "aws-cdk-lib/aws-route53";
14
+ import { Asset } from "aws-cdk-lib/aws-s3-assets";
15
+ import { Distribution, ViewerProtocolPolicy, AllowedMethods, CachedMethods, LambdaEdgeEventType, CachePolicy, CacheQueryStringBehavior, CacheHeaderBehavior, CacheCookieBehavior, } from "aws-cdk-lib/aws-cloudfront";
17
16
  import { AwsCliLayer } from "aws-cdk-lib/lambda-layer-awscli";
18
- import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
19
- import * as route53Targets from "aws-cdk-lib/aws-route53-targets";
20
- import * as route53Patterns from "aws-cdk-lib/aws-route53-patterns";
17
+ import { S3Origin, HttpOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
18
+ import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
21
19
  import { Stack } from "./Stack.js";
22
20
  import { Logger } from "../logger.js";
23
21
  import { isCDKConstruct } from "./Construct.js";
24
- import { getBuildCmdEnvironment, buildErrorResponsesForRedirectToIndex, } from "./BaseSite.js";
22
+ import { getBuildCmdEnvironment, } from "./BaseSite.js";
23
+ import { HttpsRedirect } from "./cdk/website-redirect.js";
24
+ import { DnsValidatedCertificate } from "./cdk/dns-validated-certificate.js";
25
25
  import { attachPermissionsToRole } from "./util/permission.js";
26
26
  import { ENVIRONMENT_PLACEHOLDER, getParameterPath, } from "./util/functionBinding.js";
27
27
  import { SiteEnv } from "../site-env.js";
28
- import { useProject } from "../app.js";
28
+ import { useProject } from "../project.js";
29
+ import { VisibleError } from "../error.js";
29
30
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
30
31
  /**
31
32
  * The `SsrSite` construct is a higher level CDK construct that makes it easy to create modern web apps with Server Side Rendering capabilities.
@@ -40,79 +41,66 @@ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
40
41
  */
41
42
  export class SsrSite extends Construct {
42
43
  id;
43
- /**
44
- * Exposes CDK instances created within the construct.
45
- */
46
- cdk;
47
44
  props;
48
- /**
49
- * Determines if a placeholder site should be deployed instead. We will set
50
- * this to `true` by default when performing local development, although the
51
- * user can choose to override this value.
52
- */
53
- isPlaceholder;
54
- /**
55
- * The root SST directory used for builds.
56
- */
57
- sstBuildDir;
45
+ doNotDeploy;
58
46
  buildConfig;
59
47
  serverLambdaForEdge;
60
48
  serverLambdaForRegional;
61
- awsCliLayer;
49
+ bucket;
50
+ distribution;
51
+ hostedZone;
52
+ certificate;
62
53
  constructor(scope, id, props) {
63
- super(scope, props.cdk?.id || id);
64
- this.id = id;
54
+ super(scope, props?.cdk?.id || id);
65
55
  const app = scope.node.root;
66
- this.isPlaceholder =
67
- (app.local || app.skipBuild) && !props.disablePlaceholder;
68
- this.sstBuildDir = useProject().paths.artifacts;
69
- this.props = props;
70
- this.cdk = {};
71
- this.awsCliLayer = new AwsCliLayer(this, "AwsCliLayer");
56
+ this.id = id;
57
+ this.props = {
58
+ path: ".",
59
+ waitForInvalidation: false,
60
+ timeout: "10 seconds",
61
+ memorySize: "1024 MB",
62
+ ...props,
63
+ };
64
+ this.doNotDeploy = (app.local || app.skipBuild) && !this.props.dev?.deploy;
72
65
  this.validateSiteExists();
73
66
  this.registerSiteEnvironment();
74
- this.buildConfig = this.initBuildConfig();
75
- // Prepare app
76
- if (!this.isPlaceholder) {
77
- this.buildApp();
67
+ if (this.doNotDeploy) {
68
+ // @ts-ignore
69
+ this.buildConfig = this.bucket = this.distribution = null;
70
+ return;
78
71
  }
72
+ const cliLayer = new AwsCliLayer(this, "AwsCliLayer");
73
+ // Build app
74
+ this.buildConfig = this.initBuildConfig();
75
+ this.buildApp();
79
76
  // Create Bucket which will be utilised to contain the statics
80
- this.cdk.bucket = this.createS3Bucket();
77
+ this.bucket = this.createS3Bucket();
81
78
  // Create Server functions
82
- if (props.edge) {
79
+ if (this.props.edge) {
83
80
  this.serverLambdaForEdge = this.createFunctionForEdge();
84
81
  this.createFunctionPermissionsForEdge();
85
82
  }
86
83
  else {
87
84
  this.serverLambdaForRegional = this.createFunctionForRegional();
88
85
  this.createFunctionPermissionsForRegional();
89
- this.cdk.function = this.serverLambdaForRegional;
90
86
  }
91
87
  // Create Custom Domain
92
88
  this.validateCustomDomainSettings();
93
- this.cdk.hostedZone = this.lookupHostedZone();
94
- this.cdk.certificate = this.createCertificate();
89
+ this.hostedZone = this.lookupHostedZone();
90
+ this.certificate = this.createCertificate();
95
91
  // Create S3 Deployment
96
- const assets = this.isPlaceholder
97
- ? this.createStaticsS3AssetsWithStub()
98
- : this.createStaticsS3Assets();
99
- const s3deployCR = this.createS3Deployment(assets);
92
+ const assets = this.createS3Assets();
93
+ const assetFileOptions = this.createS3AssetFileOptions();
94
+ const s3deployCR = this.createS3Deployment(cliLayer, assets, assetFileOptions);
100
95
  // Create CloudFront
101
96
  this.validateCloudFrontDistributionSettings();
102
- if (props.edge) {
103
- this.cdk.distribution = this.isPlaceholder
104
- ? this.createCloudFrontDistributionForStub()
105
- : this.createCloudFrontDistributionForEdge();
106
- }
107
- else {
108
- this.cdk.distribution = this.isPlaceholder
109
- ? this.createCloudFrontDistributionForStub()
110
- : this.createCloudFrontDistributionForRegional();
111
- }
112
- this.cdk.distribution.node.addDependency(s3deployCR);
97
+ this.distribution = this.props.edge
98
+ ? this.createCloudFrontDistributionForEdge()
99
+ : this.createCloudFrontDistributionForRegional();
100
+ this.distribution.node.addDependency(s3deployCR);
113
101
  // Invalidate CloudFront
114
- const invalidationCR = this.createCloudFrontInvalidation();
115
- invalidationCR.node.addDependency(this.cdk.distribution);
102
+ const invalidationCR = this.createCloudFrontInvalidation(cliLayer);
103
+ invalidationCR.node.addDependency(this.distribution);
116
104
  // Connect Custom Domain to CloudFront Distribution
117
105
  this.createRoute53Records();
118
106
  }
@@ -123,13 +111,19 @@ export class SsrSite extends Construct {
123
111
  * The CloudFront URL of the website.
124
112
  */
125
113
  get url() {
126
- return `https://${this.cdk.distribution.distributionDomainName}`;
114
+ if (this.doNotDeploy) {
115
+ return;
116
+ }
117
+ return `https://${this.distribution.distributionDomainName}`;
127
118
  }
128
119
  /**
129
120
  * If the custom domain is enabled, this is the URL of the website with the
130
121
  * custom domain.
131
122
  */
132
123
  get customDomainUrl() {
124
+ if (this.doNotDeploy) {
125
+ return;
126
+ }
133
127
  const { customDomain } = this.props;
134
128
  if (!customDomain) {
135
129
  return;
@@ -142,28 +136,19 @@ export class SsrSite extends Construct {
142
136
  }
143
137
  }
144
138
  /**
145
- * The ARN of the internally created S3 Bucket.
146
- */
147
- get bucketArn() {
148
- return this.cdk.bucket.bucketArn;
149
- }
150
- /**
151
- * The name of the internally created S3 Bucket.
152
- */
153
- get bucketName() {
154
- return this.cdk.bucket.bucketName;
155
- }
156
- /**
157
- * The ID of the internally created CloudFront Distribution.
158
- */
159
- get distributionId() {
160
- return this.cdk.distribution.distributionId;
161
- }
162
- /**
163
- * The domain name of the internally created CloudFront Distribution.
139
+ * The internally created CDK resources.
164
140
  */
165
- get distributionDomain() {
166
- return this.cdk.distribution.distributionDomainName;
141
+ get cdk() {
142
+ if (this.doNotDeploy) {
143
+ throw new VisibleError(`Cannot access CDK resources for the "${this.node.id}" site in dev mode`);
144
+ }
145
+ return {
146
+ function: this.serverLambdaForRegional,
147
+ bucket: this.bucket,
148
+ distribution: this.distribution,
149
+ hostedZone: this.hostedZone,
150
+ certificate: this.certificate,
151
+ };
167
152
  }
168
153
  /////////////////////
169
154
  // Public Methods
@@ -188,7 +173,6 @@ export class SsrSite extends Construct {
188
173
  return {
189
174
  type: "SsrSite",
190
175
  data: {
191
- distributionId: this.cdk.distribution.distributionId,
192
176
  customDomainUrl: this.customDomainUrl,
193
177
  },
194
178
  };
@@ -204,13 +188,13 @@ export class SsrSite extends Construct {
204
188
  // depend on the Site. B/c often the site depends on the Api, causing
205
189
  // a CloudFormation circular dependency if the Api and the Site belong
206
190
  // to different stacks.
207
- environment: ENVIRONMENT_PLACEHOLDER,
191
+ environment: this.doNotDeploy ? "" : ENVIRONMENT_PLACEHOLDER,
208
192
  parameter: this.customDomainUrl || this.url,
209
193
  },
210
194
  },
211
195
  permissions: {
212
196
  "ssm:GetParameters": [
213
- `arn:aws:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
197
+ `arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
214
198
  ],
215
199
  },
216
200
  };
@@ -223,7 +207,6 @@ export class SsrSite extends Construct {
223
207
  serverBuildOutputFile: "placeholder",
224
208
  clientBuildOutputDir: "placeholder",
225
209
  clientBuildVersionedSubDir: "placeholder",
226
- siteStub: "placeholder",
227
210
  };
228
211
  }
229
212
  buildApp() {
@@ -272,13 +255,13 @@ export class SsrSite extends Construct {
272
255
  /////////////////////
273
256
  // Bundle S3 Assets
274
257
  /////////////////////
275
- createStaticsS3Assets() {
258
+ createS3Assets() {
276
259
  // Create temp folder, clean up if exists
277
- const zipOutDir = path.resolve(path.join(this.sstBuildDir, `Site-${this.node.id}-${this.node.addr}`));
260
+ const zipOutDir = path.resolve(path.join(useProject().paths.artifacts, `Site-${this.node.id}-${this.node.addr}`));
278
261
  fs.rmSync(zipOutDir, { recursive: true, force: true });
279
262
  // Create zip files
280
263
  const app = this.node.root;
281
- const script = path.resolve(__dirname, "../support/base-site-archiver.cjs");
264
+ const script = path.resolve(__dirname, "../support/base-site-archiver.mjs");
282
265
  const fileSizeLimit = app.isRunningSSTTest()
283
266
  ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
284
267
  // @ts-ignore: "sstTestFileSizeLimitOverride" not exposed in props
@@ -302,18 +285,40 @@ export class SsrSite extends Construct {
302
285
  if (!fs.existsSync(zipFilePath)) {
303
286
  break;
304
287
  }
305
- assets.push(new s3Assets.Asset(this, `Asset${partId}`, {
288
+ assets.push(new Asset(this, `Asset${partId}`, {
306
289
  path: zipFilePath,
307
290
  }));
308
291
  }
309
292
  return assets;
310
293
  }
311
- createStaticsS3AssetsWithStub() {
312
- return [
313
- new s3Assets.Asset(this, "Asset", {
314
- path: this.buildConfig.siteStub,
315
- }),
316
- ];
294
+ createS3AssetFileOptions() {
295
+ // Build file options
296
+ const fileOptions = [];
297
+ const clientPath = path.join(this.props.path, this.buildConfig.clientBuildOutputDir);
298
+ for (const item of fs.readdirSync(clientPath)) {
299
+ // Versioned files will be cached for 1 year (immutable) both at
300
+ // CDN and browser level.
301
+ if (item === this.buildConfig.clientBuildVersionedSubDir) {
302
+ fileOptions.push({
303
+ exclude: "*",
304
+ include: `${this.buildConfig.clientBuildVersionedSubDir}/*`,
305
+ cacheControl: "public,max-age=31536000,immutable",
306
+ });
307
+ }
308
+ // Un-versioned files will be cached for 1 year at the CDN level.
309
+ // But not at the browser level. CDN cache will be invalidated on deploy.
310
+ else {
311
+ const itemPath = path.join(clientPath, item);
312
+ fileOptions.push({
313
+ exclude: "*",
314
+ include: fs.statSync(itemPath).isDirectory()
315
+ ? `${item}/*`
316
+ : `${item}`,
317
+ cacheControl: "public,max-age=0,s-maxage=31536000,must-revalidate",
318
+ });
319
+ }
320
+ }
321
+ return fileOptions;
317
322
  }
318
323
  createS3Bucket() {
319
324
  const { cdk } = this.props;
@@ -324,7 +329,7 @@ export class SsrSite extends Construct {
324
329
  // cdk.bucket is a prop
325
330
  else {
326
331
  const bucketProps = cdk?.bucket;
327
- return new s3.Bucket(this, "S3Bucket", {
332
+ return new Bucket(this, "S3Bucket", {
328
333
  publicReadAccess: true,
329
334
  autoDeleteObjects: true,
330
335
  removalPolicy: RemovalPolicy.DESTROY,
@@ -332,58 +337,32 @@ export class SsrSite extends Construct {
332
337
  });
333
338
  }
334
339
  }
335
- createS3Deployment(assets) {
340
+ createS3Deployment(cliLayer, assets, fileOptions) {
336
341
  // Create a Lambda function that will be doing the uploading
337
- const uploader = new lambda.Function(this, "S3Uploader", {
338
- code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
339
- layers: [this.awsCliLayer],
340
- runtime: lambda.Runtime.PYTHON_3_7,
342
+ const uploader = new Function(this, "S3Uploader", {
343
+ code: Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
344
+ layers: [cliLayer],
345
+ runtime: Runtime.PYTHON_3_7,
341
346
  handler: "s3-upload.handler",
342
- timeout: Duration.minutes(15),
347
+ timeout: CdkDuration.minutes(15),
343
348
  memorySize: 1024,
344
349
  });
345
- this.cdk.bucket.grantReadWrite(uploader);
350
+ this.bucket.grantReadWrite(uploader);
346
351
  assets.forEach((asset) => asset.grantRead(uploader));
347
352
  // Create the custom resource function
348
- const handler = new lambda.Function(this, "S3Handler", {
349
- code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
350
- layers: [this.awsCliLayer],
351
- runtime: lambda.Runtime.PYTHON_3_7,
353
+ const handler = new Function(this, "S3Handler", {
354
+ code: Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
355
+ layers: [cliLayer],
356
+ runtime: Runtime.PYTHON_3_7,
352
357
  handler: "s3-handler.handler",
353
- timeout: Duration.minutes(15),
358
+ timeout: CdkDuration.minutes(15),
354
359
  memorySize: 1024,
355
360
  environment: {
356
361
  UPLOADER_FUNCTION_NAME: uploader.functionName,
357
362
  },
358
363
  });
359
- this.cdk.bucket.grantReadWrite(handler);
364
+ this.bucket.grantReadWrite(handler);
360
365
  uploader.grantInvoke(handler);
361
- // Build file options
362
- const fileOptions = [];
363
- const clientPath = path.join(this.props.path, this.buildConfig.clientBuildOutputDir);
364
- for (const item of fs.readdirSync(clientPath)) {
365
- // Versioned files will be cached for 1 year (immutable) both at
366
- // CDN and browser level.
367
- if (item === this.buildConfig.clientBuildVersionedSubDir) {
368
- fileOptions.push({
369
- exclude: "*",
370
- include: `${this.buildConfig.clientBuildVersionedSubDir}/*`,
371
- cacheControl: "public,max-age=31536000,immutable",
372
- });
373
- }
374
- // Un-versioned files will be cached for 1 year at the CDN level.
375
- // But not at the browser level. CDN cache will be invalidated on deploy.
376
- else {
377
- const itemPath = path.join(clientPath, item);
378
- fileOptions.push({
379
- exclude: "*",
380
- include: fs.statSync(itemPath).isDirectory()
381
- ? `${item}/*`
382
- : `${item}`,
383
- cacheControl: "public,max-age=0,s-maxage=31536000,must-revalidate",
384
- });
385
- }
386
- }
387
366
  // Create custom resource
388
367
  return new CustomResource(this, "S3Deployment", {
389
368
  serviceToken: handler.functionArn,
@@ -393,7 +372,7 @@ export class SsrSite extends Construct {
393
372
  BucketName: asset.s3BucketName,
394
373
  ObjectKey: asset.s3ObjectKey,
395
374
  })),
396
- DestinationBucketName: this.cdk.bucket.bucketName,
375
+ DestinationBucketName: this.bucket.bucketName,
397
376
  FileOptions: (fileOptions || []).map(({ exclude, include, cacheControl }) => {
398
377
  return [
399
378
  "--exclude",
@@ -404,6 +383,7 @@ export class SsrSite extends Construct {
404
383
  cacheControl,
405
384
  ];
406
385
  }),
386
+ ReplaceValues: this.getS3ContentReplaceValues(),
407
387
  },
408
388
  });
409
389
  }
@@ -417,14 +397,14 @@ export class SsrSite extends Construct {
417
397
  return {};
418
398
  }
419
399
  createFunctionPermissionsForRegional() {
420
- const { defaults } = this.props;
421
- this.cdk.bucket.grantReadWrite(this.serverLambdaForRegional.role);
422
- if (defaults?.function?.permissions) {
423
- attachPermissionsToRole(this.serverLambdaForRegional.role, defaults.function.permissions);
400
+ const { permissions } = this.props;
401
+ this.bucket.grantReadWrite(this.serverLambdaForRegional.role);
402
+ if (permissions) {
403
+ attachPermissionsToRole(this.serverLambdaForRegional.role, permissions);
424
404
  }
425
405
  }
426
406
  createFunctionPermissionsForEdge() {
427
- this.cdk.bucket.grantReadWrite(this.serverLambdaForEdge.role);
407
+ this.bucket.grantReadWrite(this.serverLambdaForEdge.role);
428
408
  }
429
409
  /////////////////////
430
410
  // CloudFront Distribution
@@ -442,15 +422,15 @@ export class SsrSite extends Construct {
442
422
  createCloudFrontDistributionForRegional() {
443
423
  const { cdk } = this.props;
444
424
  const cfDistributionProps = cdk?.distribution || {};
445
- const s3Origin = new origins.S3Origin(this.cdk.bucket);
446
- return new cloudfront.Distribution(this, "Distribution", {
425
+ const s3Origin = new S3Origin(this.bucket);
426
+ return new Distribution(this, "Distribution", {
447
427
  // these values can be overwritten by cfDistributionProps
448
428
  defaultRootObject: "",
449
429
  // Override props.
450
430
  ...cfDistributionProps,
451
431
  // these values can NOT be overwritten by cfDistributionProps
452
432
  domainNames: this.buildDistributionDomainNames(),
453
- certificate: this.cdk.certificate,
433
+ certificate: this.certificate,
454
434
  defaultBehavior: this.buildDistributionDefaultBehaviorForRegional(),
455
435
  additionalBehaviors: {
456
436
  ...this.buildDistributionStaticFileBehaviors(s3Origin),
@@ -461,15 +441,15 @@ export class SsrSite extends Construct {
461
441
  createCloudFrontDistributionForEdge() {
462
442
  const { cdk } = this.props;
463
443
  const cfDistributionProps = cdk?.distribution || {};
464
- const s3Origin = new origins.S3Origin(this.cdk.bucket);
465
- return new cloudfront.Distribution(this, "Distribution", {
444
+ const s3Origin = new S3Origin(this.bucket);
445
+ return new Distribution(this, "Distribution", {
466
446
  // these values can be overwritten by cfDistributionProps
467
447
  defaultRootObject: "",
468
448
  // Override props.
469
449
  ...cfDistributionProps,
470
450
  // these values can NOT be overwritten by cfDistributionProps
471
451
  domainNames: this.buildDistributionDomainNames(),
472
- certificate: this.cdk.certificate,
452
+ certificate: this.certificate,
473
453
  defaultBehavior: this.buildDistributionDefaultBehaviorForEdge(s3Origin),
474
454
  additionalBehaviors: {
475
455
  ...this.buildDistributionStaticFileBehaviors(s3Origin),
@@ -477,18 +457,6 @@ export class SsrSite extends Construct {
477
457
  },
478
458
  });
479
459
  }
480
- createCloudFrontDistributionForStub() {
481
- return new cloudfront.Distribution(this, "Distribution", {
482
- defaultRootObject: "index.html",
483
- errorResponses: buildErrorResponsesForRedirectToIndex("index.html"),
484
- domainNames: this.buildDistributionDomainNames(),
485
- certificate: this.cdk.certificate,
486
- defaultBehavior: {
487
- origin: new origins.S3Origin(this.cdk.bucket),
488
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
489
- },
490
- });
491
- }
492
460
  buildDistributionDomainNames() {
493
461
  const { customDomain } = this.props;
494
462
  const domainNames = [];
@@ -507,16 +475,15 @@ export class SsrSite extends Construct {
507
475
  const { cdk } = this.props;
508
476
  const cfDistributionProps = cdk?.distribution || {};
509
477
  const fnUrl = this.serverLambdaForRegional.addFunctionUrl({
510
- authType: lambda.FunctionUrlAuthType.NONE,
478
+ authType: FunctionUrlAuthType.NONE,
511
479
  });
512
480
  return {
513
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
514
- origin: new origins.HttpOrigin(Fn.parseDomainName(fnUrl.url)),
515
- allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
516
- cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
481
+ viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
482
+ origin: new HttpOrigin(Fn.parseDomainName(fnUrl.url)),
483
+ allowedMethods: AllowedMethods.ALLOW_ALL,
484
+ cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS,
517
485
  compress: true,
518
- cachePolicy: cdk?.cachePolicies?.serverRequests ??
519
- this.createCloudFrontServerCachePolicy(),
486
+ cachePolicy: cdk?.serverCachePolicy ?? this.createCloudFrontServerCachePolicy(),
520
487
  ...(cfDistributionProps.defaultBehavior || {}),
521
488
  };
522
489
  }
@@ -524,19 +491,18 @@ export class SsrSite extends Construct {
524
491
  const { cdk } = this.props;
525
492
  const cfDistributionProps = cdk?.distribution || {};
526
493
  return {
527
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
494
+ viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
528
495
  origin,
529
- allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
530
- cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
496
+ allowedMethods: AllowedMethods.ALLOW_ALL,
497
+ cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS,
531
498
  compress: true,
532
- cachePolicy: cdk?.cachePolicies?.serverRequests ??
533
- this.createCloudFrontServerCachePolicy(),
499
+ cachePolicy: cdk?.serverCachePolicy ?? this.createCloudFrontServerCachePolicy(),
534
500
  ...(cfDistributionProps.defaultBehavior || {}),
535
501
  // concatenate edgeLambdas
536
502
  edgeLambdas: [
537
503
  {
538
504
  includeBody: true,
539
- eventType: cloudfront.LambdaEdgeEventType.ORIGIN_REQUEST,
505
+ eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
540
506
  functionVersion: this.serverLambdaForEdge.currentVersion,
541
507
  },
542
508
  ...(cfDistributionProps.defaultBehavior?.edgeLambdas || []),
@@ -547,12 +513,12 @@ export class SsrSite extends Construct {
547
513
  const { cdk } = this.props;
548
514
  // Create additional behaviours for statics
549
515
  const staticBehaviourOptions = {
550
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
516
+ viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
551
517
  origin,
552
- allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
553
- cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
518
+ allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
519
+ cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS,
554
520
  compress: true,
555
- cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
521
+ cachePolicy: CachePolicy.CACHING_OPTIMIZED,
556
522
  };
557
523
  // Add behaviour for public folder statics (excluding build)
558
524
  const staticsBehaviours = {};
@@ -568,51 +534,46 @@ export class SsrSite extends Construct {
568
534
  return staticsBehaviours;
569
535
  }
570
536
  createCloudFrontServerCachePolicy() {
571
- return new cloudfront.CachePolicy(this, "ServerCache", {
572
- queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
573
- headerBehavior: cloudfront.CacheHeaderBehavior.none(),
574
- cookieBehavior: cloudfront.CacheCookieBehavior.all(),
575
- defaultTtl: Duration.days(0),
576
- maxTtl: Duration.days(365),
577
- minTtl: Duration.days(0),
537
+ return new CachePolicy(this, "ServerCache", {
538
+ queryStringBehavior: CacheQueryStringBehavior.all(),
539
+ headerBehavior: CacheHeaderBehavior.none(),
540
+ cookieBehavior: CacheCookieBehavior.all(),
541
+ defaultTtl: CdkDuration.days(0),
542
+ maxTtl: CdkDuration.days(365),
543
+ minTtl: CdkDuration.days(0),
578
544
  enableAcceptEncodingBrotli: true,
579
545
  enableAcceptEncodingGzip: true,
580
546
  comment: "SST server response cache policy",
581
547
  });
582
548
  }
583
- createCloudFrontInvalidation() {
549
+ createCloudFrontInvalidation(cliLayer) {
584
550
  // Create a Lambda function that will be doing the invalidation
585
- const invalidator = new lambda.Function(this, "CloudFrontInvalidator", {
586
- code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
587
- layers: [this.awsCliLayer],
588
- runtime: lambda.Runtime.PYTHON_3_7,
551
+ const invalidator = new Function(this, "CloudFrontInvalidator", {
552
+ code: Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
553
+ layers: [cliLayer],
554
+ runtime: Runtime.PYTHON_3_7,
589
555
  handler: "cf-invalidate.handler",
590
- timeout: Duration.minutes(15),
556
+ timeout: CdkDuration.minutes(15),
591
557
  memorySize: 1024,
592
558
  });
593
559
  // Grant permissions to invalidate CF Distribution
594
- invalidator.addToRolePolicy(new iam.PolicyStatement({
595
- effect: iam.Effect.ALLOW,
560
+ invalidator.addToRolePolicy(new PolicyStatement({
561
+ effect: Effect.ALLOW,
596
562
  actions: [
597
563
  "cloudfront:GetInvalidation",
598
564
  "cloudfront:CreateInvalidation",
599
565
  ],
600
566
  resources: ["*"],
601
567
  }));
602
- const waitForInvalidation = this.isPlaceholder
603
- ? false
604
- : this.props.waitForInvalidation === false
605
- ? false
606
- : true;
607
568
  return new CustomResource(this, "CloudFrontInvalidation", {
608
569
  serviceToken: invalidator.functionArn,
609
570
  resourceType: "Custom::SSTCloudFrontInvalidation",
610
571
  properties: {
611
- BuildId: this.isPlaceholder ? "live" : this.generateBuildId(),
612
- DistributionId: this.cdk.distribution.distributionId,
572
+ BuildId: this.generateBuildId(),
573
+ DistributionId: this.distribution.distributionId,
613
574
  // TODO: Ignore the browser build path as it may speed up invalidation
614
575
  DistributionPaths: ["/*"],
615
- WaitForInvalidation: waitForInvalidation,
576
+ WaitForInvalidation: this.props.waitForInvalidation,
616
577
  },
617
578
  });
618
579
  }
@@ -647,7 +608,7 @@ export class SsrSite extends Construct {
647
608
  }
648
609
  let hostedZone;
649
610
  if (typeof customDomain === "string") {
650
- hostedZone = route53.HostedZone.fromLookup(this, "HostedZone", {
611
+ hostedZone = HostedZone.fromLookup(this, "HostedZone", {
651
612
  domainName: customDomain,
652
613
  });
653
614
  }
@@ -655,7 +616,7 @@ export class SsrSite extends Construct {
655
616
  hostedZone = customDomain.cdk.hostedZone;
656
617
  }
657
618
  else if (typeof customDomain.hostedZone === "string") {
658
- hostedZone = route53.HostedZone.fromLookup(this, "HostedZone", {
619
+ hostedZone = HostedZone.fromLookup(this, "HostedZone", {
659
620
  domainName: customDomain.hostedZone,
660
621
  });
661
622
  }
@@ -664,7 +625,7 @@ export class SsrSite extends Construct {
664
625
  if (customDomain.isExternalDomain === true) {
665
626
  return;
666
627
  }
667
- hostedZone = route53.HostedZone.fromLookup(this, "HostedZone", {
628
+ hostedZone = HostedZone.fromLookup(this, "HostedZone", {
668
629
  domainName: customDomain.domainName,
669
630
  });
670
631
  }
@@ -680,11 +641,11 @@ export class SsrSite extends Construct {
680
641
  }
681
642
  let acmCertificate;
682
643
  // HostedZone is set for Route 53 domains
683
- if (this.cdk.hostedZone) {
644
+ if (this.hostedZone) {
684
645
  if (typeof customDomain === "string") {
685
- acmCertificate = new acm.DnsValidatedCertificate(this, "Certificate", {
646
+ acmCertificate = new DnsValidatedCertificate(this, "Certificate", {
686
647
  domainName: customDomain,
687
- hostedZone: this.cdk.hostedZone,
648
+ hostedZone: this.hostedZone,
688
649
  region: "us-east-1",
689
650
  });
690
651
  }
@@ -692,9 +653,9 @@ export class SsrSite extends Construct {
692
653
  acmCertificate = customDomain.cdk.certificate;
693
654
  }
694
655
  else {
695
- acmCertificate = new acm.DnsValidatedCertificate(this, "Certificate", {
656
+ acmCertificate = new DnsValidatedCertificate(this, "Certificate", {
696
657
  domainName: customDomain.domainName,
697
- hostedZone: this.cdk.hostedZone,
658
+ hostedZone: this.hostedZone,
698
659
  region: "us-east-1",
699
660
  });
700
661
  }
@@ -709,7 +670,7 @@ export class SsrSite extends Construct {
709
670
  }
710
671
  createRoute53Records() {
711
672
  const { customDomain } = this.props;
712
- if (!customDomain || !this.cdk.hostedZone) {
673
+ if (!customDomain || !this.hostedZone) {
713
674
  return;
714
675
  }
715
676
  let recordName;
@@ -724,15 +685,15 @@ export class SsrSite extends Construct {
724
685
  // Create DNS record
725
686
  const recordProps = {
726
687
  recordName,
727
- zone: this.cdk.hostedZone,
728
- target: route53.RecordTarget.fromAlias(new route53Targets.CloudFrontTarget(this.cdk.distribution)),
688
+ zone: this.hostedZone,
689
+ target: RecordTarget.fromAlias(new CloudFrontTarget(this.distribution)),
729
690
  };
730
- new route53.ARecord(this, "AliasRecord", recordProps);
731
- new route53.AaaaRecord(this, "AliasRecordAAAA", recordProps);
691
+ new ARecord(this, "AliasRecord", recordProps);
692
+ new AaaaRecord(this, "AliasRecordAAAA", recordProps);
732
693
  // Create Alias redirect record
733
694
  if (domainAlias) {
734
- new route53Patterns.HttpsRedirect(this, "Redirect", {
735
- zone: this.cdk.hostedZone,
695
+ new HttpsRedirect(this, "Redirect", {
696
+ zone: this.hostedZone,
736
697
  recordNames: [domainAlias],
737
698
  targetDomain: recordName,
738
699
  });
@@ -741,6 +702,24 @@ export class SsrSite extends Construct {
741
702
  /////////////////////
742
703
  // Helper Functions
743
704
  /////////////////////
705
+ getS3ContentReplaceValues() {
706
+ const replaceValues = [];
707
+ Object.entries(this.props.environment || {})
708
+ .filter(([, value]) => Token.isUnresolved(value))
709
+ .forEach(([key, value]) => {
710
+ const token = `{{ ${key} }}`;
711
+ replaceValues.push({
712
+ files: "**/*.html",
713
+ search: token,
714
+ replace: value,
715
+ }, {
716
+ files: "**/*.js",
717
+ search: token,
718
+ replace: value,
719
+ });
720
+ });
721
+ return replaceValues;
722
+ }
744
723
  validateSiteExists() {
745
724
  const { path: sitePath } = this.props;
746
725
  if (!fs.existsSync(sitePath)) {