sst 2.27.0 → 2.28.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.
@@ -1,8 +1,8 @@
1
1
  import { readFileSync, existsSync, readdirSync, statSync } from "fs";
2
2
  import { join } from "path";
3
- import { BUILD_META_FILE_NAME } from "astro-sst/build-meta";
4
3
  import { SsrSite, } from "./SsrSite.js";
5
4
  import { AllowedMethods } from "aws-cdk-lib/aws-cloudfront";
5
+ const BUILD_META_FILE_NAME = "sst.buildMeta.json";
6
6
  /**
7
7
  * The `AstroSite` construct is a higher level CDK construct that makes it easy to create a Astro app.
8
8
  * @example
@@ -10,11 +10,49 @@ export interface NextjsSiteProps extends Omit<SsrSiteProps, "nodejs"> {
10
10
  * @default 1024 MB
11
11
  * @example
12
12
  * ```js
13
- * memorySize: "512 MB",
13
+ * imageOptimization: {
14
+ * memorySize: "512 MB",
15
+ * }
14
16
  * ```
15
17
  */
16
18
  memorySize?: number | Size;
17
19
  };
20
+ experimental?: {
21
+ /**
22
+ * Enable streaming. Currently an experimental feature in OpenNext.
23
+ * @default false
24
+ * @example
25
+ * ```js
26
+ * experimental: {
27
+ * streaming: true,
28
+ * }
29
+ * ```
30
+ */
31
+ streaming?: boolean;
32
+ /**
33
+ * Disabling incremental cache will cause the entire page to be revalidated on each request. This can result in ISR and SSG pages to be in an inconsistent state. Specify this option if you are using SSR pages only.
34
+ *
35
+ * Note that it is possible to disable incremental cache while leaving on-demand revalidation enabled.
36
+ * @default false
37
+ * @example
38
+ * ```js
39
+ * experimental: {
40
+ * disableIncrementalCache: true,
41
+ * }
42
+ */
43
+ disableIncrementalCache?: boolean;
44
+ /**
45
+ * Disabling DynamoDB cache will cause on-demand revalidation by path (`revalidatePath`) and by cache tag (`revalidateTag`) to fail silently.
46
+ * @default false
47
+ * @example
48
+ * ```js
49
+ * experimental: {
50
+ * disableDynamoDBCache: true,
51
+ * }
52
+ * ```
53
+ */
54
+ disableDynamoDBCache?: boolean;
55
+ };
18
56
  cdk?: SsrSiteProps["cdk"] & {
19
57
  revalidation?: Pick<FunctionProps, "vpc" | "vpcSubnets">;
20
58
  /**
@@ -129,6 +167,7 @@ export declare class NextjsSite extends SsrSite {
129
167
  CACHE_BUCKET_REGION: string;
130
168
  };
131
169
  };
170
+ streaming: boolean | undefined;
132
171
  } | undefined;
133
172
  };
134
173
  behaviors: {
@@ -147,7 +186,8 @@ export declare class NextjsSite extends SsrSite {
147
186
  schedule?: import("aws-cdk-lib/aws-events").Schedule | undefined;
148
187
  } | undefined;
149
188
  };
150
- protected createRevalidation(): void;
189
+ private createRevalidationQueue;
190
+ private createRevalidationTable;
151
191
  getConstructMetadata(): {
152
192
  data: {
153
193
  mode: "placeholder" | "deployed";
@@ -1,12 +1,16 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { Duration as CdkDuration } from "aws-cdk-lib/core";
3
+ import { Duration as CdkDuration, RemovalPolicy, CustomResource, } from "aws-cdk-lib/core";
4
4
  import { Code, Runtime, Function as CdkFunction, Architecture, } from "aws-cdk-lib/aws-lambda";
5
+ import { AttributeType, Billing, TableV2 as Table, } from "aws-cdk-lib/aws-dynamodb";
6
+ import { Provider } from "aws-cdk-lib/custom-resources";
5
7
  import { Queue } from "aws-cdk-lib/aws-sqs";
6
8
  import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
7
9
  import { Stack } from "./Stack.js";
8
10
  import { SsrSite } from "./SsrSite.js";
9
11
  import { toCdkSize } from "./util/size.js";
12
+ import { PolicyStatement } from "aws-cdk-lib/aws-iam";
13
+ import { RetentionDays } from "aws-cdk-lib/aws-logs";
10
14
  /**
11
15
  * The `NextjsSite` construct is a higher level CDK construct that makes it easy to create a Next.js app.
12
16
  * @example
@@ -20,14 +24,34 @@ import { toCdkSize } from "./util/size.js";
20
24
  */
21
25
  export class NextjsSite extends SsrSite {
22
26
  constructor(scope, id, props) {
27
+ const { streaming, disableDynamoDBCache, disableIncrementalCache } = {
28
+ streaming: false,
29
+ disableDynamoDBCache: false,
30
+ disableIncrementalCache: false,
31
+ ...props?.experimental,
32
+ };
23
33
  super(scope, id, {
24
- buildCommand: "npx --yes open-next@2.1.5 build",
34
+ buildCommand: [
35
+ "npx --yes open-next@2.2.1 build",
36
+ ...(streaming ? ["--streaming"] : []),
37
+ ...(disableDynamoDBCache
38
+ ? ["--dangerously-disable-dynamodb-cache"]
39
+ : []),
40
+ ...(disableIncrementalCache
41
+ ? ["--dangerously-disable-incremental-cache"]
42
+ : []),
43
+ ].join(" "),
25
44
  ...props,
26
45
  });
27
- this.createRevalidation();
46
+ if (!disableIncrementalCache) {
47
+ this.createRevalidationQueue();
48
+ if (!disableDynamoDBCache) {
49
+ this.createRevalidationTable();
50
+ }
51
+ }
28
52
  }
29
53
  plan(bucket) {
30
- const { path: sitePath, edge, imageOptimization } = this.props;
54
+ const { path: sitePath, edge, experimental, imageOptimization, } = this.props;
31
55
  const serverConfig = {
32
56
  description: "Next.js server",
33
57
  bundle: path.join(sitePath, ".open-next", "server-function"),
@@ -61,6 +85,7 @@ export class NextjsSite extends SsrSite {
61
85
  type: "function",
62
86
  constructId: "ServerFunction",
63
87
  function: serverConfig,
88
+ streaming: experimental?.streaming,
64
89
  },
65
90
  }),
66
91
  imageOptimizer: {
@@ -172,10 +197,11 @@ export class NextjsSite extends SsrSite {
172
197
  },
173
198
  });
174
199
  }
175
- createRevalidation() {
200
+ createRevalidationQueue() {
176
201
  if (!this.serverFunction)
177
202
  return;
178
203
  const { cdk } = this.props;
204
+ const server = this.serverFunction;
179
205
  const queue = new Queue(this, "RevalidationQueue", {
180
206
  fifo: true,
181
207
  receiveMessageWaitTime: CdkDuration.seconds(20),
@@ -190,10 +216,64 @@ export class NextjsSite extends SsrSite {
190
216
  });
191
217
  consumer.addEventSource(new SqsEventSource(queue, { batchSize: 5 }));
192
218
  // Allow server to send messages to the queue
219
+ server.addEnvironment("REVALIDATION_QUEUE_URL", queue.queueUrl);
220
+ server.addEnvironment("REVALIDATION_QUEUE_REGION", Stack.of(this).region);
221
+ queue.grantSendMessages(server.role);
222
+ }
223
+ createRevalidationTable() {
224
+ if (!this.serverFunction)
225
+ return;
226
+ const { path: sitePath } = this.props;
193
227
  const server = this.serverFunction;
194
- server?.addEnvironment("REVALIDATION_QUEUE_URL", queue.queueUrl);
195
- server?.addEnvironment("REVALIDATION_QUEUE_REGION", Stack.of(this).region);
196
- queue.grantSendMessages(server?.role);
228
+ const table = new Table(this, "RevalidationTable", {
229
+ partitionKey: { name: "tag", type: AttributeType.STRING },
230
+ sortKey: { name: "path", type: AttributeType.STRING },
231
+ pointInTimeRecovery: true,
232
+ billing: Billing.onDemand(),
233
+ globalSecondaryIndexes: [
234
+ {
235
+ indexName: "revalidate",
236
+ partitionKey: { name: "path", type: AttributeType.STRING },
237
+ sortKey: { name: "revalidatedAt", type: AttributeType.NUMBER },
238
+ },
239
+ ],
240
+ removalPolicy: RemovalPolicy.DESTROY,
241
+ });
242
+ server?.addEnvironment("CACHE_DYNAMO_TABLE", table.tableName);
243
+ table.grantReadWriteData(server.role);
244
+ const dynamodbProviderPath = path.join(sitePath, ".open-next", "dynamodb-provider");
245
+ if (fs.existsSync(dynamodbProviderPath)) {
246
+ const insertFn = new CdkFunction(this, "RevalidationInsertFunction", {
247
+ description: "Next.js revalidation data insert",
248
+ handler: "index.handler",
249
+ code: Code.fromAsset(dynamodbProviderPath),
250
+ runtime: Runtime.NODEJS_18_X,
251
+ timeout: CdkDuration.minutes(15),
252
+ initialPolicy: [
253
+ new PolicyStatement({
254
+ actions: [
255
+ "dynamodb:BatchWriteItem",
256
+ "dynamodb:PutItem",
257
+ "dynamodb:DescribeTable",
258
+ ],
259
+ resources: [table.tableArn],
260
+ }),
261
+ ],
262
+ environment: {
263
+ CACHE_DYNAMO_TABLE: table.tableName,
264
+ },
265
+ });
266
+ const provider = new Provider(this, "RevalidationProvider", {
267
+ onEventHandler: insertFn,
268
+ logRetention: RetentionDays.ONE_DAY,
269
+ });
270
+ new CustomResource(this, "RevalidationResource", {
271
+ serviceToken: provider.serviceToken,
272
+ properties: {
273
+ version: Date.now().toString(),
274
+ },
275
+ });
276
+ }
197
277
  }
198
278
  getConstructMetadata() {
199
279
  return {
@@ -1,4 +1,5 @@
1
1
  import { Construct } from "constructs";
2
+ import { DistributionProps } from "aws-cdk-lib/aws-cloudfront";
2
3
  import { DistributionDomainProps } from "./Distribution.js";
3
4
  import { SSTConstruct } from "./Construct.js";
4
5
  import { Permissions } from "./util/permission.js";
@@ -18,6 +19,8 @@ declare const supportedCpus: {
18
19
  };
19
20
  export interface ServiceDomainProps extends DistributionDomainProps {
20
21
  }
22
+ export interface ServiceCdkDistributionProps extends Omit<DistributionProps, "defaultBehavior"> {
23
+ }
21
24
  export interface ServiceProps {
22
25
  /**
23
26
  * Path to the directory where the app is located.
@@ -272,7 +275,7 @@ export interface ServiceProps {
272
275
  };
273
276
  cdk?: {
274
277
  /**
275
- * By default, SST creates a CloudFront distribution. Set this to `false` to skip creating the distribution.
278
+ * By default, SST creates a CloudFront distribution. Pass in a value to override the default settings this construct uses to create the CDK `Distribution` internally. Alternatively, set this to `false` to skip creating the distribution.
276
279
  * @default true
277
280
  * @example
278
281
  * ```js
@@ -283,7 +286,7 @@ export interface ServiceProps {
283
286
  * }
284
287
  * ```
285
288
  */
286
- cloudfrontDistribution?: boolean;
289
+ cloudfrontDistribution?: boolean | ServiceCdkDistributionProps;
287
290
  /**
288
291
  * By default, SST creates an Application Load Balancer to distribute requests across containers. Set this to `false` to skip creating the load balancer.
289
292
  * @default true
@@ -517,6 +517,9 @@ export class Service extends Construct {
517
517
  cachePolicy,
518
518
  originRequestPolicy: OriginRequestPolicy.ALL_VIEWER,
519
519
  },
520
+ ...(cdk?.cloudfrontDistribution === true
521
+ ? {}
522
+ : cdk?.cloudfrontDistribution),
520
523
  },
521
524
  },
522
525
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.27.0",
4
+ "version": "2.28.0",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },
@@ -119,7 +119,7 @@
119
119
  "@types/ws": "^8.5.3",
120
120
  "@types/yargs": "^17.0.13",
121
121
  "archiver": "^5.3.1",
122
- "astro-sst": "2.27.0",
122
+ "astro-sst": "2.28.0",
123
123
  "tsx": "^3.12.1",
124
124
  "typescript": "^5.2.2",
125
125
  "vitest": "^0.33.0"