sst 2.7.2 → 2.8.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/cli/commands/bind.js +1 -0
- package/cli/commands/dev.js +3 -1
- package/cli/commands/update.js +1 -0
- package/config.js +2 -1
- package/constructs/AstroSite.js +4 -8
- package/constructs/EdgeFunction.js +6 -6
- package/constructs/Function.js +3 -0
- package/constructs/RemixSite.js +4 -8
- package/constructs/SolidStartSite.js +4 -9
- package/constructs/SsrFunction.d.ts +10 -2
- package/constructs/SsrFunction.js +99 -32
- package/constructs/SsrSite.d.ts +5 -3
- package/constructs/SsrSite.js +23 -11
- package/constructs/SvelteKitSite.d.ts +27 -0
- package/constructs/SvelteKitSite.js +101 -0
- package/constructs/SvelteKitSite.tsdoc.d.ts +2 -0
- package/constructs/SvelteKitSite.tsdoc.js +2 -0
- package/constructs/deprecated/NextjsSite.js +1 -1
- package/constructs/index.d.ts +1 -0
- package/constructs/index.js +1 -0
- package/constructs/static-file-list.d.ts +1 -0
- package/constructs/static-file-list.js +51 -0
- package/node/config/index.js +0 -9
- package/node/site/index.d.ts +6 -6
- package/node/site/index.js +5 -5
- package/node/util/index.js +11 -0
- package/package.json +2 -2
- package/sst.mjs +4 -2
- package/support/base-site-archiver.mjs +18 -18
- /package/support/{sls-nextjs-site-function-stub → ssr-site-function-stub}/index.js +0 -0
package/cli/commands/bind.js
CHANGED
package/cli/commands/dev.js
CHANGED
|
@@ -192,7 +192,9 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
192
192
|
? "Remix"
|
|
193
193
|
: type === "SolidStartSite"
|
|
194
194
|
? "SolidStart"
|
|
195
|
-
:
|
|
195
|
+
: type === "SvelteKitSite"
|
|
196
|
+
? "SvelteKit"
|
|
197
|
+
: undefined;
|
|
196
198
|
if (framework) {
|
|
197
199
|
const cdCmd = path.resolve(props.path) === process.cwd()
|
|
198
200
|
? ""
|
package/cli/commands/update.js
CHANGED
package/config.js
CHANGED
|
@@ -122,7 +122,8 @@ export var Config;
|
|
|
122
122
|
.filter((c) => c.type === "AstroSite" ||
|
|
123
123
|
c.type === "NextjsSite" ||
|
|
124
124
|
c.type === "RemixSite" ||
|
|
125
|
-
c.type === "SolidStartSite"
|
|
125
|
+
c.type === "SolidStartSite" ||
|
|
126
|
+
c.type === "SvelteKitSite")
|
|
126
127
|
.filter((c) => keys.some((key) => c.data.secrets.includes(key)));
|
|
127
128
|
const siteDataPlaceholder = siteData.filter((c) => c.data.mode === "placeholder");
|
|
128
129
|
const siteDataEdge = siteData
|
package/constructs/AstroSite.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { Architecture } from "aws-cdk-lib/aws-lambda";
|
|
4
3
|
import { SsrSite } from "./SsrSite.js";
|
|
5
|
-
import {
|
|
4
|
+
import { SsrFunction } from "./SsrFunction.js";
|
|
6
5
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
7
6
|
/**
|
|
8
7
|
* The `AstroSite` construct is a higher level CDK construct that makes it easy to create a Astro app.
|
|
@@ -34,10 +33,9 @@ export class AstroSite extends SsrSite {
|
|
|
34
33
|
}
|
|
35
34
|
createFunctionForRegional() {
|
|
36
35
|
const { runtime, timeout, memorySize, permissions, environment, nodejs, bind, cdk, } = this.props;
|
|
37
|
-
const
|
|
38
|
-
description: "Server handler",
|
|
36
|
+
const ssrFn = new SsrFunction(this, `ServerFunction`, {
|
|
37
|
+
description: "Server handler for Astro",
|
|
39
38
|
handler: path.join(this.props.path, "dist", "server", "entry.handler"),
|
|
40
|
-
logRetention: "three_days",
|
|
41
39
|
runtime,
|
|
42
40
|
memorySize,
|
|
43
41
|
timeout,
|
|
@@ -49,10 +47,8 @@ export class AstroSite extends SsrSite {
|
|
|
49
47
|
environment,
|
|
50
48
|
permissions,
|
|
51
49
|
...cdk?.server,
|
|
52
|
-
architecture: cdk?.server?.architecture === Architecture.ARM_64 ? "arm_64" : "x86_64",
|
|
53
50
|
});
|
|
54
|
-
|
|
55
|
-
return fn;
|
|
51
|
+
return ssrFn.function;
|
|
56
52
|
}
|
|
57
53
|
createFunctionForEdge() {
|
|
58
54
|
const { runtime, timeout, memorySize, bind, permissions, environment, nodejs, } = this.props;
|
|
@@ -75,7 +75,7 @@ export class EdgeFunction extends Construct {
|
|
|
75
75
|
const lambdaBucket = this.createSingletonBucketInUsEast1();
|
|
76
76
|
const { fn, fnArn } = this.createFunctionInUsEast1(assetBucket, assetKey, lambdaBucket);
|
|
77
77
|
const { versionId } = this.createVersionInUsEast1(fn, fnArn);
|
|
78
|
-
//
|
|
78
|
+
// Create function after the code is updated
|
|
79
79
|
fn.node.addDependency(assetReplacer);
|
|
80
80
|
this.function = fn;
|
|
81
81
|
this.functionArn = fnArn;
|
|
@@ -182,6 +182,10 @@ export class EdgeFunction extends Construct {
|
|
|
182
182
|
}
|
|
183
183
|
createCodeReplacer(assetBucket, assetKey, handlerFilename) {
|
|
184
184
|
const { environment } = this.props;
|
|
185
|
+
const stack = Stack.of(this);
|
|
186
|
+
// Note: Source code for the Lambda functions have "{{ ENV_KEY }}" in them.
|
|
187
|
+
// They need to be replaced with real values before the Lambda
|
|
188
|
+
// functions get deployed.
|
|
185
189
|
const replacements = [
|
|
186
190
|
{
|
|
187
191
|
files: handlerFilename,
|
|
@@ -192,15 +196,11 @@ export class EdgeFunction extends Construct {
|
|
|
192
196
|
}),
|
|
193
197
|
},
|
|
194
198
|
...Object.entries(environment).map(([key, value]) => ({
|
|
195
|
-
files: "
|
|
199
|
+
files: "**/*.@(*js|json|html)",
|
|
196
200
|
search: `{{ ${key} }}`,
|
|
197
201
|
replace: value,
|
|
198
202
|
})),
|
|
199
203
|
];
|
|
200
|
-
// Note: Source code for the Lambda functions have "{{ ENV_KEY }}" in them.
|
|
201
|
-
// They need to be replaced with real values before the Lambda
|
|
202
|
-
// functions get deployed.
|
|
203
|
-
const stack = Stack.of(this);
|
|
204
204
|
const policy = new Policy(this, "AssetReplacerPolicy", {
|
|
205
205
|
statements: [
|
|
206
206
|
new PolicyStatement({
|
package/constructs/Function.js
CHANGED
|
@@ -122,6 +122,7 @@ export class Function extends CDKFunction {
|
|
|
122
122
|
environment: props.environment,
|
|
123
123
|
layers: Function.buildLayers(scope, id, props),
|
|
124
124
|
logRetention,
|
|
125
|
+
logRetentionRetryOptions: logRetention && { maxRetries: 100 },
|
|
125
126
|
});
|
|
126
127
|
}
|
|
127
128
|
// Handle local development (ie. sst start)
|
|
@@ -156,6 +157,7 @@ export class Function extends CDKFunction {
|
|
|
156
157
|
environment: props.environment,
|
|
157
158
|
layers: [],
|
|
158
159
|
logRetention,
|
|
160
|
+
logRetentionRetryOptions: logRetention && { maxRetries: 100 },
|
|
159
161
|
retryAttempts: 0,
|
|
160
162
|
...(debugOverrideProps || {}),
|
|
161
163
|
});
|
|
@@ -194,6 +196,7 @@ export class Function extends CDKFunction {
|
|
|
194
196
|
environment: props.environment,
|
|
195
197
|
layers: Function.buildLayers(scope, id, props),
|
|
196
198
|
logRetention,
|
|
199
|
+
logRetentionRetryOptions: logRetention && { maxRetries: 100 },
|
|
197
200
|
});
|
|
198
201
|
useDeferredTasks().add(async () => {
|
|
199
202
|
// Build function
|
package/constructs/RemixSite.js
CHANGED
|
@@ -3,9 +3,8 @@ import url from "url";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { createRequire } from "module";
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
|
-
import { Architecture } from "aws-cdk-lib/aws-lambda";
|
|
7
6
|
import { SsrSite } from "./SsrSite.js";
|
|
8
|
-
import {
|
|
7
|
+
import { SsrFunction } from "./SsrFunction.js";
|
|
9
8
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
10
9
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
11
10
|
/**
|
|
@@ -92,10 +91,9 @@ export class RemixSite extends SsrSite {
|
|
|
92
91
|
createFunctionForRegional() {
|
|
93
92
|
const { runtime, timeout, memorySize, permissions, environment, bind, nodejs, cdk, } = this.props;
|
|
94
93
|
const { handler, esbuild } = this.createServerLambdaBundle("regional-server.js");
|
|
95
|
-
const
|
|
96
|
-
description: "Server handler",
|
|
94
|
+
const ssrFn = new SsrFunction(this, `ServerFunction`, {
|
|
95
|
+
description: "Server handler for Remix",
|
|
97
96
|
handler,
|
|
98
|
-
logRetention: "three_days",
|
|
99
97
|
runtime,
|
|
100
98
|
memorySize,
|
|
101
99
|
timeout,
|
|
@@ -112,10 +110,8 @@ export class RemixSite extends SsrSite {
|
|
|
112
110
|
environment,
|
|
113
111
|
permissions,
|
|
114
112
|
...cdk?.server,
|
|
115
|
-
architecture: cdk?.server?.architecture === Architecture.ARM_64 ? "arm_64" : "x86_64",
|
|
116
113
|
});
|
|
117
|
-
|
|
118
|
-
return fn;
|
|
114
|
+
return ssrFn.function;
|
|
119
115
|
}
|
|
120
116
|
createFunctionForEdge() {
|
|
121
117
|
const { runtime, timeout, memorySize, bind, permissions, environment, nodejs, } = this.props;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { Architecture } from "aws-cdk-lib/aws-lambda";
|
|
3
2
|
import { SsrSite } from "./SsrSite.js";
|
|
4
|
-
import {
|
|
3
|
+
import { SsrFunction } from "./SsrFunction.js";
|
|
5
4
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
6
5
|
/**
|
|
7
6
|
* The `SolidStartSite` construct is a higher level CDK construct that makes it easy to create a SolidStart app.
|
|
@@ -25,11 +24,9 @@ export class SolidStartSite extends SsrSite {
|
|
|
25
24
|
}
|
|
26
25
|
createFunctionForRegional() {
|
|
27
26
|
const { runtime, timeout, memorySize, bind, nodejs, permissions, environment, cdk, } = this.props;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
description: "Server handler",
|
|
27
|
+
const ssrFn = new SsrFunction(this, `ServerFunction`, {
|
|
28
|
+
description: "Server handler for Solid",
|
|
31
29
|
handler: path.join(this.props.path, "dist", "server", "index.handler"),
|
|
32
|
-
logRetention: "three_days",
|
|
33
30
|
runtime,
|
|
34
31
|
memorySize,
|
|
35
32
|
timeout,
|
|
@@ -41,10 +38,8 @@ export class SolidStartSite extends SsrSite {
|
|
|
41
38
|
environment,
|
|
42
39
|
permissions,
|
|
43
40
|
...cdk?.server,
|
|
44
|
-
architecture: cdk?.server?.architecture === Architecture.ARM_64 ? "arm_64" : "x86_64",
|
|
45
41
|
});
|
|
46
|
-
|
|
47
|
-
return fn;
|
|
42
|
+
return ssrFn.function;
|
|
48
43
|
}
|
|
49
44
|
createFunctionForEdge() {
|
|
50
45
|
const { runtime, timeout, memorySize, bind, permissions, environment, nodejs, } = this.props;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
2
|
import { FunctionOptions, Function as CdkFunction } from "aws-cdk-lib/aws-lambda";
|
|
3
|
+
import { NodeJSProps, FunctionCopyFilesProps } from "./Function.js";
|
|
3
4
|
import { SSTConstruct } from "./Construct.js";
|
|
4
5
|
import { Permissions } from "./util/permission.js";
|
|
5
6
|
import { Size } from "./util/size.js";
|
|
6
7
|
import { Duration } from "./util/duration.js";
|
|
7
8
|
export interface SsrFunctionProps extends Omit<FunctionOptions, "memorySize" | "timeout" | "runtime"> {
|
|
8
|
-
bundle
|
|
9
|
+
bundle?: string;
|
|
9
10
|
handler: string;
|
|
10
11
|
runtime?: "nodejs14.x" | "nodejs16.x" | "nodejs18.x";
|
|
11
12
|
timeout: number | Duration;
|
|
@@ -13,14 +14,21 @@ export interface SsrFunctionProps extends Omit<FunctionOptions, "memorySize" | "
|
|
|
13
14
|
permissions?: Permissions;
|
|
14
15
|
environment?: Record<string, string>;
|
|
15
16
|
bind?: SSTConstruct[];
|
|
17
|
+
nodejs?: NodeJSProps;
|
|
18
|
+
copyFiles?: FunctionCopyFilesProps[];
|
|
16
19
|
}
|
|
17
20
|
export declare class SsrFunction extends Construct {
|
|
18
21
|
function: CdkFunction;
|
|
22
|
+
private assetReplacer;
|
|
23
|
+
private assetReplacerPolicy;
|
|
19
24
|
private props;
|
|
20
25
|
constructor(scope: Construct, id: string, props: SsrFunctionProps);
|
|
21
26
|
attachPermissions(permissions: Permissions): void;
|
|
22
|
-
private createCodeAsset;
|
|
23
27
|
private createFunction;
|
|
24
28
|
private createCodeReplacer;
|
|
25
29
|
private bind;
|
|
30
|
+
private buildAssetFromHandler;
|
|
31
|
+
private buildAssetFromBundle;
|
|
32
|
+
private updateCodeReplacer;
|
|
33
|
+
private updateFunction;
|
|
26
34
|
}
|
|
@@ -2,12 +2,16 @@ import url from "url";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import spawn from "cross-spawn";
|
|
4
4
|
import { Construct } from "constructs";
|
|
5
|
-
import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
5
|
+
import { Effect, Policy, PolicyStatement, } from "aws-cdk-lib/aws-iam";
|
|
6
6
|
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
7
|
-
import { Architecture, Runtime, Code, Function as CdkFunction, } from "aws-cdk-lib/aws-lambda";
|
|
7
|
+
import { Architecture, AssetCode, Runtime, Code, Function as CdkFunction, } from "aws-cdk-lib/aws-lambda";
|
|
8
|
+
import { Bucket } from "aws-cdk-lib/aws-s3";
|
|
8
9
|
import { Asset } from "aws-cdk-lib/aws-s3-assets";
|
|
9
|
-
import { Duration as CdkDuration, CustomResource } from "aws-cdk-lib";
|
|
10
|
+
import { Duration as CdkDuration, CustomResource, } from "aws-cdk-lib";
|
|
10
11
|
import { useProject } from "../project.js";
|
|
12
|
+
import { useRuntimeHandlers } from "../runtime/handlers.js";
|
|
13
|
+
import { useFunctions, } from "./Function.js";
|
|
14
|
+
import { useDeferredTasks } from "./deferred_task.js";
|
|
11
15
|
import { Stack } from "./Stack.js";
|
|
12
16
|
import { bindEnvironment, bindPermissions, getReferencedSecrets, } from "./util/functionBinding.js";
|
|
13
17
|
import { attachPermissionsToRole } from "./util/permission.js";
|
|
@@ -19,6 +23,8 @@ const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
|
19
23
|
/////////////////////
|
|
20
24
|
export class SsrFunction extends Construct {
|
|
21
25
|
function;
|
|
26
|
+
assetReplacer;
|
|
27
|
+
assetReplacerPolicy;
|
|
22
28
|
props;
|
|
23
29
|
constructor(scope, id, props) {
|
|
24
30
|
super(scope, id);
|
|
@@ -27,41 +33,48 @@ export class SsrFunction extends Construct {
|
|
|
27
33
|
environment: props.environment || {},
|
|
28
34
|
permissions: props.permissions || [],
|
|
29
35
|
};
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
const { assetBucket, assetKey } = (props.bundle
|
|
37
|
+
? // Case: bundle is pre-built
|
|
38
|
+
() => {
|
|
39
|
+
const asset = this.buildAssetFromBundle(props.bundle);
|
|
40
|
+
return {
|
|
41
|
+
assetBucket: asset.s3BucketName,
|
|
42
|
+
assetKey: asset.s3ObjectKey,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
: // Case: bundle is NOT pre-built
|
|
46
|
+
() => {
|
|
47
|
+
this.buildAssetFromHandler((code) => {
|
|
48
|
+
const codeConfig = code.bind(this.function);
|
|
49
|
+
const assetBucket = codeConfig.s3Location?.bucketName;
|
|
50
|
+
const assetKey = codeConfig.s3Location?.objectKey;
|
|
51
|
+
this.updateCodeReplacer(assetBucket, assetKey);
|
|
52
|
+
this.updateFunction(code, assetBucket, assetKey);
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
assetBucket: "placeholder",
|
|
56
|
+
assetKey: "placeholder",
|
|
57
|
+
};
|
|
58
|
+
})();
|
|
59
|
+
const { assetReplacer, assetReplacerPolicy } = this.createCodeReplacer(assetBucket, assetKey);
|
|
60
|
+
this.function = this.createFunction(assetBucket, assetKey);
|
|
33
61
|
this.attachPermissions(props.permissions || []);
|
|
34
62
|
this.bind(props.bind || []);
|
|
63
|
+
// Create function after the code is updated
|
|
35
64
|
this.function.node.addDependency(assetReplacer);
|
|
65
|
+
this.assetReplacer = assetReplacer;
|
|
66
|
+
this.assetReplacerPolicy = assetReplacerPolicy;
|
|
36
67
|
}
|
|
37
68
|
attachPermissions(permissions) {
|
|
38
69
|
attachPermissionsToRole(this.function.role, permissions);
|
|
39
70
|
}
|
|
40
|
-
|
|
41
|
-
const { bundle } = this.props;
|
|
42
|
-
// Note: cannot point the bundle to the `.open-next/server-function`
|
|
43
|
-
// b/c the folder contains node_modules. And pnpm node_modules
|
|
44
|
-
// contains symlinks. CDK cannot zip symlinks correctly.
|
|
45
|
-
// https://github.com/aws/aws-cdk/issues/9251
|
|
46
|
-
// We will zip the folder ourselves.
|
|
47
|
-
const outputPath = path.resolve(useProject().paths.artifacts, `SsrFunction-${this.node.id}-${this.node.addr}`);
|
|
48
|
-
const script = path.resolve(__dirname, "../support/ssr-site-function-archiver.mjs");
|
|
49
|
-
const result = spawn.sync("node", [script, path.join(bundle), path.join(outputPath, "server-function.zip")], { stdio: "inherit" });
|
|
50
|
-
if (result.status !== 0) {
|
|
51
|
-
throw new Error(`There was a problem generating the assets package.`);
|
|
52
|
-
}
|
|
53
|
-
// Create asset
|
|
54
|
-
return new Asset(this, "Asset", {
|
|
55
|
-
path: path.join(outputPath, "server-function.zip"),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
createFunction(asset) {
|
|
71
|
+
createFunction(assetBucket, assetKey) {
|
|
59
72
|
const { runtime, timeout, memorySize, handler } = this.props;
|
|
60
73
|
return new CdkFunction(this, `ServerFunction`, {
|
|
61
74
|
...this.props,
|
|
62
75
|
handler,
|
|
63
76
|
logRetention: RetentionDays.THREE_DAYS,
|
|
64
|
-
code: Code.fromBucket(
|
|
77
|
+
code: Code.fromBucket(Bucket.fromBucketName(this, "IServerFunctionBucket", assetBucket), assetKey),
|
|
65
78
|
runtime: runtime === "nodejs14.x"
|
|
66
79
|
? Runtime.NODEJS_14_X
|
|
67
80
|
: runtime === "nodejs16.x"
|
|
@@ -76,18 +89,21 @@ export class SsrFunction extends Construct {
|
|
|
76
89
|
: CdkDuration.seconds(timeout),
|
|
77
90
|
});
|
|
78
91
|
}
|
|
79
|
-
createCodeReplacer(
|
|
92
|
+
createCodeReplacer(assetBucket, assetKey) {
|
|
80
93
|
const { environment } = this.props;
|
|
81
94
|
// Note: Source code for the Lambda functions have "{{ ENV_KEY }}" in them.
|
|
82
95
|
// They need to be replaced with real values before the Lambda
|
|
83
96
|
// functions get deployed.
|
|
97
|
+
// - "*.js" files: ie. Next.js server function
|
|
98
|
+
// - "*.html" files: ie. SvelteKit prerendered pages data
|
|
99
|
+
// - "*.json" files: ie. SvelteKit prerendered + SSR data
|
|
84
100
|
const stack = Stack.of(this);
|
|
85
101
|
const policy = new Policy(this, "AssetReplacerPolicy", {
|
|
86
102
|
statements: [
|
|
87
103
|
new PolicyStatement({
|
|
88
104
|
effect: Effect.ALLOW,
|
|
89
105
|
actions: ["s3:GetObject", "s3:PutObject"],
|
|
90
|
-
resources: [`arn:${stack.partition}:s3:::${
|
|
106
|
+
resources: [`arn:${stack.partition}:s3:::${assetBucket}/*`],
|
|
91
107
|
}),
|
|
92
108
|
],
|
|
93
109
|
});
|
|
@@ -96,17 +112,17 @@ export class SsrFunction extends Construct {
|
|
|
96
112
|
serviceToken: stack.customResourceHandler.functionArn,
|
|
97
113
|
resourceType: "Custom::AssetReplacer",
|
|
98
114
|
properties: {
|
|
99
|
-
bucket:
|
|
100
|
-
key:
|
|
115
|
+
bucket: assetBucket,
|
|
116
|
+
key: assetKey,
|
|
101
117
|
replacements: Object.entries(environment).map(([key, value]) => ({
|
|
102
|
-
files: "
|
|
118
|
+
files: "**/*.@(*js|json|html)",
|
|
103
119
|
search: `{{ ${key} }}`,
|
|
104
120
|
replace: value,
|
|
105
121
|
})),
|
|
106
122
|
},
|
|
107
123
|
});
|
|
108
124
|
resource.node.addDependency(policy);
|
|
109
|
-
return resource;
|
|
125
|
+
return { assetReplacer: resource, assetReplacerPolicy: policy };
|
|
110
126
|
}
|
|
111
127
|
bind(constructs) {
|
|
112
128
|
const app = this.node.root;
|
|
@@ -131,4 +147,55 @@ export class SsrFunction extends Construct {
|
|
|
131
147
|
]));
|
|
132
148
|
});
|
|
133
149
|
}
|
|
150
|
+
buildAssetFromHandler(onBundled) {
|
|
151
|
+
useFunctions().add(this.node.addr, {
|
|
152
|
+
handler: this.props.handler,
|
|
153
|
+
runtime: this.props.runtime,
|
|
154
|
+
nodejs: this.props.nodejs,
|
|
155
|
+
copyFiles: this.props.copyFiles,
|
|
156
|
+
});
|
|
157
|
+
useDeferredTasks().add(async () => {
|
|
158
|
+
// Build function
|
|
159
|
+
const bundle = await useRuntimeHandlers().build(this.node.addr, "deploy");
|
|
160
|
+
// create wrapper that calls the handler
|
|
161
|
+
if (bundle.type === "error")
|
|
162
|
+
throw new Error(`There was a problem bundling the SSR function for the "${this.node.id}" Site.`);
|
|
163
|
+
const code = AssetCode.fromAsset(bundle.out);
|
|
164
|
+
onBundled(code);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
buildAssetFromBundle(bundle) {
|
|
168
|
+
// Note: cannot point the bundle to the `.open-next/server-function`
|
|
169
|
+
// b/c the folder contains node_modules. And pnpm node_modules
|
|
170
|
+
// contains symlinks. CDK cannot zip symlinks correctly.
|
|
171
|
+
// https://github.com/aws/aws-cdk/issues/9251
|
|
172
|
+
// We will zip the folder ourselves.
|
|
173
|
+
const outputPath = path.resolve(useProject().paths.artifacts, `SsrFunction-${this.node.id}-${this.node.addr}`);
|
|
174
|
+
const script = path.resolve(__dirname, "../support/ssr-site-function-archiver.mjs");
|
|
175
|
+
const result = spawn.sync("node", [script, path.join(bundle), path.join(outputPath, "server-function.zip")], { stdio: "inherit" });
|
|
176
|
+
if (result.status !== 0) {
|
|
177
|
+
throw new Error(`There was a problem generating the assets package.`);
|
|
178
|
+
}
|
|
179
|
+
// Create asset
|
|
180
|
+
return new Asset(this, `FunctionAsset`, {
|
|
181
|
+
path: path.join(outputPath, "server-function.zip"),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
updateCodeReplacer(assetBucket, assetKey) {
|
|
185
|
+
const stack = Stack.of(this);
|
|
186
|
+
const cfnReplacer = this.assetReplacer.node
|
|
187
|
+
.defaultChild;
|
|
188
|
+
cfnReplacer.addPropertyOverride("bucket", assetBucket);
|
|
189
|
+
cfnReplacer.addPropertyOverride("key", assetKey);
|
|
190
|
+
const cfnPolicy = this.assetReplacerPolicy.node.defaultChild;
|
|
191
|
+
cfnPolicy.addPropertyOverride("PolicyDocument.Statement.0.Resource", `arn:${stack.partition}:s3:::${assetBucket}/*`);
|
|
192
|
+
}
|
|
193
|
+
updateFunction(code, assetBucket, assetKey) {
|
|
194
|
+
const cfnFunction = this.function.node.defaultChild;
|
|
195
|
+
cfnFunction.code = {
|
|
196
|
+
s3Bucket: assetBucket,
|
|
197
|
+
s3Key: assetKey,
|
|
198
|
+
};
|
|
199
|
+
code.bindToResource(cfnFunction);
|
|
200
|
+
}
|
|
134
201
|
}
|
package/constructs/SsrSite.d.ts
CHANGED
|
@@ -5,19 +5,21 @@ import { IHostedZone } from "aws-cdk-lib/aws-route53";
|
|
|
5
5
|
import { Distribution, ICachePolicy, BehaviorOptions, CachePolicy, Function as CfFunction, FunctionEventType as CfFunctionEventType } from "aws-cdk-lib/aws-cloudfront";
|
|
6
6
|
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
|
|
7
7
|
import { SSTConstruct } from "./Construct.js";
|
|
8
|
-
import { NodeJSProps
|
|
8
|
+
import { NodeJSProps } from "./Function.js";
|
|
9
9
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
10
10
|
import { BaseSiteDomainProps, BaseSiteReplaceProps, BaseSiteCdkDistributionProps } from "./BaseSite.js";
|
|
11
11
|
import { Size } from "./util/size.js";
|
|
12
12
|
import { Duration } from "./util/duration.js";
|
|
13
13
|
import { Permissions } from "./util/permission.js";
|
|
14
14
|
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
15
|
-
type SsrSiteType = "NextjsSite" | "RemixSite" | "AstroSite" | "SolidStartSite";
|
|
15
|
+
type SsrSiteType = "NextjsSite" | "RemixSite" | "AstroSite" | "SolidStartSite" | "SvelteKitSite";
|
|
16
16
|
export type SsrBuildConfig = {
|
|
17
17
|
typesPath: string;
|
|
18
18
|
serverBuildOutputFile: string;
|
|
19
|
+
serverCFFunctionInjection?: string;
|
|
19
20
|
clientBuildOutputDir: string;
|
|
20
21
|
clientBuildVersionedSubDir: string;
|
|
22
|
+
prerenderedBuildOutputDir?: string;
|
|
21
23
|
};
|
|
22
24
|
export interface SsrSiteNodeJSProps extends NodeJSProps {
|
|
23
25
|
}
|
|
@@ -259,7 +261,7 @@ export declare class SsrSite extends Construct implements SSTConstruct {
|
|
|
259
261
|
private createS3Deployment;
|
|
260
262
|
protected createFunctionForRegional(): CdkFunction;
|
|
261
263
|
protected createFunctionForEdge(): EdgeFunction;
|
|
262
|
-
protected createFunctionForDev():
|
|
264
|
+
protected createFunctionForDev(): CdkFunction;
|
|
263
265
|
private createFunctionPermissionsForRegional;
|
|
264
266
|
private createFunctionPermissionsForEdge;
|
|
265
267
|
private validateCloudFrontDistributionSettings;
|
package/constructs/SsrSite.js
CHANGED
|
@@ -20,8 +20,8 @@ import { Stack } from "./Stack.js";
|
|
|
20
20
|
import { Logger } from "../logger.js";
|
|
21
21
|
import { createAppContext } from "./context.js";
|
|
22
22
|
import { isCDKConstruct } from "./Construct.js";
|
|
23
|
-
import { Function } from "./Function.js";
|
|
24
23
|
import { Secret } from "./Secret.js";
|
|
24
|
+
import { SsrFunction } from "./SsrFunction.js";
|
|
25
25
|
import { getBuildCmdEnvironment, } from "./BaseSite.js";
|
|
26
26
|
import { HttpsRedirect } from "./cdk/website-redirect.js";
|
|
27
27
|
import { DnsValidatedCertificate } from "./cdk/dns-validated-certificate.js";
|
|
@@ -167,8 +167,10 @@ export class SsrSite extends Construct {
|
|
|
167
167
|
* ```
|
|
168
168
|
*/
|
|
169
169
|
attachPermissions(permissions) {
|
|
170
|
-
this.serverLambdaForDev?.attachPermissions(permissions);
|
|
171
170
|
this.serverLambdaForEdge?.attachPermissions(permissions);
|
|
171
|
+
if (this.serverLambdaForDev) {
|
|
172
|
+
attachPermissionsToRole(this.serverLambdaForDev.role, permissions);
|
|
173
|
+
}
|
|
172
174
|
if (this.serverLambdaForRegional) {
|
|
173
175
|
attachPermissionsToRole(this.serverLambdaForRegional.role, permissions);
|
|
174
176
|
}
|
|
@@ -291,7 +293,14 @@ export class SsrSite extends Construct {
|
|
|
291
293
|
: 200;
|
|
292
294
|
const result = spawn.sync("node", [
|
|
293
295
|
script,
|
|
294
|
-
|
|
296
|
+
[
|
|
297
|
+
path.join(this.props.path, this.buildConfig.clientBuildOutputDir),
|
|
298
|
+
...(this.buildConfig.prerenderedBuildOutputDir
|
|
299
|
+
? [
|
|
300
|
+
path.join(this.props.path, this.buildConfig.prerenderedBuildOutputDir),
|
|
301
|
+
]
|
|
302
|
+
: []),
|
|
303
|
+
].join(","),
|
|
295
304
|
zipOutDir,
|
|
296
305
|
`${fileSizeLimit}`,
|
|
297
306
|
], {
|
|
@@ -425,22 +434,20 @@ export class SsrSite extends Construct {
|
|
|
425
434
|
assumedBy: new AnyPrincipal(),
|
|
426
435
|
maxSessionDuration: CdkDuration.hours(12),
|
|
427
436
|
});
|
|
428
|
-
const
|
|
437
|
+
const ssrFn = new SsrFunction(this, `ServerFunction`, {
|
|
429
438
|
description: "Server handler placeholder",
|
|
430
|
-
|
|
439
|
+
bundle: path.join(__dirname, "../../support/ssr-site-function-stub"),
|
|
440
|
+
handler: "index.handler",
|
|
431
441
|
runtime,
|
|
432
442
|
memorySize,
|
|
433
443
|
timeout,
|
|
444
|
+
role,
|
|
434
445
|
bind,
|
|
435
446
|
environment,
|
|
436
447
|
permissions,
|
|
437
|
-
|
|
438
|
-
// Force enable live dev to prevent the function handler to be built
|
|
439
|
-
// in the case user set "enableLiveDev: false" on the app or stack.
|
|
440
|
-
enableLiveDev: true,
|
|
448
|
+
// note: do not need to set vpc settings b/c this function is not being used
|
|
441
449
|
});
|
|
442
|
-
|
|
443
|
-
return fn;
|
|
450
|
+
return ssrFn.function;
|
|
444
451
|
}
|
|
445
452
|
createFunctionPermissionsForRegional() {
|
|
446
453
|
this.bucket.grantReadWrite(this.serverLambdaForRegional.role);
|
|
@@ -466,6 +473,7 @@ export class SsrSite extends Construct {
|
|
|
466
473
|
function handler(event) {
|
|
467
474
|
var request = event.request;
|
|
468
475
|
request.headers["x-forwarded-host"] = request.headers.host;
|
|
476
|
+
${this.buildConfig.serverCFFunctionInjection || ""}
|
|
469
477
|
return request;
|
|
470
478
|
}`),
|
|
471
479
|
});
|
|
@@ -786,6 +794,10 @@ function handler(event) {
|
|
|
786
794
|
files: "**/*.js",
|
|
787
795
|
search: token,
|
|
788
796
|
replace: value,
|
|
797
|
+
}, {
|
|
798
|
+
files: "**/*.json",
|
|
799
|
+
search: token,
|
|
800
|
+
replace: value,
|
|
789
801
|
});
|
|
790
802
|
});
|
|
791
803
|
return replaceValues;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Function as CdkFunction } from "aws-cdk-lib/aws-lambda";
|
|
2
|
+
import { SsrSite } from "./SsrSite.js";
|
|
3
|
+
import { EdgeFunction } from "./EdgeFunction.js";
|
|
4
|
+
/**
|
|
5
|
+
* The `SvelteKitSite` construct is a higher level CDK construct that makes it easy to create a SvelteKit app.
|
|
6
|
+
* @example
|
|
7
|
+
* Deploys a SvelteKit app in the `my-svelte-app` directory.
|
|
8
|
+
*
|
|
9
|
+
* ```js
|
|
10
|
+
* new SvelteKitSite(stack, "web", {
|
|
11
|
+
* path: "my-svelte-app/",
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare class SvelteKitSite extends SsrSite {
|
|
16
|
+
protected initBuildConfig(): {
|
|
17
|
+
typesPath: string;
|
|
18
|
+
serverBuildOutputFile: string;
|
|
19
|
+
serverCFFunctionInjection: string;
|
|
20
|
+
clientBuildOutputDir: string;
|
|
21
|
+
clientBuildVersionedSubDir: string;
|
|
22
|
+
prerenderedBuildOutputDir: string;
|
|
23
|
+
};
|
|
24
|
+
protected createFunctionForRegional(): CdkFunction;
|
|
25
|
+
protected createFunctionForEdge(): EdgeFunction;
|
|
26
|
+
protected generateBuildId(): string;
|
|
27
|
+
}
|