sst 2.30.3 → 2.31.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/BaseSite.d.ts +2 -13
- package/constructs/NextjsSite.d.ts +144 -18
- package/constructs/NextjsSite.js +120 -28
- package/constructs/RDS.js +2 -2
- package/constructs/SsrSite.d.ts +19 -73
- package/constructs/SsrSite.js +93 -205
- package/constructs/StaticSite.d.ts +46 -33
- package/constructs/StaticSite.js +57 -74
- package/constructs/deprecated/NextjsSite.js +57 -71
- package/package.json +5 -4
- package/support/base-site-archiver.mjs +18 -18
- package/support/custom-resources/index.mjs +8426 -383
- package/support/base-site-custom-resource/s3-handler.py +0 -195
- package/support/base-site-custom-resource/s3-upload.py +0 -89
package/constructs/BaseSite.d.ts
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
import { ErrorResponse, DistributionProps, BehaviorOptions, IOrigin } from "aws-cdk-lib/aws-cloudfront";
|
|
2
|
-
export interface BaseSiteFileOptionsFilter {
|
|
3
|
-
include?: string;
|
|
4
|
-
exclude?: string;
|
|
5
|
-
}
|
|
6
2
|
export interface BaseSiteFileOptions {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
contentType?: string;
|
|
10
|
-
contentEncoding?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface BaseSiteFileOptionsDeprecated {
|
|
13
|
-
include?: string | string[];
|
|
14
|
-
exclude?: string | string[];
|
|
3
|
+
files: string | string[];
|
|
4
|
+
ignore?: string | string[];
|
|
15
5
|
cacheControl?: string;
|
|
16
6
|
contentType?: string;
|
|
17
|
-
contentEncoding?: string;
|
|
18
7
|
}
|
|
19
8
|
export interface BaseSiteEnvironmentOutputsInfo {
|
|
20
9
|
path: string;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
|
+
import { Duration as CdkDuration } from "aws-cdk-lib/core";
|
|
2
3
|
import { Runtime, FunctionProps, Architecture } from "aws-cdk-lib/aws-lambda";
|
|
3
4
|
import { SsrSite, SsrSiteNormalizedProps, SsrSiteProps } from "./SsrSite.js";
|
|
4
5
|
import { Size } from "./util/size.js";
|
|
5
6
|
import { Bucket } from "aws-cdk-lib/aws-s3";
|
|
7
|
+
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
8
|
+
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
6
9
|
import { CachePolicyProps } from "aws-cdk-lib/aws-cloudfront";
|
|
7
10
|
export interface NextjsSiteProps extends Omit<SsrSiteProps, "nodejs"> {
|
|
8
11
|
/**
|
|
@@ -14,6 +17,17 @@ export interface NextjsSiteProps extends Omit<SsrSiteProps, "nodejs"> {
|
|
|
14
17
|
* ```
|
|
15
18
|
*/
|
|
16
19
|
openNextVersion?: string;
|
|
20
|
+
/**
|
|
21
|
+
* How the logs are stored in CloudWatch
|
|
22
|
+
* - "combined" - Logs from all routes are stored in the same log group.
|
|
23
|
+
* - "per-route" - Logs from each route are stored in a separate log group.
|
|
24
|
+
* @default "combined"
|
|
25
|
+
* @example
|
|
26
|
+
* ```js
|
|
27
|
+
* logging: "per-route",
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
logging?: "combined" | "per-route";
|
|
17
31
|
imageOptimization?: {
|
|
18
32
|
/**
|
|
19
33
|
* The amount of memory in MB allocated for image optimization function.
|
|
@@ -109,6 +123,7 @@ type NextjsSiteNormalizedProps = NextjsSiteProps & SsrSiteNormalizedProps;
|
|
|
109
123
|
*/
|
|
110
124
|
export declare class NextjsSite extends SsrSite {
|
|
111
125
|
props: NextjsSiteNormalizedProps;
|
|
126
|
+
private routes?;
|
|
112
127
|
constructor(scope: Construct, id: string, props?: NextjsSiteProps);
|
|
113
128
|
static buildDefaultServerCachePolicyProps(): CachePolicyProps;
|
|
114
129
|
protected plan(bucket: Bucket): {
|
|
@@ -122,14 +137,64 @@ export declare class NextjsSite extends SsrSite {
|
|
|
122
137
|
edgeServer: {
|
|
123
138
|
constructId: string;
|
|
124
139
|
function: {
|
|
125
|
-
|
|
126
|
-
bundle: string;
|
|
140
|
+
layers: import("aws-cdk-lib/aws-lambda").ILayerVersion[] | undefined;
|
|
127
141
|
handler: string;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
142
|
+
bundle?: string | undefined;
|
|
143
|
+
runtime?: "nodejs14.x" | "nodejs16.x" | "nodejs18.x" | undefined;
|
|
144
|
+
timeout?: number | `${number} second` | `${number} seconds` | `${number} minute` | `${number} minutes` | `${number} hour` | `${number} hours` | `${number} day` | `${number} days` | undefined;
|
|
145
|
+
memorySize?: number | `${number} MB` | `${number} GB` | undefined;
|
|
146
|
+
permissions?: import("./index.js").Permissions | undefined;
|
|
147
|
+
environment?: Record<string, string> | undefined;
|
|
148
|
+
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
149
|
+
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
150
|
+
copyFiles?: import("./Function.js").FunctionCopyFilesProps[] | undefined;
|
|
151
|
+
logRetention?: RetentionDays | undefined;
|
|
152
|
+
functionName?: string | undefined;
|
|
153
|
+
tracing?: import("aws-cdk-lib/aws-lambda").Tracing | undefined;
|
|
154
|
+
architecture?: Architecture | undefined;
|
|
155
|
+
description?: string | undefined;
|
|
156
|
+
ephemeralStorageSize?: import("aws-cdk-lib/core").Size | undefined;
|
|
157
|
+
initialPolicy?: PolicyStatement[] | undefined;
|
|
158
|
+
role?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
159
|
+
vpc?: import("aws-cdk-lib/aws-ec2").IVpc | undefined;
|
|
160
|
+
vpcSubnets?: import("aws-cdk-lib/aws-ec2").SubnetSelection | undefined;
|
|
161
|
+
securityGroups?: import("aws-cdk-lib/aws-ec2").ISecurityGroup[] | undefined;
|
|
162
|
+
allowAllOutbound?: boolean | undefined;
|
|
163
|
+
deadLetterQueueEnabled?: boolean | undefined;
|
|
164
|
+
deadLetterQueue?: import("aws-cdk-lib/aws-sqs").IQueue | undefined;
|
|
165
|
+
deadLetterTopic?: import("aws-cdk-lib/aws-sns").ITopic | undefined;
|
|
166
|
+
snapStart?: import("aws-cdk-lib/aws-lambda").SnapStartConf | undefined;
|
|
167
|
+
profiling?: boolean | undefined;
|
|
168
|
+
profilingGroup?: import("aws-cdk-lib/aws-codeguruprofiler").IProfilingGroup | undefined;
|
|
169
|
+
insightsVersion?: import("aws-cdk-lib/aws-lambda").LambdaInsightsVersion | undefined;
|
|
170
|
+
adotInstrumentation?: import("aws-cdk-lib/aws-lambda").AdotInstrumentationConfig | undefined;
|
|
171
|
+
paramsAndSecrets?: import("aws-cdk-lib/aws-lambda").ParamsAndSecretsLayerVersion | undefined;
|
|
172
|
+
reservedConcurrentExecutions?: number | undefined;
|
|
173
|
+
events?: import("aws-cdk-lib/aws-lambda").IEventSource[] | undefined;
|
|
174
|
+
logRetentionRole?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
175
|
+
logRetentionRetryOptions?: import("aws-cdk-lib/aws-lambda").LogRetentionRetryOptions | undefined;
|
|
176
|
+
currentVersionOptions?: import("aws-cdk-lib/aws-lambda").VersionOptions | undefined;
|
|
177
|
+
filesystem?: import("aws-cdk-lib/aws-lambda").FileSystem | undefined;
|
|
178
|
+
allowPublicSubnet?: boolean | undefined;
|
|
179
|
+
environmentEncryption?: import("aws-cdk-lib/aws-kms").IKey | undefined;
|
|
180
|
+
codeSigningConfig?: import("aws-cdk-lib/aws-lambda").ICodeSigningConfig | undefined;
|
|
181
|
+
runtimeManagementMode?: import("aws-cdk-lib/aws-lambda").RuntimeManagementMode | undefined;
|
|
182
|
+
onFailure?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
183
|
+
onSuccess?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
184
|
+
maxEventAge?: CdkDuration | undefined;
|
|
185
|
+
retryAttempts?: number | undefined;
|
|
186
|
+
} | {
|
|
187
|
+
layers: import("aws-cdk-lib/aws-lambda").ILayerVersion[] | undefined;
|
|
188
|
+
handler: string;
|
|
189
|
+
bundle?: string | undefined;
|
|
190
|
+
runtime?: "nodejs14.x" | "nodejs16.x" | "nodejs18.x" | undefined;
|
|
191
|
+
timeout?: number | `${number} second` | `${number} seconds` | `${number} minute` | `${number} minutes` | `${number} hour` | `${number} hours` | `${number} day` | `${number} days` | undefined;
|
|
192
|
+
memorySize?: number | `${number} MB` | `${number} GB` | undefined;
|
|
193
|
+
permissions?: import("./index.js").Permissions | undefined;
|
|
194
|
+
environment?: Record<string, string> | undefined;
|
|
195
|
+
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
196
|
+
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
197
|
+
scopeOverride?: import("constructs").IConstruct | undefined;
|
|
133
198
|
};
|
|
134
199
|
};
|
|
135
200
|
} | undefined;
|
|
@@ -169,14 +234,64 @@ export declare class NextjsSite extends SsrSite {
|
|
|
169
234
|
type: "function";
|
|
170
235
|
constructId: string;
|
|
171
236
|
function: {
|
|
172
|
-
|
|
173
|
-
bundle: string;
|
|
237
|
+
layers: import("aws-cdk-lib/aws-lambda").ILayerVersion[] | undefined;
|
|
174
238
|
handler: string;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
239
|
+
bundle?: string | undefined;
|
|
240
|
+
runtime?: "nodejs14.x" | "nodejs16.x" | "nodejs18.x" | undefined;
|
|
241
|
+
timeout?: number | `${number} second` | `${number} seconds` | `${number} minute` | `${number} minutes` | `${number} hour` | `${number} hours` | `${number} day` | `${number} days` | undefined;
|
|
242
|
+
memorySize?: number | `${number} MB` | `${number} GB` | undefined;
|
|
243
|
+
permissions?: import("./index.js").Permissions | undefined;
|
|
244
|
+
environment?: Record<string, string> | undefined;
|
|
245
|
+
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
246
|
+
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
247
|
+
copyFiles?: import("./Function.js").FunctionCopyFilesProps[] | undefined;
|
|
248
|
+
logRetention?: RetentionDays | undefined;
|
|
249
|
+
functionName?: string | undefined;
|
|
250
|
+
tracing?: import("aws-cdk-lib/aws-lambda").Tracing | undefined;
|
|
251
|
+
architecture?: Architecture | undefined;
|
|
252
|
+
description?: string | undefined;
|
|
253
|
+
ephemeralStorageSize?: import("aws-cdk-lib/core").Size | undefined;
|
|
254
|
+
initialPolicy?: PolicyStatement[] | undefined;
|
|
255
|
+
role?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
256
|
+
vpc?: import("aws-cdk-lib/aws-ec2").IVpc | undefined;
|
|
257
|
+
vpcSubnets?: import("aws-cdk-lib/aws-ec2").SubnetSelection | undefined;
|
|
258
|
+
securityGroups?: import("aws-cdk-lib/aws-ec2").ISecurityGroup[] | undefined;
|
|
259
|
+
allowAllOutbound?: boolean | undefined;
|
|
260
|
+
deadLetterQueueEnabled?: boolean | undefined;
|
|
261
|
+
deadLetterQueue?: import("aws-cdk-lib/aws-sqs").IQueue | undefined;
|
|
262
|
+
deadLetterTopic?: import("aws-cdk-lib/aws-sns").ITopic | undefined;
|
|
263
|
+
snapStart?: import("aws-cdk-lib/aws-lambda").SnapStartConf | undefined;
|
|
264
|
+
profiling?: boolean | undefined;
|
|
265
|
+
profilingGroup?: import("aws-cdk-lib/aws-codeguruprofiler").IProfilingGroup | undefined;
|
|
266
|
+
insightsVersion?: import("aws-cdk-lib/aws-lambda").LambdaInsightsVersion | undefined;
|
|
267
|
+
adotInstrumentation?: import("aws-cdk-lib/aws-lambda").AdotInstrumentationConfig | undefined;
|
|
268
|
+
paramsAndSecrets?: import("aws-cdk-lib/aws-lambda").ParamsAndSecretsLayerVersion | undefined;
|
|
269
|
+
reservedConcurrentExecutions?: number | undefined;
|
|
270
|
+
events?: import("aws-cdk-lib/aws-lambda").IEventSource[] | undefined;
|
|
271
|
+
logRetentionRole?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
272
|
+
logRetentionRetryOptions?: import("aws-cdk-lib/aws-lambda").LogRetentionRetryOptions | undefined;
|
|
273
|
+
currentVersionOptions?: import("aws-cdk-lib/aws-lambda").VersionOptions | undefined;
|
|
274
|
+
filesystem?: import("aws-cdk-lib/aws-lambda").FileSystem | undefined;
|
|
275
|
+
allowPublicSubnet?: boolean | undefined;
|
|
276
|
+
environmentEncryption?: import("aws-cdk-lib/aws-kms").IKey | undefined;
|
|
277
|
+
codeSigningConfig?: import("aws-cdk-lib/aws-lambda").ICodeSigningConfig | undefined;
|
|
278
|
+
runtimeManagementMode?: import("aws-cdk-lib/aws-lambda").RuntimeManagementMode | undefined;
|
|
279
|
+
onFailure?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
280
|
+
onSuccess?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
281
|
+
maxEventAge?: CdkDuration | undefined;
|
|
282
|
+
retryAttempts?: number | undefined;
|
|
283
|
+
} | {
|
|
284
|
+
layers: import("aws-cdk-lib/aws-lambda").ILayerVersion[] | undefined;
|
|
285
|
+
handler: string;
|
|
286
|
+
bundle?: string | undefined;
|
|
287
|
+
runtime?: "nodejs14.x" | "nodejs16.x" | "nodejs18.x" | undefined;
|
|
288
|
+
timeout?: number | `${number} second` | `${number} seconds` | `${number} minute` | `${number} minutes` | `${number} hour` | `${number} hours` | `${number} day` | `${number} days` | undefined;
|
|
289
|
+
memorySize?: number | `${number} MB` | `${number} GB` | undefined;
|
|
290
|
+
permissions?: import("./index.js").Permissions | undefined;
|
|
291
|
+
environment?: Record<string, string> | undefined;
|
|
292
|
+
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
293
|
+
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
294
|
+
scopeOverride?: import("constructs").IConstruct | undefined;
|
|
180
295
|
};
|
|
181
296
|
streaming: boolean | undefined;
|
|
182
297
|
} | undefined;
|
|
@@ -203,8 +318,12 @@ export declare class NextjsSite extends SsrSite {
|
|
|
203
318
|
type: "NextjsSite";
|
|
204
319
|
data: {
|
|
205
320
|
routes: {
|
|
206
|
-
|
|
207
|
-
|
|
321
|
+
logGroupPrefix: string;
|
|
322
|
+
data: {
|
|
323
|
+
route: string;
|
|
324
|
+
logGroupPath: string;
|
|
325
|
+
}[];
|
|
326
|
+
} | undefined;
|
|
208
327
|
mode: "placeholder" | "deployed";
|
|
209
328
|
path: string;
|
|
210
329
|
runtime: "nodejs14.x" | "nodejs16.x" | "nodejs18.x";
|
|
@@ -215,8 +334,15 @@ export declare class NextjsSite extends SsrSite {
|
|
|
215
334
|
secrets: string[];
|
|
216
335
|
};
|
|
217
336
|
};
|
|
218
|
-
private
|
|
219
|
-
private
|
|
337
|
+
private wrapServerFunction;
|
|
338
|
+
private useRoutes;
|
|
220
339
|
private getBuildId;
|
|
340
|
+
private isPerRouteLoggingEnabled;
|
|
341
|
+
private disableDefaultLogging;
|
|
342
|
+
private static buildCloudWatchRouteName;
|
|
343
|
+
private static buildCloudWatchRouteHash;
|
|
344
|
+
static _test: {
|
|
345
|
+
buildCloudWatchRouteName: typeof NextjsSite.buildCloudWatchRouteName;
|
|
346
|
+
};
|
|
221
347
|
}
|
|
222
348
|
export {};
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import crypto from "crypto";
|
|
3
4
|
import { Duration as CdkDuration, RemovalPolicy, CustomResource, } from "aws-cdk-lib/core";
|
|
4
|
-
import { Code, Runtime, Function as CdkFunction, Architecture, } from "aws-cdk-lib/aws-lambda";
|
|
5
|
+
import { Code, Runtime, Function as CdkFunction, Architecture, LayerVersion, } from "aws-cdk-lib/aws-lambda";
|
|
5
6
|
import { AttributeType, Billing, TableV2 as Table, } from "aws-cdk-lib/aws-dynamodb";
|
|
6
7
|
import { Provider } from "aws-cdk-lib/custom-resources";
|
|
7
8
|
import { Queue } from "aws-cdk-lib/aws-sqs";
|
|
@@ -9,9 +10,10 @@ import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
|
9
10
|
import { Stack } from "./Stack.js";
|
|
10
11
|
import { SsrSite } from "./SsrSite.js";
|
|
11
12
|
import { toCdkSize } from "./util/size.js";
|
|
12
|
-
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
13
|
+
import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
13
14
|
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
14
15
|
import { VisibleError } from "../error.js";
|
|
16
|
+
const LAYER_VERSION = "2";
|
|
15
17
|
const DEFAULT_OPEN_NEXT_VERSION = "2.2.4";
|
|
16
18
|
const DEFAULT_CACHE_POLICY_ALLOWED_HEADERS = [
|
|
17
19
|
"accept",
|
|
@@ -32,13 +34,11 @@ const DEFAULT_CACHE_POLICY_ALLOWED_HEADERS = [
|
|
|
32
34
|
* ```
|
|
33
35
|
*/
|
|
34
36
|
export class NextjsSite extends SsrSite {
|
|
37
|
+
routes;
|
|
35
38
|
constructor(scope, id, props) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
disableIncrementalCache: false,
|
|
40
|
-
...props?.experimental,
|
|
41
|
-
};
|
|
39
|
+
const streaming = props?.experimental?.streaming ?? false;
|
|
40
|
+
const disableDynamoDBCache = props?.experimental?.disableDynamoDBCache ?? false;
|
|
41
|
+
const disableIncrementalCache = props?.experimental?.disableIncrementalCache ?? false;
|
|
42
42
|
super(scope, id, {
|
|
43
43
|
buildCommand: [
|
|
44
44
|
"npx",
|
|
@@ -55,6 +55,9 @@ export class NextjsSite extends SsrSite {
|
|
|
55
55
|
].join(" "),
|
|
56
56
|
...props,
|
|
57
57
|
});
|
|
58
|
+
if (this.isPerRouteLoggingEnabled()) {
|
|
59
|
+
this.disableDefaultLogging();
|
|
60
|
+
}
|
|
58
61
|
if (!disableIncrementalCache) {
|
|
59
62
|
this.createRevalidationQueue();
|
|
60
63
|
if (!disableDynamoDBCache) {
|
|
@@ -67,16 +70,16 @@ export class NextjsSite extends SsrSite {
|
|
|
67
70
|
}
|
|
68
71
|
plan(bucket) {
|
|
69
72
|
const { path: sitePath, edge, experimental, imageOptimization, } = this.props;
|
|
70
|
-
const serverConfig = {
|
|
73
|
+
const serverConfig = this.wrapServerFunction({
|
|
71
74
|
description: "Next.js server",
|
|
72
75
|
bundle: path.join(sitePath, ".open-next", "server-function"),
|
|
73
|
-
handler:
|
|
76
|
+
handler: "index.handler",
|
|
74
77
|
environment: {
|
|
75
78
|
CACHE_BUCKET_NAME: bucket.bucketName,
|
|
76
79
|
CACHE_BUCKET_KEY_PREFIX: "_cache",
|
|
77
80
|
CACHE_BUCKET_REGION: Stack.of(this).region,
|
|
78
81
|
},
|
|
79
|
-
};
|
|
82
|
+
});
|
|
80
83
|
return this.validatePlan({
|
|
81
84
|
cloudFrontFunctions: {
|
|
82
85
|
serverCfFunction: {
|
|
@@ -289,50 +292,100 @@ export class NextjsSite extends SsrSite {
|
|
|
289
292
|
type: "NextjsSite",
|
|
290
293
|
data: {
|
|
291
294
|
...metadata.data,
|
|
292
|
-
routes: this.
|
|
295
|
+
routes: this.isPerRouteLoggingEnabled()
|
|
296
|
+
? {
|
|
297
|
+
logGroupPrefix: `/sst/lambda/${this.serverFunction.functionName}`,
|
|
298
|
+
data: this.useRoutes().map(({ route, logGroupPath }) => ({
|
|
299
|
+
route,
|
|
300
|
+
logGroupPath,
|
|
301
|
+
})),
|
|
302
|
+
}
|
|
303
|
+
: undefined,
|
|
293
304
|
},
|
|
294
305
|
};
|
|
295
306
|
}
|
|
296
|
-
|
|
297
|
-
const { path: sitePath, experimental } = this.props;
|
|
307
|
+
wrapServerFunction(config) {
|
|
308
|
+
const { path: sitePath, experimental, cdk } = this.props;
|
|
309
|
+
const stack = Stack.of(this);
|
|
298
310
|
const wrapperName = "nextjssite-index";
|
|
299
311
|
const serverPath = path.join(sitePath, ".open-next", "server-function");
|
|
312
|
+
const injections = [];
|
|
313
|
+
if (this.isPerRouteLoggingEnabled()) {
|
|
314
|
+
injections.push(`
|
|
315
|
+
const routeData = ${JSON.stringify(this.useRoutes())}.find(({ regex }) => event.rawPath.match(new RegExp(regex)));
|
|
316
|
+
if (routeData) {
|
|
317
|
+
console.log("::sst::" + JSON.stringify({
|
|
318
|
+
action:"log.split",
|
|
319
|
+
properties: {
|
|
320
|
+
logGroupName:"/sst/lambda/" + context.functionName + routeData.logGroupPath,
|
|
321
|
+
},
|
|
322
|
+
}));
|
|
323
|
+
}`);
|
|
324
|
+
}
|
|
300
325
|
fs.writeFileSync(path.join(serverPath, `${wrapperName}.mjs`), experimental?.streaming
|
|
301
326
|
? [
|
|
302
|
-
`export const handler = awslambda.streamifyResponse(async (
|
|
327
|
+
`export const handler = awslambda.streamifyResponse(async (event, context) => {`,
|
|
328
|
+
...injections,
|
|
303
329
|
` const { handler: rawHandler} = await import("./index.mjs");`,
|
|
304
|
-
` return rawHandler(
|
|
330
|
+
` return rawHandler(event, context);`,
|
|
305
331
|
`});`,
|
|
306
332
|
].join("\n")
|
|
307
333
|
: [
|
|
308
|
-
`export const handler = async (
|
|
334
|
+
`export const handler = async (event, context) => {`,
|
|
335
|
+
...injections,
|
|
309
336
|
` const { handler: rawHandler} = await import("./index.mjs");`,
|
|
310
|
-
` return rawHandler(
|
|
337
|
+
` return rawHandler(event, context);`,
|
|
311
338
|
`};`,
|
|
312
339
|
].join("\n"));
|
|
313
|
-
return
|
|
340
|
+
return {
|
|
341
|
+
...config,
|
|
342
|
+
layers: this.isPerRouteLoggingEnabled()
|
|
343
|
+
? [
|
|
344
|
+
LayerVersion.fromLayerVersionArn(this, "SSTExtension", cdk?.server?.architecture?.name === Architecture.X86_64.name
|
|
345
|
+
? `arn:aws:lambda:${stack.region}:226609089145:layer:sst-extension-amd64:${LAYER_VERSION}`
|
|
346
|
+
: `arn:aws:lambda:${stack.region}:226609089145:layer:sst-extension-arm64:${LAYER_VERSION}`),
|
|
347
|
+
]
|
|
348
|
+
: undefined,
|
|
349
|
+
handler: `${wrapperName}.handler`,
|
|
350
|
+
};
|
|
314
351
|
}
|
|
315
|
-
|
|
352
|
+
useRoutes() {
|
|
353
|
+
if (this.routes)
|
|
354
|
+
return this.routes;
|
|
316
355
|
const id = this.node.id;
|
|
317
356
|
const { path: sitePath } = this.props;
|
|
318
357
|
try {
|
|
319
358
|
const content = JSON.parse(fs
|
|
320
359
|
.readFileSync(path.join(sitePath, ".next/routes-manifest.json"))
|
|
321
360
|
.toString());
|
|
322
|
-
|
|
361
|
+
this.routes = [
|
|
323
362
|
...[...content.dynamicRoutes, ...content.staticRoutes]
|
|
324
|
-
.map(({ page }) =>
|
|
325
|
-
|
|
326
|
-
|
|
363
|
+
.map(({ page, regex }) => {
|
|
364
|
+
const cwRoute = NextjsSite.buildCloudWatchRouteName(page);
|
|
365
|
+
const cwHash = NextjsSite.buildCloudWatchRouteHash(page);
|
|
366
|
+
return {
|
|
367
|
+
route: page,
|
|
368
|
+
regex,
|
|
369
|
+
logGroupPath: `/${cwHash}${cwRoute}`,
|
|
370
|
+
};
|
|
371
|
+
})
|
|
327
372
|
.sort((a, b) => a.route.localeCompare(b.route)),
|
|
328
373
|
...(content.dataRoutes || [])
|
|
329
|
-
.map(({ page }) =>
|
|
330
|
-
|
|
374
|
+
.map(({ page, dataRouteRegex }) => {
|
|
375
|
+
const routeDisplayName = page.endsWith("/")
|
|
331
376
|
? `/_next/data/BUILD_ID${page}index.json`
|
|
332
|
-
: `/_next/data/BUILD_ID${page}.json
|
|
333
|
-
|
|
377
|
+
: `/_next/data/BUILD_ID${page}.json`;
|
|
378
|
+
const cwRoute = NextjsSite.buildCloudWatchRouteName(routeDisplayName);
|
|
379
|
+
const cwHash = NextjsSite.buildCloudWatchRouteHash(`data:${page}`);
|
|
380
|
+
return {
|
|
381
|
+
route: routeDisplayName,
|
|
382
|
+
regex: dataRouteRegex,
|
|
383
|
+
logGroupPath: `/${cwHash}${cwRoute}`,
|
|
384
|
+
};
|
|
385
|
+
})
|
|
334
386
|
.sort((a, b) => a.route.localeCompare(b.route)),
|
|
335
387
|
];
|
|
388
|
+
return this.routes;
|
|
336
389
|
}
|
|
337
390
|
catch (e) {
|
|
338
391
|
console.error(e);
|
|
@@ -343,4 +396,43 @@ export class NextjsSite extends SsrSite {
|
|
|
343
396
|
const { path: sitePath } = this.props;
|
|
344
397
|
return fs.readFileSync(path.join(sitePath, ".next/BUILD_ID")).toString();
|
|
345
398
|
}
|
|
399
|
+
isPerRouteLoggingEnabled() {
|
|
400
|
+
return (!this.doNotDeploy &&
|
|
401
|
+
!this.props.edge &&
|
|
402
|
+
this.props.logging === "per-route");
|
|
403
|
+
}
|
|
404
|
+
disableDefaultLogging() {
|
|
405
|
+
// Note: keep default logs enabled
|
|
406
|
+
return;
|
|
407
|
+
const stack = Stack.of(this);
|
|
408
|
+
const server = this.serverFunction;
|
|
409
|
+
const policy = new Policy(this, "DisableLoggingPolicy", {
|
|
410
|
+
statements: [
|
|
411
|
+
new PolicyStatement({
|
|
412
|
+
effect: Effect.DENY,
|
|
413
|
+
actions: [
|
|
414
|
+
"logs:CreateLogGroup",
|
|
415
|
+
"logs:CreateLogStream",
|
|
416
|
+
"logs:PutLogEvents",
|
|
417
|
+
],
|
|
418
|
+
resources: [
|
|
419
|
+
`arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${server.functionName}`,
|
|
420
|
+
`arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${server.functionName}:*`,
|
|
421
|
+
],
|
|
422
|
+
}),
|
|
423
|
+
],
|
|
424
|
+
});
|
|
425
|
+
server.role?.attachInlinePolicy(policy);
|
|
426
|
+
}
|
|
427
|
+
static buildCloudWatchRouteName(route) {
|
|
428
|
+
return route.replace(/[^a-zA-Z0-9_\-/.#]/g, "");
|
|
429
|
+
}
|
|
430
|
+
static buildCloudWatchRouteHash(route) {
|
|
431
|
+
const hash = crypto.createHash("sha256");
|
|
432
|
+
hash.update(route);
|
|
433
|
+
return hash.digest("hex").substring(0, 8);
|
|
434
|
+
}
|
|
435
|
+
static _test = {
|
|
436
|
+
buildCloudWatchRouteName: NextjsSite.buildCloudWatchRouteName,
|
|
437
|
+
};
|
|
346
438
|
}
|
package/constructs/RDS.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import
|
|
2
|
+
import { globSync } from "glob";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import url from "url";
|
|
5
5
|
import * as crypto from "crypto";
|
|
@@ -347,7 +347,7 @@ export class RDS extends Construct {
|
|
|
347
347
|
}
|
|
348
348
|
generateMigrationsHash(migrations) {
|
|
349
349
|
// Get all files inside the migrations folder
|
|
350
|
-
const files =
|
|
350
|
+
const files = globSync("**", {
|
|
351
351
|
dot: true,
|
|
352
352
|
nodir: true,
|
|
353
353
|
follow: true,
|
package/constructs/SsrSite.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { SSTConstruct } from "./Construct.js";
|
|
|
8
8
|
import { NodeJSProps, FunctionProps } from "./Function.js";
|
|
9
9
|
import { SsrFunction, SsrFunctionProps } from "./SsrFunction.js";
|
|
10
10
|
import { EdgeFunction, EdgeFunctionProps } from "./EdgeFunction.js";
|
|
11
|
-
import { BaseSiteFileOptions,
|
|
11
|
+
import { BaseSiteFileOptions, BaseSiteReplaceProps, BaseSiteCdkDistributionProps } from "./BaseSite.js";
|
|
12
12
|
import { Size } from "./util/size.js";
|
|
13
13
|
import { Duration } from "./util/duration.js";
|
|
14
14
|
import { Permissions } from "./util/permission.js";
|
|
@@ -52,12 +52,7 @@ export interface SsrSiteNodeJSProps extends NodeJSProps {
|
|
|
52
52
|
}
|
|
53
53
|
export interface SsrDomainProps extends DistributionDomainProps {
|
|
54
54
|
}
|
|
55
|
-
export interface SsrSiteFileOptionsFilter extends BaseSiteFileOptionsFilter {
|
|
56
|
-
}
|
|
57
55
|
export interface SsrSiteFileOptions extends BaseSiteFileOptions {
|
|
58
|
-
filters: SsrSiteFileOptionsFilter[];
|
|
59
|
-
}
|
|
60
|
-
export interface SsrSiteFileOptionsDeprecated extends BaseSiteFileOptionsDeprecated {
|
|
61
56
|
}
|
|
62
57
|
export interface SsrSiteReplaceProps extends BaseSiteReplaceProps {
|
|
63
58
|
}
|
|
@@ -207,18 +202,18 @@ export interface SsrSiteProps {
|
|
|
207
202
|
*/
|
|
208
203
|
url?: string;
|
|
209
204
|
};
|
|
210
|
-
|
|
205
|
+
assets?: {
|
|
211
206
|
/**
|
|
212
|
-
* Character encoding for text based assets
|
|
207
|
+
* Character encoding for text based assets uploaded to S3 (ex: html, css, js, etc.). If "none" is specified, no charset will be returned in header.
|
|
213
208
|
* @default utf-8
|
|
214
209
|
* @example
|
|
215
210
|
* ```js
|
|
216
|
-
*
|
|
217
|
-
*
|
|
211
|
+
* assets: {
|
|
212
|
+
* textEncoding: "iso-8859-1"
|
|
218
213
|
* }
|
|
219
214
|
* ```
|
|
220
215
|
*/
|
|
221
|
-
textEncoding?: "
|
|
216
|
+
textEncoding?: "utf-8" | "iso-8859-1" | "windows-1252" | "ascii" | "none";
|
|
222
217
|
/**
|
|
223
218
|
* The strategy to use for invalidating the CDN cache. By default, the CDN cache will invalidate on changes any cached file, but this could become slow on very large projects.
|
|
224
219
|
* - "never" - No invalidation will be performed.
|
|
@@ -228,7 +223,7 @@ export interface SsrSiteProps {
|
|
|
228
223
|
* @default all
|
|
229
224
|
* @example
|
|
230
225
|
* ```js
|
|
231
|
-
*
|
|
226
|
+
* assets: {
|
|
232
227
|
* cdnInvalidationStrategy: "versioned"
|
|
233
228
|
* }
|
|
234
229
|
* ```
|
|
@@ -239,8 +234,8 @@ export interface SsrSiteProps {
|
|
|
239
234
|
* @default 1 year
|
|
240
235
|
* @example
|
|
241
236
|
* ```js
|
|
242
|
-
*
|
|
243
|
-
*
|
|
237
|
+
* assets: {
|
|
238
|
+
* versionedFilesTTL: "30 days"
|
|
244
239
|
* }
|
|
245
240
|
* ```
|
|
246
241
|
*/
|
|
@@ -250,7 +245,7 @@ export interface SsrSiteProps {
|
|
|
250
245
|
* @default public,max-age=31536000,immutable
|
|
251
246
|
* @example
|
|
252
247
|
* ```js
|
|
253
|
-
*
|
|
248
|
+
* assets: {
|
|
254
249
|
* versionedFilesCacheHeader: "public,max-age=31536000,immutable"
|
|
255
250
|
* }
|
|
256
251
|
* ```
|
|
@@ -261,8 +256,8 @@ export interface SsrSiteProps {
|
|
|
261
256
|
* @default 1 day
|
|
262
257
|
* @example
|
|
263
258
|
* ```js
|
|
264
|
-
*
|
|
265
|
-
*
|
|
259
|
+
* assets: {
|
|
260
|
+
* nonVersionedFilesTTL: "4 hours"
|
|
266
261
|
* }
|
|
267
262
|
* ```
|
|
268
263
|
*/
|
|
@@ -272,7 +267,7 @@ export interface SsrSiteProps {
|
|
|
272
267
|
* @default public,max-age=0,s-maxage=86400,stale-while-revalidate=8640
|
|
273
268
|
* @example
|
|
274
269
|
* ```js
|
|
275
|
-
*
|
|
270
|
+
* assets: {
|
|
276
271
|
* nonVersionedFilesCacheHeader: "public,max-age=0,no-cache"
|
|
277
272
|
* }
|
|
278
273
|
* ```
|
|
@@ -282,10 +277,10 @@ export interface SsrSiteProps {
|
|
|
282
277
|
* List of file options to specify cache control and content type for cached files. These file options are appended to the default file options so it's possible to override the default file options by specifying an overlapping file pattern.
|
|
283
278
|
* @example
|
|
284
279
|
* ```js
|
|
285
|
-
*
|
|
280
|
+
* assets: {
|
|
286
281
|
* fileOptions: [
|
|
287
282
|
* {
|
|
288
|
-
*
|
|
283
|
+
* files: "**\/*.zip",
|
|
289
284
|
* cacheControl: "private,no-cache,no-store,must-revalidate",
|
|
290
285
|
* contentType: "application/zip",
|
|
291
286
|
* },
|
|
@@ -294,6 +289,10 @@ export interface SsrSiteProps {
|
|
|
294
289
|
* ```
|
|
295
290
|
*/
|
|
296
291
|
fileOptions?: SsrSiteFileOptions[];
|
|
292
|
+
/**
|
|
293
|
+
* @internal
|
|
294
|
+
*/
|
|
295
|
+
_uploadConcurrency?: number;
|
|
297
296
|
};
|
|
298
297
|
/**
|
|
299
298
|
* While deploying, SST waits for the CloudFront cache invalidation process to finish. This ensures that the new content will be served once the deploy command finishes. However, this process can sometimes take more than 5 mins. For non-prod environments it might make sense to pass in `false`. That'll skip waiting for the cache to invalidate and speed up the deploy process.
|
|
@@ -343,59 +342,6 @@ export interface SsrSiteProps {
|
|
|
343
342
|
responseHeadersPolicy?: IResponseHeadersPolicy;
|
|
344
343
|
server?: Pick<CdkFunctionProps, "layers" | "vpc" | "vpcSubnets" | "securityGroups" | "allowAllOutbound" | "allowPublicSubnet" | "architecture" | "logRetention"> & Pick<FunctionProps, "copyFiles">;
|
|
345
344
|
};
|
|
346
|
-
/**
|
|
347
|
-
* Pass in a list of file options to customize cache control and content type specific files. Specifying file options will bypass all default file options and only use the ones specified. Most configurations within the `cache` prop will be ignored.
|
|
348
|
-
* @deprecated Use `cache.fileOptions` instead. Note that the `cache.fileOptions` are appended to default file options, not a replacement as this prop was.
|
|
349
|
-
* @default
|
|
350
|
-
* Versioned files cached for 1 year at the CDN and browser level.
|
|
351
|
-
* Nonversioned files cached for 1 day at the CDN level, but not at the browser level.
|
|
352
|
-
* ```js
|
|
353
|
-
* fileOptions: [
|
|
354
|
-
* {
|
|
355
|
-
* exclude: "*",
|
|
356
|
-
* include: "{versioned_directory}/*",
|
|
357
|
-
* cacheControl: "public,max-age=31536000,immutable",
|
|
358
|
-
* },
|
|
359
|
-
* {
|
|
360
|
-
* exclude: "*",
|
|
361
|
-
* include: "[{non_versioned_file1}, {non_versioned_file2}, ...]",
|
|
362
|
-
* cacheControl: "public,max-age=0,s-maxage=31536000,must-revalidate",
|
|
363
|
-
* },
|
|
364
|
-
* {
|
|
365
|
-
* exclude: "*",
|
|
366
|
-
* include: "[{non_versioned_dir_1}/*, {non_versioned_dir_2}/*, ...]",
|
|
367
|
-
* cacheControl: "public,max-age=0,s-maxage=31536000,must-revalidate",
|
|
368
|
-
* },
|
|
369
|
-
* ]
|
|
370
|
-
* ```
|
|
371
|
-
*
|
|
372
|
-
* @example
|
|
373
|
-
* ```js
|
|
374
|
-
* fileOptions: [
|
|
375
|
-
* {
|
|
376
|
-
* exclude: "*",
|
|
377
|
-
* include: "{versioned_directory}/*.css",
|
|
378
|
-
* cacheControl: "public,max-age=31536000,immutable",
|
|
379
|
-
* contentType: "text/css; charset=UTF-8",
|
|
380
|
-
* },
|
|
381
|
-
* {
|
|
382
|
-
* exclude: "*",
|
|
383
|
-
* include: "{versioned_directory}/*.js",
|
|
384
|
-
* cacheControl: "public,max-age=31536000,immutable",
|
|
385
|
-
* },
|
|
386
|
-
* {
|
|
387
|
-
* exclude: "*",
|
|
388
|
-
* include: "[{non_versioned_file1}, {non_versioned_file2}, ...]",
|
|
389
|
-
* cacheControl: "public,max-age=0,s-maxage=31536000,must-revalidate",
|
|
390
|
-
* },
|
|
391
|
-
* {
|
|
392
|
-
* exclude: "*",
|
|
393
|
-
* include: "[{non_versioned_dir_1}/*, {non_versioned_dir_2}/*, ...]",
|
|
394
|
-
* cacheControl: "public,max-age=0,s-maxage=31536000,must-revalidate",
|
|
395
|
-
* },
|
|
396
|
-
* ]
|
|
397
|
-
*/
|
|
398
|
-
fileOptions?: SsrSiteFileOptionsDeprecated[];
|
|
399
345
|
}
|
|
400
346
|
export type SsrSiteNormalizedProps = SsrSiteProps & {
|
|
401
347
|
path: Exclude<SsrSiteProps["path"], undefined>;
|