sst 2.36.5 → 2.36.7
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/ApiGatewayV1Api.d.ts +7 -4
- package/constructs/AstroSite.d.ts +1 -0
- package/constructs/NextjsSite.d.ts +16 -144
- package/constructs/NextjsSite.js +31 -53
- package/constructs/SsrFunction.d.ts +3 -0
- package/constructs/SsrFunction.js +45 -10
- package/constructs/SsrSite.d.ts +1 -0
- package/constructs/SsrSite.js +15 -0
- package/node/util/loader.js +5 -4
- package/package.json +2 -2
- package/support/edge-function/edge-lambda-version.mjs +39 -2
- package/support/edge-function/edge-lambda.mjs +39 -2
- package/support/edge-function/s3-bucket.mjs +39 -2
|
@@ -158,7 +158,7 @@ export interface ApiGatewayV1ApiProps<Authorizers extends Record<string, ApiGate
|
|
|
158
158
|
*/
|
|
159
159
|
id?: string;
|
|
160
160
|
/**
|
|
161
|
-
* Override the internally created
|
|
161
|
+
* Override the internally created REST API.
|
|
162
162
|
*
|
|
163
163
|
* @example
|
|
164
164
|
* ```js
|
|
@@ -195,9 +195,12 @@ export interface ApiGatewayV1ApiProps<Authorizers extends Record<string, ApiGate
|
|
|
195
195
|
* ```
|
|
196
196
|
*
|
|
197
197
|
* API Gateway REST API is structured in a tree structure:
|
|
198
|
-
*
|
|
199
|
-
* -
|
|
200
|
-
*
|
|
198
|
+
*
|
|
199
|
+
* - Each path part is a separate API Gateway resource object
|
|
200
|
+
* - And a path part is a child resource of the preceding part
|
|
201
|
+
*
|
|
202
|
+
* So the part path `/notes`, is a child resource of the root resource `/`. And `/notes/{noteId}` is a child resource of `/notes`.
|
|
203
|
+
* If `/notes` has been created in the imported API, you have to import it before creating the `/notes/{noteId}` child route.
|
|
201
204
|
*/
|
|
202
205
|
importedPaths?: {
|
|
203
206
|
[path: string]: string;
|
|
@@ -30,6 +30,7 @@ export declare class AstroSite extends SsrSite {
|
|
|
30
30
|
type: "function";
|
|
31
31
|
constructId: string;
|
|
32
32
|
function: import("./SsrFunction.js").SsrFunctionProps;
|
|
33
|
+
injections?: string[] | undefined;
|
|
33
34
|
streaming?: boolean | undefined;
|
|
34
35
|
} | {
|
|
35
36
|
type: "image-optimization-function";
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
|
-
import { Duration as CdkDuration } from "aws-cdk-lib/core";
|
|
3
2
|
import { Runtime, FunctionProps, Architecture } from "aws-cdk-lib/aws-lambda";
|
|
4
3
|
import { SsrSite, SsrSiteNormalizedProps, SsrSiteProps } from "./SsrSite.js";
|
|
5
4
|
import { Size } from "./util/size.js";
|
|
6
5
|
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";
|
|
9
6
|
import { CachePolicyProps } from "aws-cdk-lib/aws-cloudfront";
|
|
10
7
|
export interface NextjsSiteProps extends Omit<SsrSiteProps, "nodejs"> {
|
|
11
8
|
/**
|
|
@@ -148,78 +145,15 @@ export declare class NextjsSite extends SsrSite {
|
|
|
148
145
|
edgeServer: {
|
|
149
146
|
constructId: string;
|
|
150
147
|
function: {
|
|
151
|
-
|
|
148
|
+
description: string;
|
|
149
|
+
bundle: string;
|
|
152
150
|
handler: string;
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
environment?: Record<string, string> | undefined;
|
|
159
|
-
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
160
|
-
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
161
|
-
copyFiles?: import("./Function.js").FunctionCopyFilesProps[] | undefined;
|
|
162
|
-
logRetention?: RetentionDays | undefined;
|
|
163
|
-
functionName?: string | undefined;
|
|
164
|
-
tracing?: import("aws-cdk-lib/aws-lambda").Tracing | undefined;
|
|
165
|
-
architecture?: Architecture | undefined;
|
|
166
|
-
description?: string | undefined;
|
|
167
|
-
ephemeralStorageSize?: import("aws-cdk-lib/core").Size | undefined;
|
|
168
|
-
initialPolicy?: PolicyStatement[] | undefined;
|
|
169
|
-
role?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
170
|
-
vpc?: import("aws-cdk-lib/aws-ec2").IVpc | undefined;
|
|
171
|
-
vpcSubnets?: import("aws-cdk-lib/aws-ec2").SubnetSelection | undefined;
|
|
172
|
-
securityGroups?: import("aws-cdk-lib/aws-ec2").ISecurityGroup[] | undefined;
|
|
173
|
-
allowAllOutbound?: boolean | undefined;
|
|
174
|
-
deadLetterQueueEnabled?: boolean | undefined;
|
|
175
|
-
deadLetterQueue?: import("aws-cdk-lib/aws-sqs").IQueue | undefined;
|
|
176
|
-
deadLetterTopic?: import("aws-cdk-lib/aws-sns").ITopic | undefined;
|
|
177
|
-
snapStart?: import("aws-cdk-lib/aws-lambda").SnapStartConf | undefined;
|
|
178
|
-
profiling?: boolean | undefined;
|
|
179
|
-
profilingGroup?: import("aws-cdk-lib/aws-codeguruprofiler").IProfilingGroup | undefined;
|
|
180
|
-
insightsVersion?: import("aws-cdk-lib/aws-lambda").LambdaInsightsVersion | undefined;
|
|
181
|
-
adotInstrumentation?: import("aws-cdk-lib/aws-lambda").AdotInstrumentationConfig | undefined;
|
|
182
|
-
paramsAndSecrets?: import("aws-cdk-lib/aws-lambda").ParamsAndSecretsLayerVersion | undefined;
|
|
183
|
-
reservedConcurrentExecutions?: number | undefined;
|
|
184
|
-
events?: import("aws-cdk-lib/aws-lambda").IEventSource[] | undefined;
|
|
185
|
-
logRetentionRole?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
186
|
-
logRetentionRetryOptions?: import("aws-cdk-lib/aws-lambda").LogRetentionRetryOptions | undefined;
|
|
187
|
-
currentVersionOptions?: import("aws-cdk-lib/aws-lambda").VersionOptions | undefined;
|
|
188
|
-
filesystem?: import("aws-cdk-lib/aws-lambda").FileSystem | undefined;
|
|
189
|
-
allowPublicSubnet?: boolean | undefined;
|
|
190
|
-
environmentEncryption?: import("aws-cdk-lib/aws-kms").IKey | undefined;
|
|
191
|
-
codeSigningConfig?: import("aws-cdk-lib/aws-lambda").ICodeSigningConfig | undefined;
|
|
192
|
-
runtimeManagementMode?: import("aws-cdk-lib/aws-lambda").RuntimeManagementMode | undefined;
|
|
193
|
-
logGroup?: import("aws-cdk-lib/aws-logs").ILogGroup | undefined;
|
|
194
|
-
logFormat?: string | undefined;
|
|
195
|
-
applicationLogLevel?: string | undefined;
|
|
196
|
-
systemLogLevel?: string | undefined;
|
|
197
|
-
onFailure?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
198
|
-
onSuccess?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
199
|
-
maxEventAge?: CdkDuration | undefined;
|
|
200
|
-
retryAttempts?: number | undefined;
|
|
201
|
-
} | {
|
|
151
|
+
environment: {
|
|
152
|
+
CACHE_BUCKET_NAME: string;
|
|
153
|
+
CACHE_BUCKET_KEY_PREFIX: string;
|
|
154
|
+
CACHE_BUCKET_REGION: string;
|
|
155
|
+
};
|
|
202
156
|
layers: import("aws-cdk-lib/aws-lambda").ILayerVersion[] | undefined;
|
|
203
|
-
handler: string;
|
|
204
|
-
bundle?: string | undefined;
|
|
205
|
-
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | undefined;
|
|
206
|
-
timeout?: number | `${number} second` | `${number} seconds` | `${number} minute` | `${number} minutes` | `${number} hour` | `${number} hours` | `${number} day` | `${number} days` | undefined;
|
|
207
|
-
memorySize?: number | `${number} MB` | `${number} GB` | undefined;
|
|
208
|
-
permissions?: import("./index.js").Permissions | undefined;
|
|
209
|
-
/**
|
|
210
|
-
* How the logs are stored in CloudWatch
|
|
211
|
-
* - "combined" - Logs from all routes are stored in the same log group.
|
|
212
|
-
* - "per-route" - Logs from each route are stored in a separate log group.
|
|
213
|
-
* @default "per-route"
|
|
214
|
-
* @example
|
|
215
|
-
* ```js
|
|
216
|
-
* logging: "combined",
|
|
217
|
-
* ```
|
|
218
|
-
*/
|
|
219
|
-
environment?: Record<string, string> | undefined;
|
|
220
|
-
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
221
|
-
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
222
|
-
scopeOverride?: import("constructs").IConstruct | undefined;
|
|
223
157
|
};
|
|
224
158
|
};
|
|
225
159
|
} | undefined;
|
|
@@ -259,80 +193,18 @@ export declare class NextjsSite extends SsrSite {
|
|
|
259
193
|
type: "function";
|
|
260
194
|
constructId: string;
|
|
261
195
|
function: {
|
|
262
|
-
|
|
196
|
+
description: string;
|
|
197
|
+
bundle: string;
|
|
263
198
|
handler: string;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
environment?: Record<string, string> | undefined;
|
|
270
|
-
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
271
|
-
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
272
|
-
copyFiles?: import("./Function.js").FunctionCopyFilesProps[] | undefined;
|
|
273
|
-
logRetention?: RetentionDays | undefined;
|
|
274
|
-
functionName?: string | undefined;
|
|
275
|
-
tracing?: import("aws-cdk-lib/aws-lambda").Tracing | undefined;
|
|
276
|
-
architecture?: Architecture | undefined;
|
|
277
|
-
description?: string | undefined;
|
|
278
|
-
ephemeralStorageSize?: import("aws-cdk-lib/core").Size | undefined;
|
|
279
|
-
initialPolicy?: PolicyStatement[] | undefined;
|
|
280
|
-
role?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
281
|
-
vpc?: import("aws-cdk-lib/aws-ec2").IVpc | undefined;
|
|
282
|
-
vpcSubnets?: import("aws-cdk-lib/aws-ec2").SubnetSelection | undefined;
|
|
283
|
-
securityGroups?: import("aws-cdk-lib/aws-ec2").ISecurityGroup[] | undefined;
|
|
284
|
-
allowAllOutbound?: boolean | undefined;
|
|
285
|
-
deadLetterQueueEnabled?: boolean | undefined;
|
|
286
|
-
deadLetterQueue?: import("aws-cdk-lib/aws-sqs").IQueue | undefined;
|
|
287
|
-
deadLetterTopic?: import("aws-cdk-lib/aws-sns").ITopic | undefined;
|
|
288
|
-
snapStart?: import("aws-cdk-lib/aws-lambda").SnapStartConf | undefined;
|
|
289
|
-
profiling?: boolean | undefined;
|
|
290
|
-
profilingGroup?: import("aws-cdk-lib/aws-codeguruprofiler").IProfilingGroup | undefined;
|
|
291
|
-
insightsVersion?: import("aws-cdk-lib/aws-lambda").LambdaInsightsVersion | undefined;
|
|
292
|
-
adotInstrumentation?: import("aws-cdk-lib/aws-lambda").AdotInstrumentationConfig | undefined;
|
|
293
|
-
paramsAndSecrets?: import("aws-cdk-lib/aws-lambda").ParamsAndSecretsLayerVersion | undefined;
|
|
294
|
-
reservedConcurrentExecutions?: number | undefined;
|
|
295
|
-
events?: import("aws-cdk-lib/aws-lambda").IEventSource[] | undefined;
|
|
296
|
-
logRetentionRole?: import("aws-cdk-lib/aws-iam").IRole | undefined;
|
|
297
|
-
logRetentionRetryOptions?: import("aws-cdk-lib/aws-lambda").LogRetentionRetryOptions | undefined;
|
|
298
|
-
currentVersionOptions?: import("aws-cdk-lib/aws-lambda").VersionOptions | undefined;
|
|
299
|
-
filesystem?: import("aws-cdk-lib/aws-lambda").FileSystem | undefined;
|
|
300
|
-
allowPublicSubnet?: boolean | undefined;
|
|
301
|
-
environmentEncryption?: import("aws-cdk-lib/aws-kms").IKey | undefined;
|
|
302
|
-
codeSigningConfig?: import("aws-cdk-lib/aws-lambda").ICodeSigningConfig | undefined;
|
|
303
|
-
runtimeManagementMode?: import("aws-cdk-lib/aws-lambda").RuntimeManagementMode | undefined;
|
|
304
|
-
logGroup?: import("aws-cdk-lib/aws-logs").ILogGroup | undefined;
|
|
305
|
-
logFormat?: string | undefined;
|
|
306
|
-
applicationLogLevel?: string | undefined;
|
|
307
|
-
systemLogLevel?: string | undefined;
|
|
308
|
-
onFailure?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
309
|
-
onSuccess?: import("aws-cdk-lib/aws-lambda").IDestination | undefined;
|
|
310
|
-
maxEventAge?: CdkDuration | undefined;
|
|
311
|
-
retryAttempts?: number | undefined;
|
|
312
|
-
} | {
|
|
199
|
+
environment: {
|
|
200
|
+
CACHE_BUCKET_NAME: string;
|
|
201
|
+
CACHE_BUCKET_KEY_PREFIX: string;
|
|
202
|
+
CACHE_BUCKET_REGION: string;
|
|
203
|
+
};
|
|
313
204
|
layers: import("aws-cdk-lib/aws-lambda").ILayerVersion[] | undefined;
|
|
314
|
-
handler: string;
|
|
315
|
-
bundle?: string | undefined;
|
|
316
|
-
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | undefined;
|
|
317
|
-
timeout?: number | `${number} second` | `${number} seconds` | `${number} minute` | `${number} minutes` | `${number} hour` | `${number} hours` | `${number} day` | `${number} days` | undefined;
|
|
318
|
-
memorySize?: number | `${number} MB` | `${number} GB` | undefined;
|
|
319
|
-
permissions?: import("./index.js").Permissions | undefined;
|
|
320
|
-
/**
|
|
321
|
-
* How the logs are stored in CloudWatch
|
|
322
|
-
* - "combined" - Logs from all routes are stored in the same log group.
|
|
323
|
-
* - "per-route" - Logs from each route are stored in a separate log group.
|
|
324
|
-
* @default "per-route"
|
|
325
|
-
* @example
|
|
326
|
-
* ```js
|
|
327
|
-
* logging: "combined",
|
|
328
|
-
* ```
|
|
329
|
-
*/
|
|
330
|
-
environment?: Record<string, string> | undefined;
|
|
331
|
-
bind?: import("./Construct.js").SSTConstruct[] | undefined;
|
|
332
|
-
nodejs?: import("./Function.js").NodeJSProps | undefined;
|
|
333
|
-
scopeOverride?: import("constructs").IConstruct | undefined;
|
|
334
205
|
};
|
|
335
206
|
streaming: boolean | undefined;
|
|
207
|
+
injections: string[];
|
|
336
208
|
} | undefined;
|
|
337
209
|
};
|
|
338
210
|
edge: boolean;
|
|
@@ -374,7 +246,6 @@ export declare class NextjsSite extends SsrSite {
|
|
|
374
246
|
secrets: string[];
|
|
375
247
|
};
|
|
376
248
|
};
|
|
377
|
-
private wrapServerFunction;
|
|
378
249
|
private removeSourcemaps;
|
|
379
250
|
private useRoutes;
|
|
380
251
|
private useRoutesManifest;
|
|
@@ -382,6 +253,7 @@ export declare class NextjsSite extends SsrSite {
|
|
|
382
253
|
private useAppPathsManifest;
|
|
383
254
|
private usePagesManifest;
|
|
384
255
|
private usePrerenderManifest;
|
|
256
|
+
private useServerFunctionPerRouteLoggingInjection;
|
|
385
257
|
private getBuildId;
|
|
386
258
|
private getSourcemapForAppRoute;
|
|
387
259
|
private getSourcemapForPagesRoute;
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -89,8 +89,9 @@ export class NextjsSite extends SsrSite {
|
|
|
89
89
|
return super.buildDefaultServerCachePolicyProps(DEFAULT_CACHE_POLICY_ALLOWED_HEADERS);
|
|
90
90
|
}
|
|
91
91
|
plan(bucket) {
|
|
92
|
-
const { path: sitePath, edge, experimental, imageOptimization, } = this.props;
|
|
93
|
-
const
|
|
92
|
+
const { path: sitePath, edge, experimental, imageOptimization, cdk, } = this.props;
|
|
93
|
+
const stack = Stack.of(this);
|
|
94
|
+
const serverConfig = {
|
|
94
95
|
description: "Next.js server",
|
|
95
96
|
bundle: path.join(sitePath, ".open-next", "server-function"),
|
|
96
97
|
handler: "index.handler",
|
|
@@ -99,7 +100,14 @@ export class NextjsSite extends SsrSite {
|
|
|
99
100
|
CACHE_BUCKET_KEY_PREFIX: "_cache",
|
|
100
101
|
CACHE_BUCKET_REGION: Stack.of(this).region,
|
|
101
102
|
},
|
|
102
|
-
|
|
103
|
+
layers: this.isPerRouteLoggingEnabled()
|
|
104
|
+
? [
|
|
105
|
+
LayerVersion.fromLayerVersionArn(this, "SSTExtension", cdk?.server?.architecture?.name === Architecture.X86_64.name
|
|
106
|
+
? `arn:aws:lambda:${stack.region}:226609089145:layer:sst-extension-amd64:${LAYER_VERSION}`
|
|
107
|
+
: `arn:aws:lambda:${stack.region}:226609089145:layer:sst-extension-arm64:${LAYER_VERSION}`),
|
|
108
|
+
]
|
|
109
|
+
: undefined,
|
|
110
|
+
};
|
|
103
111
|
this.removeSourcemaps();
|
|
104
112
|
return this.validatePlan({
|
|
105
113
|
edge: edge ?? false,
|
|
@@ -126,6 +134,9 @@ export class NextjsSite extends SsrSite {
|
|
|
126
134
|
constructId: "ServerFunction",
|
|
127
135
|
function: serverConfig,
|
|
128
136
|
streaming: experimental?.streaming,
|
|
137
|
+
injections: this.isPerRouteLoggingEnabled()
|
|
138
|
+
? [this.useServerFunctionPerRouteLoggingInjection()]
|
|
139
|
+
: [],
|
|
129
140
|
},
|
|
130
141
|
}),
|
|
131
142
|
imageOptimizer: {
|
|
@@ -331,56 +342,6 @@ export class NextjsSite extends SsrSite {
|
|
|
331
342
|
},
|
|
332
343
|
};
|
|
333
344
|
}
|
|
334
|
-
wrapServerFunction(config) {
|
|
335
|
-
const { path: sitePath, experimental, cdk } = this.props;
|
|
336
|
-
const stack = Stack.of(this);
|
|
337
|
-
const wrapperName = "nextjssite-index";
|
|
338
|
-
const serverPath = path.join(sitePath, ".open-next", "server-function");
|
|
339
|
-
const injections = [];
|
|
340
|
-
if (this.isPerRouteLoggingEnabled()) {
|
|
341
|
-
injections.push(`
|
|
342
|
-
if (event.rawPath) {
|
|
343
|
-
const routeData = ${JSON.stringify(this.useRoutes().map(({ regex, logGroupPath }) => ({
|
|
344
|
-
regex,
|
|
345
|
-
logGroupPath,
|
|
346
|
-
})))}.find(({ regex }) => event.rawPath.match(new RegExp(regex)));
|
|
347
|
-
if (routeData) {
|
|
348
|
-
console.log("::sst::" + JSON.stringify({
|
|
349
|
-
action:"log.split",
|
|
350
|
-
properties: {
|
|
351
|
-
logGroupName:"/sst/lambda/" + context.functionName + routeData.logGroupPath,
|
|
352
|
-
},
|
|
353
|
-
}));
|
|
354
|
-
}
|
|
355
|
-
}`);
|
|
356
|
-
}
|
|
357
|
-
fs.writeFileSync(path.join(serverPath, `${wrapperName}.mjs`), experimental?.streaming
|
|
358
|
-
? [
|
|
359
|
-
`export const handler = awslambda.streamifyResponse(async (event, context) => {`,
|
|
360
|
-
...injections,
|
|
361
|
-
` const { handler: rawHandler} = await import("./index.mjs");`,
|
|
362
|
-
` return rawHandler(event, context);`,
|
|
363
|
-
`});`,
|
|
364
|
-
].join("\n")
|
|
365
|
-
: [
|
|
366
|
-
`export const handler = async (event, context) => {`,
|
|
367
|
-
...injections,
|
|
368
|
-
` const { handler: rawHandler} = await import("./index.mjs");`,
|
|
369
|
-
` return rawHandler(event, context);`,
|
|
370
|
-
`};`,
|
|
371
|
-
].join("\n"));
|
|
372
|
-
return {
|
|
373
|
-
...config,
|
|
374
|
-
layers: this.isPerRouteLoggingEnabled()
|
|
375
|
-
? [
|
|
376
|
-
LayerVersion.fromLayerVersionArn(this, "SSTExtension", cdk?.server?.architecture?.name === Architecture.X86_64.name
|
|
377
|
-
? `arn:aws:lambda:${stack.region}:226609089145:layer:sst-extension-amd64:${LAYER_VERSION}`
|
|
378
|
-
: `arn:aws:lambda:${stack.region}:226609089145:layer:sst-extension-arm64:${LAYER_VERSION}`),
|
|
379
|
-
]
|
|
380
|
-
: undefined,
|
|
381
|
-
handler: `${wrapperName}.handler`,
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
345
|
removeSourcemaps() {
|
|
385
346
|
const { path: sitePath } = this.props;
|
|
386
347
|
const files = globSync("**/*.js.map", {
|
|
@@ -506,6 +467,23 @@ export class NextjsSite extends SsrSite {
|
|
|
506
467
|
Logger.debug("Failed to load prerender-manifest.json", e);
|
|
507
468
|
}
|
|
508
469
|
}
|
|
470
|
+
useServerFunctionPerRouteLoggingInjection() {
|
|
471
|
+
return `
|
|
472
|
+
if (event.rawPath) {
|
|
473
|
+
const routeData = ${JSON.stringify(this.useRoutes().map(({ regex, logGroupPath }) => ({
|
|
474
|
+
regex,
|
|
475
|
+
logGroupPath,
|
|
476
|
+
})))}.find(({ regex }) => event.rawPath.match(new RegExp(regex)));
|
|
477
|
+
if (routeData) {
|
|
478
|
+
console.log("::sst::" + JSON.stringify({
|
|
479
|
+
action:"log.split",
|
|
480
|
+
properties: {
|
|
481
|
+
logGroupName:"/sst/lambda/" + context.functionName + routeData.logGroupPath,
|
|
482
|
+
},
|
|
483
|
+
}));
|
|
484
|
+
}
|
|
485
|
+
}`;
|
|
486
|
+
}
|
|
509
487
|
getBuildId() {
|
|
510
488
|
const { path: sitePath } = this.props;
|
|
511
489
|
return fs.readFileSync(path.join(sitePath, ".next/BUILD_ID")).toString();
|
|
@@ -19,6 +19,8 @@ export interface SsrFunctionProps extends Omit<FunctionOptions, "memorySize" | "
|
|
|
19
19
|
nodejs?: NodeJSProps;
|
|
20
20
|
copyFiles?: FunctionCopyFilesProps[];
|
|
21
21
|
logRetention?: RetentionDays;
|
|
22
|
+
streaming?: boolean;
|
|
23
|
+
injections?: string[];
|
|
22
24
|
}
|
|
23
25
|
export declare class SsrFunction extends Construct implements SSTConstruct {
|
|
24
26
|
readonly id: string;
|
|
@@ -43,6 +45,7 @@ export declare class SsrFunction extends Construct implements SSTConstruct {
|
|
|
43
45
|
private bind;
|
|
44
46
|
private buildAssetFromHandler;
|
|
45
47
|
private buildAssetFromBundle;
|
|
48
|
+
private writeWrapperFile;
|
|
46
49
|
private updateCodeReplacer;
|
|
47
50
|
private updateFunction;
|
|
48
51
|
/** @internal */
|
|
@@ -38,6 +38,8 @@ export class SsrFunction extends Construct {
|
|
|
38
38
|
this.props = {
|
|
39
39
|
timeout: 10,
|
|
40
40
|
memorySize: 1024,
|
|
41
|
+
streaming: false,
|
|
42
|
+
injections: [],
|
|
41
43
|
...props,
|
|
42
44
|
environment: props.environment || {},
|
|
43
45
|
permissions: props.permissions || [],
|
|
@@ -53,15 +55,15 @@ export class SsrFunction extends Construct {
|
|
|
53
55
|
this.assetReplacer = assetReplacer;
|
|
54
56
|
this.assetReplacerPolicy = assetReplacerPolicy;
|
|
55
57
|
useDeferredTasks().add(async () => {
|
|
56
|
-
const { bundle } = props;
|
|
57
|
-
const code = bundle
|
|
58
|
+
const { bundle } = this.props;
|
|
59
|
+
const { code, handler } = bundle
|
|
58
60
|
? await this.buildAssetFromBundle(bundle)
|
|
59
61
|
: await this.buildAssetFromHandler();
|
|
60
62
|
const codeConfig = code.bind(this.function);
|
|
61
63
|
const assetBucket = codeConfig.s3Location?.bucketName;
|
|
62
64
|
const assetKey = codeConfig.s3Location?.objectKey;
|
|
63
65
|
this.updateCodeReplacer(assetBucket, assetKey);
|
|
64
|
-
this.updateFunction(code, assetBucket, assetKey);
|
|
66
|
+
this.updateFunction(code, assetBucket, assetKey, handler);
|
|
65
67
|
});
|
|
66
68
|
const app = this.node.root;
|
|
67
69
|
app.registerTypes(this);
|
|
@@ -171,11 +173,12 @@ export class SsrFunction extends Construct {
|
|
|
171
173
|
});
|
|
172
174
|
}
|
|
173
175
|
async buildAssetFromHandler() {
|
|
176
|
+
const { handler, runtime, nodejs, copyFiles, injections } = this.props;
|
|
174
177
|
useFunctions().add(this.node.addr, {
|
|
175
|
-
handler
|
|
176
|
-
runtime
|
|
177
|
-
nodejs
|
|
178
|
-
copyFiles
|
|
178
|
+
handler,
|
|
179
|
+
runtime,
|
|
180
|
+
nodejs,
|
|
181
|
+
copyFiles,
|
|
179
182
|
});
|
|
180
183
|
// build function
|
|
181
184
|
const result = await useRuntimeHandlers().build(this.node.addr, "deploy");
|
|
@@ -185,6 +188,7 @@ export class SsrFunction extends Construct {
|
|
|
185
188
|
`There was a problem bundling the SSR function for the "${this.node.id}" Site.`,
|
|
186
189
|
...result.errors,
|
|
187
190
|
].join("\n"));
|
|
191
|
+
const newHandler = await this.writeWrapperFile(result.out, result.handler);
|
|
188
192
|
// upload sourcemap
|
|
189
193
|
const stack = Stack.of(this);
|
|
190
194
|
if (result.sourcemap) {
|
|
@@ -200,9 +204,11 @@ export class SsrFunction extends Construct {
|
|
|
200
204
|
});
|
|
201
205
|
}
|
|
202
206
|
this.missingSourcemap = !result.sourcemap;
|
|
203
|
-
return AssetCode.fromAsset(result.out);
|
|
207
|
+
return { code: AssetCode.fromAsset(result.out), handler: newHandler };
|
|
204
208
|
}
|
|
205
209
|
async buildAssetFromBundle(bundle) {
|
|
210
|
+
const { handler } = this.props;
|
|
211
|
+
const newHandler = await this.writeWrapperFile(bundle, handler);
|
|
206
212
|
// Note: cannot point the bundle to the `.open-next/server-function`
|
|
207
213
|
// b/c the folder contains node_modules. And pnpm node_modules
|
|
208
214
|
// contains symlinks. CDK cannot zip symlinks correctly.
|
|
@@ -214,7 +220,35 @@ export class SsrFunction extends Construct {
|
|
|
214
220
|
if (result.status !== 0) {
|
|
215
221
|
throw new Error(`There was a problem generating the assets package.`);
|
|
216
222
|
}
|
|
217
|
-
return
|
|
223
|
+
return {
|
|
224
|
+
code: AssetCode.fromAsset(path.join(outputPath, "server-function.zip")),
|
|
225
|
+
handler: newHandler,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
async writeWrapperFile(bundle, handler) {
|
|
229
|
+
const { streaming, injections } = this.props;
|
|
230
|
+
if (injections.length === 0)
|
|
231
|
+
return handler;
|
|
232
|
+
const { dir: handlerDir, name: oldHandlerName, ext: oldHandlerExt, } = path.posix.parse(handler);
|
|
233
|
+
const oldHandlerFunction = oldHandlerExt.replace(/^\./, "");
|
|
234
|
+
const newHandlerName = "server-index";
|
|
235
|
+
const newHandlerFunction = "handler";
|
|
236
|
+
await fs.writeFile(path.join(bundle, handlerDir, `${newHandlerName}.mjs`), streaming
|
|
237
|
+
? [
|
|
238
|
+
`export const ${newHandlerFunction} = awslambda.streamifyResponse(async (event, context) => {`,
|
|
239
|
+
...injections,
|
|
240
|
+
` const { ${oldHandlerFunction}: rawHandler} = await import("./${oldHandlerName}.mjs");`,
|
|
241
|
+
` return rawHandler(event, context);`,
|
|
242
|
+
`});`,
|
|
243
|
+
].join("\n")
|
|
244
|
+
: [
|
|
245
|
+
`export const ${newHandlerFunction} = async (event, context) => {`,
|
|
246
|
+
...injections,
|
|
247
|
+
` const { ${oldHandlerFunction}: rawHandler} = await import("./${oldHandlerName}.mjs");`,
|
|
248
|
+
` return rawHandler(event, context);`,
|
|
249
|
+
`};`,
|
|
250
|
+
].join("\n"));
|
|
251
|
+
return path.posix.join(handlerDir, `${newHandlerName}.${newHandlerFunction}`);
|
|
218
252
|
}
|
|
219
253
|
updateCodeReplacer(assetBucket, assetKey) {
|
|
220
254
|
const stack = Stack.of(this);
|
|
@@ -225,8 +259,9 @@ export class SsrFunction extends Construct {
|
|
|
225
259
|
const cfnPolicy = this.assetReplacerPolicy.node.defaultChild;
|
|
226
260
|
cfnPolicy.addPropertyOverride("PolicyDocument.Statement.0.Resource", `arn:${stack.partition}:s3:::${assetBucket}/*`);
|
|
227
261
|
}
|
|
228
|
-
updateFunction(code, assetBucket, assetKey) {
|
|
262
|
+
updateFunction(code, assetBucket, assetKey, handler) {
|
|
229
263
|
const cfnFunction = this.function.node.defaultChild;
|
|
264
|
+
cfnFunction.handler = handler;
|
|
230
265
|
cfnFunction.code = {
|
|
231
266
|
s3Bucket: assetBucket,
|
|
232
267
|
s3Key: assetKey,
|
package/constructs/SsrSite.d.ts
CHANGED
package/constructs/SsrSite.js
CHANGED
|
@@ -443,6 +443,11 @@ function handler(event) {
|
|
|
443
443
|
...props.function.environment,
|
|
444
444
|
},
|
|
445
445
|
...cdk?.server,
|
|
446
|
+
streaming: props.streaming,
|
|
447
|
+
injections: [
|
|
448
|
+
...(warm ? [useServerFunctionWarmingInjection()] : []),
|
|
449
|
+
...(props.injections || []),
|
|
450
|
+
],
|
|
446
451
|
});
|
|
447
452
|
ssrFunctions.push(fn);
|
|
448
453
|
bucket.grantReadWrite(fn?.role);
|
|
@@ -632,6 +637,16 @@ function handler(event) {
|
|
|
632
637
|
OriginRequestPolicy.fromOriginRequestPolicyId(self, "ServerOriginRequestPolicy", "b689b0a8-53d0-40ab-baf2-68738e2966ac");
|
|
633
638
|
return singletonOriginRequestPolicy;
|
|
634
639
|
}
|
|
640
|
+
function useServerFunctionWarmingInjection() {
|
|
641
|
+
return `
|
|
642
|
+
if (event.type === "warmer") {
|
|
643
|
+
return new Promise((resolve) => {
|
|
644
|
+
setTimeout(() => {
|
|
645
|
+
resolve({ serverId: "server-" + Math.random().toString(36).slice(2, 8) });
|
|
646
|
+
}, event.delay);
|
|
647
|
+
});
|
|
648
|
+
}`;
|
|
649
|
+
}
|
|
635
650
|
function getS3FileOptions(copy) {
|
|
636
651
|
const fileOptions = [];
|
|
637
652
|
const nonVersionedFilesTTL = typeof assets?.nonVersionedFilesTTL === "number"
|
package/node/util/loader.js
CHANGED
|
@@ -9,10 +9,11 @@ export function createLoader(batchFn) {
|
|
|
9
9
|
const batch = current;
|
|
10
10
|
if (!batch)
|
|
11
11
|
return;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
batchFn(batch.keys).then((result) => {
|
|
13
|
+
for (let i = 0; i < result.length; i++) {
|
|
14
|
+
batch.promises[i](result[i]);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
16
17
|
current = undefined;
|
|
17
18
|
}
|
|
18
19
|
function getBatch() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sideEffects": false,
|
|
3
3
|
"name": "sst",
|
|
4
|
-
"version": "2.36.
|
|
4
|
+
"version": "2.36.7",
|
|
5
5
|
"bin": {
|
|
6
6
|
"sst": "cli/sst.js"
|
|
7
7
|
},
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"@types/ws": "^8.5.3",
|
|
121
121
|
"@types/yargs": "^17.0.13",
|
|
122
122
|
"archiver": "^5.3.1",
|
|
123
|
-
"astro-sst": "2.36.
|
|
123
|
+
"astro-sst": "2.36.7",
|
|
124
124
|
"async": "^3.2.4",
|
|
125
125
|
"tsx": "^3.12.1",
|
|
126
126
|
"typescript": "^5.2.2",
|