sst 2.0.0-rc.56 → 2.0.0-rc.57
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/AppSyncApi.d.ts +2 -3
- package/constructs/AppSyncApi.js +3 -3
- package/constructs/Auth.js +10 -0
- package/constructs/EdgeFunction.d.ts +1 -1
- package/constructs/EdgeFunction.js +42 -55
- package/constructs/NextjsSite.js +7 -28
- package/constructs/SsrFunction.d.ts +21 -0
- package/constructs/SsrFunction.js +107 -0
- package/constructs/SsrSite.d.ts +4 -4
- package/constructs/SsrSite.js +20 -4
- package/constructs/Stack.js +1 -1
- package/constructs/deprecated/NextjsSite.js +2 -2
- package/constructs/util/appSyncApiDomain.d.ts +1 -1
- package/constructs/util/permission.js +0 -2
- package/package.json +15 -12
- package/runtime/handlers.js +1 -1
- package/sst.mjs +3 -2
- package/stacks/monitor.js +2 -1
- package/support/custom-resources/index.mjs +36531 -138
- /package/support/{edge-function-code-replacer → sls-nextjs-site-function-code-replacer}/lambda-code-updater.py +0 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export declare function weakImport(pkg: string): Promise<any>;
|
|
2
2
|
import { Construct } from "constructs";
|
|
3
3
|
import * as rds from "aws-cdk-lib/aws-rds";
|
|
4
|
-
import * as
|
|
5
|
-
import * as appsync from "@aws-cdk/aws-appsync-alpha";
|
|
4
|
+
import * as appsync from "aws-cdk-lib/aws-appsync";
|
|
6
5
|
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
|
|
7
6
|
import * as acm from "aws-cdk-lib/aws-certificatemanager";
|
|
8
7
|
import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
|
|
@@ -372,7 +371,7 @@ export declare class AppSyncApi extends Construct implements SSTConstruct {
|
|
|
372
371
|
};
|
|
373
372
|
private readonly props;
|
|
374
373
|
private _customDomainUrl?;
|
|
375
|
-
_cfnDomainName?:
|
|
374
|
+
_cfnDomainName?: appsync.CfnDomainName;
|
|
376
375
|
private readonly functionsByDsKey;
|
|
377
376
|
private readonly dataSourcesByDsKey;
|
|
378
377
|
private readonly dsKeysByResKey;
|
package/constructs/AppSyncApi.js
CHANGED
|
@@ -11,7 +11,7 @@ export async function weakImport(pkg) {
|
|
|
11
11
|
const { print, buildSchema } = await weakImport("graphql");
|
|
12
12
|
const { mergeTypeDefs } = await weakImport("@graphql-tools/merge");
|
|
13
13
|
import { Construct } from "constructs";
|
|
14
|
-
import * as appsync from "
|
|
14
|
+
import * as appsync from "aws-cdk-lib/aws-appsync";
|
|
15
15
|
import * as appSyncApiDomain from "./util/appSyncApiDomain.js";
|
|
16
16
|
import { getFunctionRef, isCDKConstruct } from "./Construct.js";
|
|
17
17
|
import { Function as Fn, } from "./Function.js";
|
|
@@ -314,8 +314,8 @@ export class AppSyncApi extends Construct {
|
|
|
314
314
|
if (domainData) {
|
|
315
315
|
this._cfnDomainName = this.cdk.graphqlApi.node.children.find((child) => child.cfnResourceType ===
|
|
316
316
|
"AWS::AppSync::DomainName");
|
|
317
|
-
const cfnDomainNameApiAssociation = this.cdk.graphqlApi.node.children.find((child) => child
|
|
318
|
-
|
|
317
|
+
const cfnDomainNameApiAssociation = this.cdk.graphqlApi.node.children.find((child) => child.cfnResourceType ===
|
|
318
|
+
"AWS::AppSync::DomainNameApiAssociation");
|
|
319
319
|
if (this._cfnDomainName && cfnDomainNameApiAssociation) {
|
|
320
320
|
cfnDomainNameApiAssociation.node.addDependency(this._cfnDomainName);
|
|
321
321
|
}
|
package/constructs/Auth.js
CHANGED
|
@@ -45,6 +45,16 @@ export class Auth extends Construct {
|
|
|
45
45
|
privatePath: getParameterPath(this, PRIVATE_KEY_PROP),
|
|
46
46
|
},
|
|
47
47
|
});
|
|
48
|
+
stack.customResourceHandler.role?.addToPrincipalPolicy(new PolicyStatement({
|
|
49
|
+
actions: [
|
|
50
|
+
"ssm:GetParameter",
|
|
51
|
+
"ssm:PutParameter",
|
|
52
|
+
"ssm:DeleteParameter",
|
|
53
|
+
],
|
|
54
|
+
resources: [
|
|
55
|
+
`arn:${stack.partition}:ssm:${stack.region}:${stack.account}:parameter/*`,
|
|
56
|
+
],
|
|
57
|
+
}));
|
|
48
58
|
}
|
|
49
59
|
/** @internal */
|
|
50
60
|
getConstructMetadata() {
|
|
@@ -32,11 +32,11 @@ export declare class EdgeFunction extends Construct {
|
|
|
32
32
|
private createAsset;
|
|
33
33
|
private createRole;
|
|
34
34
|
private createFunction;
|
|
35
|
-
private createSingletonAwsCliLayer;
|
|
36
35
|
private createLambdaCodeReplacer;
|
|
37
36
|
private createSingletonBucketCR;
|
|
38
37
|
private createFunctionCR;
|
|
39
38
|
private createVersionCR;
|
|
39
|
+
private getLambdaContentReplaceValues;
|
|
40
40
|
private updateVersionLogicalId;
|
|
41
41
|
private trimFromStart;
|
|
42
42
|
private calculateHash;
|
|
@@ -6,7 +6,6 @@ import { Construct } from "constructs";
|
|
|
6
6
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
7
7
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
8
8
|
import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
|
|
9
|
-
import { AwsCliLayer } from "aws-cdk-lib/lambda-layer-awscli";
|
|
10
9
|
import { Lazy, Duration, CustomResource } from "aws-cdk-lib";
|
|
11
10
|
import { Stack } from "./Stack.js";
|
|
12
11
|
import { attachPermissionsToRole } from "./util/permission.js";
|
|
@@ -23,7 +22,7 @@ export class EdgeFunction extends Construct {
|
|
|
23
22
|
constructor(scope, id, props) {
|
|
24
23
|
super(scope, id);
|
|
25
24
|
this.props = props;
|
|
26
|
-
const {
|
|
25
|
+
const { scopeOverride } = props;
|
|
27
26
|
// Correct scope
|
|
28
27
|
this.scope = scopeOverride || this;
|
|
29
28
|
// Wrap function code
|
|
@@ -63,7 +62,7 @@ const handler = async (event) => {
|
|
|
63
62
|
// replacer to inject the environment variables assigned to the
|
|
64
63
|
// EdgeFunction construct.
|
|
65
64
|
//
|
|
66
|
-
// "{{
|
|
65
|
+
// "{{ _SST_FUNCTION_ENVIRONMENT_ }}" will get replaced during
|
|
67
66
|
// deployment with an object of environment key-value pairs, ie.
|
|
68
67
|
// const environment = {"API_URL": "https://api.example.com"};
|
|
69
68
|
//
|
|
@@ -71,7 +70,7 @@ const handler = async (event) => {
|
|
|
71
70
|
// support runtime environment variables. A downside of this approach
|
|
72
71
|
// is that environment variables cannot be toggled after deployment,
|
|
73
72
|
// each change to one requires a redeployment.
|
|
74
|
-
const environment = "{{
|
|
73
|
+
const environment = "{{ _SST_FUNCTION_ENVIRONMENT_ }}";
|
|
75
74
|
process.env = { ...process.env, ...environment };
|
|
76
75
|
} catch (e) {
|
|
77
76
|
console.log("Failed to set SST Lambda@Edge environment.");
|
|
@@ -132,67 +131,29 @@ ${exports}
|
|
|
132
131
|
const versionId = versionCR.getAttString("Version");
|
|
133
132
|
this.updateVersionLogicalId(functionCR, versionCR);
|
|
134
133
|
// Deploy after the code is updated
|
|
135
|
-
const updaterCR = this.createLambdaCodeReplacer(
|
|
134
|
+
const updaterCR = this.createLambdaCodeReplacer(asset);
|
|
136
135
|
functionCR.node.addDependency(updaterCR);
|
|
137
136
|
return { functionArn, versionId };
|
|
138
137
|
}
|
|
139
|
-
|
|
140
|
-
// Do not recreate if exist
|
|
141
|
-
const resId = "AwsCliLayer";
|
|
142
|
-
const stack = Stack.of(this);
|
|
143
|
-
const existingResource = stack.node.tryFindChild(resId);
|
|
144
|
-
if (existingResource) {
|
|
145
|
-
return existingResource;
|
|
146
|
-
}
|
|
147
|
-
// Create custom resource
|
|
148
|
-
return new AwsCliLayer(stack, resId);
|
|
149
|
-
}
|
|
150
|
-
createLambdaCodeReplacer(name, asset) {
|
|
138
|
+
createLambdaCodeReplacer(asset) {
|
|
151
139
|
// Note: Source code for the Lambda functions have "{{ ENV_KEY }}" in them.
|
|
152
140
|
// They need to be replaced with real values before the Lambda
|
|
153
141
|
// functions get deployed.
|
|
154
|
-
const { format } = this.props;
|
|
155
|
-
const providerId = "LambdaCodeReplacerProvider";
|
|
156
|
-
const resId = `${name}LambdaCodeReplacer`;
|
|
157
142
|
const stack = Stack.of(this);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
provider = new lambda.Function(stack, providerId, {
|
|
162
|
-
code: lambda.Code.fromAsset(path.join(__dirname, "../support/edge-function-code-replacer")),
|
|
163
|
-
layers: [this.createSingletonAwsCliLayer()],
|
|
164
|
-
runtime: lambda.Runtime.PYTHON_3_7,
|
|
165
|
-
handler: "lambda-code-updater.handler",
|
|
166
|
-
timeout: Duration.minutes(15),
|
|
167
|
-
memorySize: 1024,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
// Allow provider to perform search/replace on the asset
|
|
171
|
-
provider.role?.addToPrincipalPolicy(new iam.PolicyStatement({
|
|
172
|
-
effect: iam.Effect.ALLOW,
|
|
173
|
-
actions: ["s3:*"],
|
|
174
|
-
resources: [
|
|
175
|
-
`arn:${stack.partition}:s3:::${asset.s3BucketName}/${asset.s3ObjectKey}`,
|
|
176
|
-
],
|
|
177
|
-
}));
|
|
178
|
-
// Create custom resource to replace the code
|
|
179
|
-
const resource = new CustomResource(this.scope, resId, {
|
|
180
|
-
serviceToken: provider.functionArn,
|
|
181
|
-
resourceType: "Custom::SSTLambdaCodeUpdater",
|
|
143
|
+
const resource = new CustomResource(this.scope, "AssetReplacer", {
|
|
144
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
145
|
+
resourceType: "Custom::AssetReplacer",
|
|
182
146
|
properties: {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
},
|
|
187
|
-
ReplaceValues: [
|
|
188
|
-
{
|
|
189
|
-
files: `index-wrapper.${format === "esm" ? "mjs" : "cjs"}`,
|
|
190
|
-
search: '"{{ _SST_EDGE_FUNCTION_ENVIRONMENT_ }}"',
|
|
191
|
-
replace: JSON.stringify(this.props.environment || {}),
|
|
192
|
-
},
|
|
193
|
-
],
|
|
147
|
+
bucket: asset.s3BucketName,
|
|
148
|
+
key: asset.s3ObjectKey,
|
|
149
|
+
replacements: this.getLambdaContentReplaceValues(),
|
|
194
150
|
},
|
|
195
151
|
});
|
|
152
|
+
stack.customResourceHandler.role?.addToPrincipalPolicy(new iam.PolicyStatement({
|
|
153
|
+
effect: iam.Effect.ALLOW,
|
|
154
|
+
actions: ["s3:GetObject", "s3:PutObject"],
|
|
155
|
+
resources: [`arn:${stack.partition}:s3:::${asset.s3BucketName}/*`],
|
|
156
|
+
}));
|
|
196
157
|
return resource;
|
|
197
158
|
}
|
|
198
159
|
createSingletonBucketCR() {
|
|
@@ -302,6 +263,32 @@ ${exports}
|
|
|
302
263
|
/////////////////////
|
|
303
264
|
// Internal Functions
|
|
304
265
|
/////////////////////
|
|
266
|
+
getLambdaContentReplaceValues() {
|
|
267
|
+
const { format } = this.props;
|
|
268
|
+
const replaceValues = [];
|
|
269
|
+
Object.entries(this.props.environment || {}).forEach(([key, value]) => {
|
|
270
|
+
const token = `{{ ${key} }}`;
|
|
271
|
+
replaceValues.push({
|
|
272
|
+
files: "**/*.js",
|
|
273
|
+
search: token,
|
|
274
|
+
replace: value,
|
|
275
|
+
}, {
|
|
276
|
+
files: "**/*.cjs",
|
|
277
|
+
search: token,
|
|
278
|
+
replace: value,
|
|
279
|
+
}, {
|
|
280
|
+
files: "**/*.mjs",
|
|
281
|
+
search: token,
|
|
282
|
+
replace: value,
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
replaceValues.push({
|
|
286
|
+
files: `index-wrapper.${format === "esm" ? "mjs" : "cjs"}`,
|
|
287
|
+
search: '"{{ _SST_FUNCTION_ENVIRONMENT_ }}"',
|
|
288
|
+
replace: JSON.stringify(this.props.environment || {}),
|
|
289
|
+
});
|
|
290
|
+
return replaceValues;
|
|
291
|
+
}
|
|
305
292
|
updateVersionLogicalId(functionCR, versionCR) {
|
|
306
293
|
// Override the version's logical ID with a lazy string which includes the
|
|
307
294
|
// hash of the function itself, so a new version resource is created when
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import url from "url";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import spawn from "cross-spawn";
|
|
5
4
|
import { Fn, Duration, RemovalPolicy } from "aws-cdk-lib";
|
|
6
5
|
import * as logs from "aws-cdk-lib/aws-logs";
|
|
7
6
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
8
7
|
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
|
|
9
8
|
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
|
|
10
|
-
import {
|
|
9
|
+
import { SsrFunction } from "./SsrFunction.js";
|
|
11
10
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
12
11
|
import { SsrSite } from "./SsrSite.js";
|
|
13
12
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
@@ -38,36 +37,16 @@ export class NextjsSite extends SsrSite {
|
|
|
38
37
|
}
|
|
39
38
|
createFunctionForRegional() {
|
|
40
39
|
const { defaults, environment } = this.props;
|
|
41
|
-
|
|
42
|
-
// b/c the folder contains node_modules. And pnpm node_modules
|
|
43
|
-
// contains symlinks. CDK cannot zip symlinks correctly.
|
|
44
|
-
// https://github.com/aws/aws-cdk/issues/9251
|
|
45
|
-
// We will zip the folder ourselves.
|
|
46
|
-
const zipOutDir = path.resolve(path.join(useProject().paths.artifacts, `Site-${this.node.id}-${this.node.addr}`));
|
|
47
|
-
const script = path.resolve(__dirname, "../support/ssr-site-function-archiver.mjs");
|
|
48
|
-
const result = spawn.sync("node", [
|
|
49
|
-
script,
|
|
50
|
-
path.join(this.props.path, ".open-next", "server-function"),
|
|
51
|
-
path.join(zipOutDir, "server-function.zip"),
|
|
52
|
-
], {
|
|
53
|
-
stdio: "inherit",
|
|
54
|
-
});
|
|
55
|
-
if (result.status !== 0) {
|
|
56
|
-
throw new Error(`There was a problem generating the assets package.`);
|
|
57
|
-
}
|
|
58
|
-
return new lambda.Function(this, `ServerFunction`, {
|
|
40
|
+
const ssrFn = new SsrFunction(this, `ServerFunction`, {
|
|
59
41
|
description: "Server handler for Next.js",
|
|
42
|
+
bundlePath: path.join(this.props.path, ".open-next", "server-function"),
|
|
60
43
|
handler: "index.handler",
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
logRetention: logs.RetentionDays.THREE_DAYS,
|
|
65
|
-
code: lambda.Code.fromAsset(path.join(zipOutDir, "server-function.zip")),
|
|
66
|
-
runtime: lambda.Runtime.NODEJS_18_X,
|
|
67
|
-
memorySize: defaults?.function?.memorySize || 512,
|
|
68
|
-
timeout: Duration.seconds(defaults?.function?.timeout || 10),
|
|
44
|
+
timeout: defaults?.function?.timeout,
|
|
45
|
+
memory: defaults?.function?.memorySize,
|
|
46
|
+
permissions: defaults?.function?.permissions,
|
|
69
47
|
environment,
|
|
70
48
|
});
|
|
49
|
+
return ssrFn.function;
|
|
71
50
|
}
|
|
72
51
|
createImageOptimizationFunctionForRegional() {
|
|
73
52
|
const { defaults, path: sitePath } = this.props;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
3
|
+
import { Permissions } from "./util/permission.js";
|
|
4
|
+
export interface SsrFunctionProps {
|
|
5
|
+
description?: string;
|
|
6
|
+
bundlePath: string;
|
|
7
|
+
handler: string;
|
|
8
|
+
timeout?: number;
|
|
9
|
+
memory?: number;
|
|
10
|
+
permissions?: Permissions;
|
|
11
|
+
environment?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
export declare class SsrFunction extends Construct {
|
|
14
|
+
function: lambda.Function;
|
|
15
|
+
private props;
|
|
16
|
+
constructor(scope: Construct, id: string, props: SsrFunctionProps);
|
|
17
|
+
attachPermissions(permissions: Permissions): void;
|
|
18
|
+
private createFunction;
|
|
19
|
+
private createLambdaCodeReplacer;
|
|
20
|
+
private getLambdaContentReplaceValues;
|
|
21
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import url from "url";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import spawn from "cross-spawn";
|
|
4
|
+
import { Construct } from "constructs";
|
|
5
|
+
import * as iam from "aws-cdk-lib/aws-iam";
|
|
6
|
+
import * as logs from "aws-cdk-lib/aws-logs";
|
|
7
|
+
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
8
|
+
import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
|
|
9
|
+
import { Duration, CustomResource } from "aws-cdk-lib";
|
|
10
|
+
import { Stack } from "./Stack.js";
|
|
11
|
+
import { useProject } from "../project.js";
|
|
12
|
+
import { attachPermissionsToRole } from "./util/permission.js";
|
|
13
|
+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
14
|
+
/////////////////////
|
|
15
|
+
// Construct
|
|
16
|
+
/////////////////////
|
|
17
|
+
export class SsrFunction extends Construct {
|
|
18
|
+
function;
|
|
19
|
+
props;
|
|
20
|
+
constructor(scope, id, props) {
|
|
21
|
+
super(scope, id);
|
|
22
|
+
this.props = props;
|
|
23
|
+
const { permissions } = props;
|
|
24
|
+
this.function = this.createFunction();
|
|
25
|
+
this.attachPermissions(permissions || []);
|
|
26
|
+
}
|
|
27
|
+
attachPermissions(permissions) {
|
|
28
|
+
attachPermissionsToRole(this.function.role, permissions);
|
|
29
|
+
}
|
|
30
|
+
createFunction() {
|
|
31
|
+
const { timeout, memory, handler, bundlePath, environment } = this.props;
|
|
32
|
+
// Note: cannot point the bundlePath to the `.open-next/server-function`
|
|
33
|
+
// b/c the folder contains node_modules. And pnpm node_modules
|
|
34
|
+
// contains symlinks. CDK cannot zip symlinks correctly.
|
|
35
|
+
// https://github.com/aws/aws-cdk/issues/9251
|
|
36
|
+
// We will zip the folder ourselves.
|
|
37
|
+
const zipOutDir = path.resolve(useProject().paths.artifacts, `Site-${this.node.id}-${this.node.addr}`);
|
|
38
|
+
const script = path.resolve(__dirname, "../support/ssr-site-function-archiver.mjs");
|
|
39
|
+
const result = spawn.sync("node", [
|
|
40
|
+
script,
|
|
41
|
+
path.join(bundlePath),
|
|
42
|
+
path.join(zipOutDir, "server-function.zip"),
|
|
43
|
+
], { stdio: "inherit" });
|
|
44
|
+
if (result.status !== 0) {
|
|
45
|
+
throw new Error(`There was a problem generating the assets package.`);
|
|
46
|
+
}
|
|
47
|
+
// Create asset
|
|
48
|
+
const asset = new s3Assets.Asset(this, "Asset", {
|
|
49
|
+
path: path.join(zipOutDir, "server-function.zip"),
|
|
50
|
+
});
|
|
51
|
+
// Deploy after the code is updated
|
|
52
|
+
const replacer = this.createLambdaCodeReplacer(asset);
|
|
53
|
+
const fn = new lambda.Function(this, `ServerFunction`, {
|
|
54
|
+
description: this.props.description,
|
|
55
|
+
handler,
|
|
56
|
+
logRetention: logs.RetentionDays.THREE_DAYS,
|
|
57
|
+
code: lambda.Code.fromBucket(asset.bucket, asset.s3ObjectKey),
|
|
58
|
+
runtime: lambda.Runtime.NODEJS_18_X,
|
|
59
|
+
memorySize: memory || 512,
|
|
60
|
+
timeout: Duration.seconds(timeout || 10),
|
|
61
|
+
environment,
|
|
62
|
+
});
|
|
63
|
+
fn.node.addDependency(replacer);
|
|
64
|
+
return fn;
|
|
65
|
+
}
|
|
66
|
+
createLambdaCodeReplacer(asset) {
|
|
67
|
+
// Note: Source code for the Lambda functions have "{{ ENV_KEY }}" in them.
|
|
68
|
+
// They need to be replaced with real values before the Lambda
|
|
69
|
+
// functions get deployed.
|
|
70
|
+
const stack = Stack.of(this);
|
|
71
|
+
const resource = new CustomResource(this, "AssetReplacer", {
|
|
72
|
+
serviceToken: stack.customResourceHandler.functionArn,
|
|
73
|
+
resourceType: "Custom::AssetReplacer",
|
|
74
|
+
properties: {
|
|
75
|
+
bucket: asset.s3BucketName,
|
|
76
|
+
key: asset.s3ObjectKey,
|
|
77
|
+
replacements: this.getLambdaContentReplaceValues(),
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
stack.customResourceHandler.role?.addToPrincipalPolicy(new iam.PolicyStatement({
|
|
81
|
+
effect: iam.Effect.ALLOW,
|
|
82
|
+
actions: ["s3:GetObject", "s3:PutObject"],
|
|
83
|
+
resources: [`arn:${stack.partition}:s3:::${asset.s3BucketName}/*`],
|
|
84
|
+
}));
|
|
85
|
+
return resource;
|
|
86
|
+
}
|
|
87
|
+
getLambdaContentReplaceValues() {
|
|
88
|
+
const replaceValues = [];
|
|
89
|
+
Object.entries(this.props.environment || {}).forEach(([key, value]) => {
|
|
90
|
+
const token = `{{ ${key} }}`;
|
|
91
|
+
replaceValues.push({
|
|
92
|
+
files: "**/*.js",
|
|
93
|
+
search: token,
|
|
94
|
+
replace: value,
|
|
95
|
+
}, {
|
|
96
|
+
files: "**/*.cjs",
|
|
97
|
+
search: token,
|
|
98
|
+
replace: value,
|
|
99
|
+
}, {
|
|
100
|
+
files: "**/*.mjs",
|
|
101
|
+
search: token,
|
|
102
|
+
replace: value,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
return replaceValues;
|
|
106
|
+
}
|
|
107
|
+
}
|
package/constructs/SsrSite.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import * as acm from "aws-cdk-lib/aws-certificatemanager";
|
|
|
7
7
|
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
|
|
8
8
|
import { SSTConstruct } from "./Construct.js";
|
|
9
9
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
10
|
-
import { BaseSiteDomainProps, BaseSiteCdkDistributionProps } from "./BaseSite.js";
|
|
10
|
+
import { BaseSiteDomainProps, BaseSiteReplaceProps, BaseSiteCdkDistributionProps } from "./BaseSite.js";
|
|
11
11
|
import { Permissions } from "./util/permission.js";
|
|
12
12
|
import { FunctionBindingProps } from "./util/functionBinding.js";
|
|
13
13
|
export type SsrBuildConfig = {
|
|
@@ -17,6 +17,8 @@ export type SsrBuildConfig = {
|
|
|
17
17
|
};
|
|
18
18
|
export interface SsrDomainProps extends BaseSiteDomainProps {
|
|
19
19
|
}
|
|
20
|
+
export interface SsrSiteReplaceProps extends BaseSiteReplaceProps {
|
|
21
|
+
}
|
|
20
22
|
export interface SsrCdkDistributionProps extends BaseSiteCdkDistributionProps {
|
|
21
23
|
}
|
|
22
24
|
export interface SsrSiteProps {
|
|
@@ -155,9 +157,6 @@ export declare class SsrSite extends Construct implements SSTConstruct {
|
|
|
155
157
|
path: string;
|
|
156
158
|
};
|
|
157
159
|
private doNotDeploy;
|
|
158
|
-
/**
|
|
159
|
-
* The root SST directory used for builds.
|
|
160
|
-
*/
|
|
161
160
|
protected buildConfig: SsrBuildConfig;
|
|
162
161
|
private serverLambdaForEdge?;
|
|
163
162
|
protected serverLambdaForRegional?: lambda.Function;
|
|
@@ -229,6 +228,7 @@ export declare class SsrSite extends Construct implements SSTConstruct {
|
|
|
229
228
|
protected lookupHostedZone(): route53.IHostedZone | undefined;
|
|
230
229
|
private createCertificate;
|
|
231
230
|
protected createRoute53Records(): void;
|
|
231
|
+
private getS3ContentReplaceValues;
|
|
232
232
|
private validateSiteExists;
|
|
233
233
|
private registerSiteEnvironment;
|
|
234
234
|
protected generateBuildId(): string;
|
package/constructs/SsrSite.js
CHANGED
|
@@ -6,7 +6,7 @@ import crypto from "crypto";
|
|
|
6
6
|
import spawn from "cross-spawn";
|
|
7
7
|
import { execSync } from "child_process";
|
|
8
8
|
import { Construct } from "constructs";
|
|
9
|
-
import { Fn, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
|
|
9
|
+
import { Fn, Token, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
|
|
10
10
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
11
11
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
12
12
|
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
@@ -43,9 +43,6 @@ export class SsrSite extends Construct {
|
|
|
43
43
|
id;
|
|
44
44
|
props;
|
|
45
45
|
doNotDeploy;
|
|
46
|
-
/**
|
|
47
|
-
* The root SST directory used for builds.
|
|
48
|
-
*/
|
|
49
46
|
buildConfig;
|
|
50
47
|
serverLambdaForEdge;
|
|
51
48
|
serverLambdaForRegional;
|
|
@@ -384,6 +381,7 @@ export class SsrSite extends Construct {
|
|
|
384
381
|
cacheControl,
|
|
385
382
|
];
|
|
386
383
|
}),
|
|
384
|
+
ReplaceValues: this.getS3ContentReplaceValues(),
|
|
387
385
|
},
|
|
388
386
|
});
|
|
389
387
|
}
|
|
@@ -704,6 +702,24 @@ export class SsrSite extends Construct {
|
|
|
704
702
|
/////////////////////
|
|
705
703
|
// Helper Functions
|
|
706
704
|
/////////////////////
|
|
705
|
+
getS3ContentReplaceValues() {
|
|
706
|
+
const replaceValues = [];
|
|
707
|
+
Object.entries(this.props.environment || {})
|
|
708
|
+
.filter(([, value]) => Token.isUnresolved(value))
|
|
709
|
+
.forEach(([key, value]) => {
|
|
710
|
+
const token = `{{ ${key} }}`;
|
|
711
|
+
replaceValues.push({
|
|
712
|
+
files: "**/*.html",
|
|
713
|
+
search: token,
|
|
714
|
+
replace: value,
|
|
715
|
+
}, {
|
|
716
|
+
files: "**/*.js",
|
|
717
|
+
search: token,
|
|
718
|
+
replace: value,
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
return replaceValues;
|
|
722
|
+
}
|
|
707
723
|
validateSiteExists() {
|
|
708
724
|
const { path: sitePath } = this.props;
|
|
709
725
|
if (!fs.existsSync(sitePath)) {
|
package/constructs/Stack.js
CHANGED
|
@@ -174,7 +174,7 @@ export class Stack extends cdk.Stack {
|
|
|
174
174
|
createCustomResourceHandler() {
|
|
175
175
|
return new lambda.Function(this, "CustomResourceHandler", {
|
|
176
176
|
code: lambda.Code.fromAsset(path.join(__dirname, "../support/custom-resources/"), {
|
|
177
|
-
assetHash: this.stackName + "-custom-resources-
|
|
177
|
+
assetHash: this.stackName + "-custom-resources-20230130",
|
|
178
178
|
}),
|
|
179
179
|
handler: "index.handler",
|
|
180
180
|
runtime: lambda.Runtime.NODEJS_16_X,
|
|
@@ -265,7 +265,7 @@ export class NextjsSite extends Construct {
|
|
|
265
265
|
throw new Error(`No build output found at "${siteOutputPath}" for the "${this.node.id}" NextjsSite.`);
|
|
266
266
|
}
|
|
267
267
|
// create zip files
|
|
268
|
-
const script = path.join(__dirname, "../../support/base-site-archiver.
|
|
268
|
+
const script = path.join(__dirname, "../../support/base-site-archiver.mjs");
|
|
269
269
|
const zipPath = path.resolve(path.join(this.sstBuildDir, `NextjsSite-${this.node.id}-${this.node.addr}`));
|
|
270
270
|
// clear zip path to ensure no partX.zip remain from previous build
|
|
271
271
|
fs.rmSync(zipPath, {
|
|
@@ -461,7 +461,7 @@ export class NextjsSite extends Construct {
|
|
|
461
461
|
// Create provider if not already created
|
|
462
462
|
if (!provider) {
|
|
463
463
|
provider = new lambda.Function(stack, providerId, {
|
|
464
|
-
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/
|
|
464
|
+
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/sls-nextjs-site-function-code-replacer")),
|
|
465
465
|
layers: [this.awsCliLayer],
|
|
466
466
|
runtime: lambda.Runtime.PYTHON_3_7,
|
|
467
467
|
handler: "lambda-code-updater.handler",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as route53 from "aws-cdk-lib/aws-route53";
|
|
2
|
-
import * as appsync from "
|
|
2
|
+
import * as appsync from "aws-cdk-lib/aws-appsync";
|
|
3
3
|
import * as acm from "aws-cdk-lib/aws-certificatemanager";
|
|
4
4
|
import { AppSyncApi } from "../AppSyncApi.js";
|
|
5
5
|
export interface CustomDomainProps {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/ban-ts-comment*/
|
|
2
2
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
3
3
|
import { isCDKConstruct, isCDKConstructOf } from "../Construct.js";
|
|
4
|
-
import { Logger } from "../../logger.js";
|
|
5
4
|
import { Api } from "../Api.js";
|
|
6
5
|
import { ApiGatewayV1Api } from "../ApiGatewayV1Api.js";
|
|
7
6
|
import { Stack } from "../Stack.js";
|
|
@@ -212,7 +211,6 @@ function permissionsToStatementsAndGrants(permissions) {
|
|
|
212
211
|
grants.push(permission);
|
|
213
212
|
}
|
|
214
213
|
else {
|
|
215
|
-
Logger.debug("permission object", permission);
|
|
216
214
|
throw new Error(`The specified permissions are not supported.`);
|
|
217
215
|
}
|
|
218
216
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sst",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.57",
|
|
4
4
|
"bin": {
|
|
5
5
|
"sst": "cli/sst.js"
|
|
6
6
|
},
|
|
@@ -22,14 +22,13 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://sst.dev",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@aws-cdk/aws-apigatewayv2-alpha": "^2.
|
|
26
|
-
"@aws-cdk/aws-apigatewayv2-authorizers-alpha": "^2.
|
|
27
|
-
"@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.
|
|
28
|
-
"@aws-cdk/
|
|
29
|
-
"@aws-cdk/
|
|
30
|
-
"@aws-cdk/
|
|
31
|
-
"@aws-cdk/
|
|
32
|
-
"@aws-cdk/region-info": "2.55.0",
|
|
25
|
+
"@aws-cdk/aws-apigatewayv2-alpha": "^2.62.2-alpha.0",
|
|
26
|
+
"@aws-cdk/aws-apigatewayv2-authorizers-alpha": "^2.62.2-alpha.0",
|
|
27
|
+
"@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.62.2-alpha.0",
|
|
28
|
+
"@aws-cdk/cloud-assembly-schema": "2.62.2",
|
|
29
|
+
"@aws-cdk/cloudformation-diff": "2.62.2",
|
|
30
|
+
"@aws-cdk/cx-api": "2.62.2",
|
|
31
|
+
"@aws-cdk/region-info": "2.62.2",
|
|
33
32
|
"@aws-sdk/client-cloudformation": "3.208.0",
|
|
34
33
|
"@aws-sdk/client-iot": "3.208.0",
|
|
35
34
|
"@aws-sdk/client-iot-data-plane": "3.208.0",
|
|
@@ -47,13 +46,14 @@
|
|
|
47
46
|
"@babel/core": "^7.0.0-0",
|
|
48
47
|
"@babel/generator": "^7.20.5",
|
|
49
48
|
"@trpc/server": "9.16.0",
|
|
49
|
+
"adm-zip": "^0.5.10",
|
|
50
50
|
"archiver": "^5.3.1",
|
|
51
|
-
"aws-cdk": "2.
|
|
52
|
-
"aws-cdk-lib": "2.
|
|
51
|
+
"aws-cdk": "2.62.2",
|
|
52
|
+
"aws-cdk-lib": "2.62.2",
|
|
53
53
|
"aws-iot-device-sdk": "^2.2.12",
|
|
54
54
|
"aws-sdk": "2.1252.0",
|
|
55
55
|
"builtin-modules": "3.2.0",
|
|
56
|
-
"cdk-assets": "2.
|
|
56
|
+
"cdk-assets": "2.62.2",
|
|
57
57
|
"chalk": "^4.1.2",
|
|
58
58
|
"chokidar": "^3.5.3",
|
|
59
59
|
"ci-info": "^3.7.0",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"kysely": "^0.23.3",
|
|
77
77
|
"kysely-codegen": "^0.9.0",
|
|
78
78
|
"kysely-data-api": "^0.1.4",
|
|
79
|
+
"minimatch": "^6.1.6",
|
|
79
80
|
"openid-client": "^5.1.8",
|
|
80
81
|
"ora": "^6.1.2",
|
|
81
82
|
"promptly": "^3.2.0",
|
|
@@ -93,6 +94,7 @@
|
|
|
93
94
|
"@aws-sdk/types": "^3.208.0",
|
|
94
95
|
"@sls-next/lambda-at-edge": "^3.7.0",
|
|
95
96
|
"@tsconfig/node16": "^1.0.3",
|
|
97
|
+
"@types/adm-zip": "^0.5.0",
|
|
96
98
|
"@types/aws-iot-device-sdk": "^2.2.4",
|
|
97
99
|
"@types/aws-lambda": "^8.10.108",
|
|
98
100
|
"@types/babel__core": "^7.1.20",
|
|
@@ -127,6 +129,7 @@
|
|
|
127
129
|
"author": "",
|
|
128
130
|
"scripts": {
|
|
129
131
|
"build": "node build.mjs && tsc",
|
|
132
|
+
"test": "vitest run",
|
|
130
133
|
"dev": "tsc -w"
|
|
131
134
|
}
|
|
132
135
|
}
|
package/runtime/handlers.js
CHANGED
|
@@ -19,7 +19,7 @@ export const useRuntimeHandlers = Context.memo(() => {
|
|
|
19
19
|
for: (runtime) => {
|
|
20
20
|
const result = handlers.find((x) => x.canHandle(runtime));
|
|
21
21
|
if (!result)
|
|
22
|
-
throw new Error(
|
|
22
|
+
throw new Error(`${runtime} runtime is unsupported`);
|
|
23
23
|
return result;
|
|
24
24
|
},
|
|
25
25
|
async build(functionID, mode) {
|
package/sst.mjs
CHANGED
|
@@ -1344,7 +1344,8 @@ async function monitor(stack) {
|
|
|
1344
1344
|
]);
|
|
1345
1345
|
Logger.debug("Stack description", describe);
|
|
1346
1346
|
if (lastEvent) {
|
|
1347
|
-
|
|
1347
|
+
const eventsReversed = [...events.StackEvents ?? []].reverse();
|
|
1348
|
+
for (const event of eventsReversed) {
|
|
1348
1349
|
if (!event.Timestamp)
|
|
1349
1350
|
continue;
|
|
1350
1351
|
if (event.Timestamp.getTime() > lastEvent.getTime()) {
|
|
@@ -2861,7 +2862,7 @@ var init_handlers = __esm({
|
|
|
2861
2862
|
for: (runtime) => {
|
|
2862
2863
|
const result2 = handlers.find((x) => x.canHandle(runtime));
|
|
2863
2864
|
if (!result2)
|
|
2864
|
-
throw new Error(
|
|
2865
|
+
throw new Error(`${runtime} runtime is unsupported`);
|
|
2865
2866
|
return result2;
|
|
2866
2867
|
},
|
|
2867
2868
|
async build(functionID, mode) {
|