sst 2.24.0 → 2.24.2

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.
@@ -167,7 +167,7 @@ export const bind = (program) => program
167
167
  ]);
168
168
  const metadataData = await metadataForStack(ssrSite.stack);
169
169
  const metadata = metadataData
170
- .filter((c) => [
170
+ ?.filter((c) => [
171
171
  "NextjsSite",
172
172
  "AstroSite",
173
173
  "RemixSite",
@@ -198,7 +198,7 @@ export const bind = (program) => program
198
198
  const { metadataForStack } = await import("../../stacks/metadata.js");
199
199
  const metadataData = await metadataForStack(staticSite.stack);
200
200
  const metadata = metadataData
201
- .filter((c) => ["StaticSite", "SlsNextjsSite"].includes(c.type))
201
+ ?.filter((c) => ["StaticSite", "SlsNextjsSite"].includes(c.type))
202
202
  .find((c) => {
203
203
  // metadata prior to SST v2.3.0 doesn't have path
204
204
  if (!c.data.path || !c.data.environment) {
@@ -224,7 +224,7 @@ export const bind = (program) => program
224
224
  // Get metadata
225
225
  const metadataData = await metadataForStack(service.stack);
226
226
  const metadata = metadataData
227
- .filter((c) => ["Service"].includes(c.type))
227
+ ?.filter((c) => ["Service"].includes(c.type))
228
228
  .find((c) => {
229
229
  return (path.resolve(project.paths.root, c.data.path) === process.cwd());
230
230
  });
@@ -242,6 +242,28 @@ export interface ServiceProps {
242
242
  url?: string;
243
243
  };
244
244
  cdk?: {
245
+ /**
246
+ * By default, SST creates a CloudFront distribution. Set this to `false` to skip creating the distribution.
247
+ * @default true
248
+ * @example
249
+ * ```js
250
+ * {
251
+ * cloudfrontDistribution: false
252
+ * }
253
+ * ```
254
+ */
255
+ cloudfrontDistribution?: boolean;
256
+ /**
257
+ * By default, SST creates an Application Load Balancer to distribute requests across containers. Set this to `false` to skip creating the load balancer.
258
+ * @default true
259
+ * @example
260
+ * ```js
261
+ * {
262
+ * applicationLoadBalancer: false
263
+ * }
264
+ * ```
265
+ */
266
+ applicationLoadBalancer?: boolean;
245
267
  /**
246
268
  * Customizing the container definition for the ECS task.
247
269
  * @example
@@ -305,7 +327,7 @@ export declare class Service extends Construct implements SSTConstruct {
305
327
  private cluster;
306
328
  private container;
307
329
  private taskDefinition;
308
- private distribution;
330
+ private distribution?;
309
331
  constructor(scope: Construct, id: string, props?: ServiceProps);
310
332
  /**
311
333
  * The CloudFront URL of the website.
@@ -322,7 +344,7 @@ export declare class Service extends Construct implements SSTConstruct {
322
344
  get cdk(): {
323
345
  vpc: IVpc;
324
346
  cluster: Cluster;
325
- distribution: import("aws-cdk-lib/aws-cloudfront").IDistribution;
347
+ distribution: import("aws-cdk-lib/aws-cloudfront").IDistribution | undefined;
326
348
  hostedZone: import("aws-cdk-lib/aws-route53").IHostedZone | undefined;
327
349
  certificate: import("aws-cdk-lib/aws-certificatemanager").ICertificate | undefined;
328
350
  } | undefined;
@@ -206,7 +206,7 @@ export class Service extends Construct {
206
206
  this.updateContainerImage(dockerfile, taskDefinition, container);
207
207
  }
208
208
  // Invalidate CloudFront
209
- this.distribution.createInvalidation();
209
+ this.distribution?.createInvalidation();
210
210
  });
211
211
  }
212
212
  /////////////////////
@@ -218,7 +218,7 @@ export class Service extends Construct {
218
218
  get url() {
219
219
  if (this.doNotDeploy)
220
220
  return this.props.dev?.url;
221
- return this.distribution.url;
221
+ return this.distribution?.url;
222
222
  }
223
223
  /**
224
224
  * If the custom domain is enabled, this is the URL of the website with the
@@ -227,7 +227,7 @@ export class Service extends Construct {
227
227
  get customDomainUrl() {
228
228
  if (this.doNotDeploy)
229
229
  return;
230
- return this.distribution.customDomainUrl;
230
+ return this.distribution?.customDomainUrl;
231
231
  }
232
232
  /**
233
233
  * The internally created CDK resources.
@@ -238,9 +238,9 @@ export class Service extends Construct {
238
238
  return {
239
239
  vpc: this.vpc,
240
240
  cluster: this.cluster,
241
- distribution: this.distribution.cdk.distribution,
242
- hostedZone: this.distribution.cdk.hostedZone,
243
- certificate: this.distribution.cdk.certificate,
241
+ distribution: this.distribution?.cdk.distribution,
242
+ hostedZone: this.distribution?.cdk.hostedZone,
243
+ certificate: this.distribution?.cdk.certificate,
244
244
  };
245
245
  }
246
246
  /////////////////////
@@ -268,29 +268,35 @@ export class Service extends Construct {
268
268
  /** @internal */
269
269
  getFunctionBinding() {
270
270
  const app = this.node.root;
271
- return {
272
- clientPackage: "service",
273
- variables: {
274
- url: this.doNotDeploy
275
- ? {
276
- type: "plain",
277
- value: this.props.dev?.url ?? "localhost",
278
- }
279
- : {
280
- // Do not set real value b/c we don't want to make the Lambda function
281
- // depend on the Site. B/c often the site depends on the Api, causing
282
- // a CloudFormation circular dependency if the Api and the Site belong
283
- // to different stacks.
284
- type: "site_url",
285
- value: this.customDomainUrl || this.url,
286
- },
287
- },
288
- permissions: {
289
- "ssm:GetParameters": [
290
- `arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
291
- ],
292
- },
293
- };
271
+ return this.distribution
272
+ ? {
273
+ clientPackage: "service",
274
+ variables: {
275
+ url: this.doNotDeploy
276
+ ? {
277
+ type: "plain",
278
+ value: this.props.dev?.url ?? "localhost",
279
+ }
280
+ : {
281
+ // Do not set real value b/c we don't want to make the Lambda function
282
+ // depend on the Site. B/c often the site depends on the Api, causing
283
+ // a CloudFormation circular dependency if the Api and the Site belong
284
+ // to different stacks.
285
+ type: "site_url",
286
+ value: this.customDomainUrl || this.url,
287
+ },
288
+ },
289
+ permissions: {
290
+ "ssm:GetParameters": [
291
+ `arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
292
+ ],
293
+ },
294
+ }
295
+ : {
296
+ clientPackage: "service",
297
+ variables: {},
298
+ permissions: {},
299
+ };
294
300
  }
295
301
  /**
296
302
  * Binds additional resources to service.
@@ -404,6 +410,11 @@ export class Service extends Construct {
404
410
  return { cluster, taskDefinition, container, service };
405
411
  }
406
412
  createLoadBalancer(vpc, service) {
413
+ const { cdk } = this.props;
414
+ // Do not create load balancer if disabled
415
+ if (cdk?.applicationLoadBalancer === false) {
416
+ return {};
417
+ }
407
418
  const alb = new ApplicationLoadBalancer(this, "LoadBalancer", {
408
419
  vpc,
409
420
  internetFacing: true,
@@ -429,13 +440,18 @@ export class Service extends Construct {
429
440
  targetUtilizationPercent: memoryUtilization ?? 70,
430
441
  scaleOutCooldown: CdkDuration.seconds(300),
431
442
  });
432
- scaling.scaleOnRequestCount("RequestScaling", {
433
- requestsPerTarget: requestsPerContainer ?? 500,
434
- targetGroup: target,
435
- });
443
+ if (target) {
444
+ scaling.scaleOnRequestCount("RequestScaling", {
445
+ requestsPerTarget: requestsPerContainer ?? 500,
446
+ targetGroup: target,
447
+ });
448
+ }
436
449
  }
437
450
  createDistribution(alb) {
438
- const { customDomain } = this.props;
451
+ const { cdk, customDomain } = this.props;
452
+ // Do not create distribution if disabled or if ALB was not created (ie. disabled)
453
+ if (!alb || cdk?.cloudfrontDistribution === false)
454
+ return;
439
455
  const cachePolicy = new CachePolicy(this, "CachePolicy", {
440
456
  queryStringBehavior: CacheQueryStringBehavior.all(),
441
457
  headerBehavior: CacheHeaderBehavior.none(),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.24.0",
4
+ "version": "2.24.2",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },
@@ -6,6 +6,6 @@ declare module "../bus.js" {
6
6
  "stacks.metadata.deleted": {};
7
7
  }
8
8
  }
9
- export declare function metadataForStack(stack: String): Promise<Metadata[]>;
9
+ export declare function metadataForStack(stack: String): Promise<Metadata[] | undefined>;
10
10
  export declare function metadata(): Promise<Record<string, Metadata[]>>;
11
11
  export declare const useMetadata: () => Promise<Record<string, Metadata[]>>;
@@ -16,12 +16,18 @@ export async function metadataForStack(stack) {
16
16
  region: project.config.region,
17
17
  credentials: credentials,
18
18
  });
19
- const result = await s3.send(new GetObjectCommand({
20
- Key: `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/stack.${stack}.json`,
21
- Bucket: bootstrap.bucket,
22
- }));
23
- const body = await result.Body.transformToString();
24
- return JSON.parse(body);
19
+ try {
20
+ const result = await s3.send(new GetObjectCommand({
21
+ Key: `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/stack.${stack}.json`,
22
+ Bucket: bootstrap.bucket,
23
+ }));
24
+ const body = await result.Body.transformToString();
25
+ return JSON.parse(body);
26
+ }
27
+ catch (e) {
28
+ Logger.debug(`Fetching metadata for stack ${stack} failed`, e);
29
+ return;
30
+ }
25
31
  }
26
32
  export async function metadata() {
27
33
  Logger.debug("Fetching all metadata");