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.
package/constructs/AstroSite.js
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
|
|
189
|
+
private createRevalidationQueue;
|
|
190
|
+
private createRevalidationTable;
|
|
151
191
|
getConstructMetadata(): {
|
|
152
192
|
data: {
|
|
153
193
|
mode: "placeholder" | "deployed";
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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 {
|
package/constructs/Service.d.ts
CHANGED
|
@@ -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.
|
|
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
|
package/constructs/Service.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sideEffects": false,
|
|
3
3
|
"name": "sst",
|
|
4
|
-
"version": "2.
|
|
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.
|
|
122
|
+
"astro-sst": "2.28.0",
|
|
123
123
|
"tsx": "^3.12.1",
|
|
124
124
|
"typescript": "^5.2.2",
|
|
125
125
|
"vitest": "^0.33.0"
|