sst 2.1.20 → 2.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constructs/AstroSite.js +7 -3
- package/constructs/EdgeFunction.d.ts +9 -6
- package/constructs/EdgeFunction.js +92 -81
- package/constructs/NextjsSite.d.ts +6 -6
- package/constructs/NextjsSite.js +35 -33
- package/constructs/RemixSite.js +17 -6
- package/constructs/SolidStartSite.js +7 -3
- package/constructs/SsrSite.d.ts +7 -0
- package/package.json +1 -1
- package/runtime/handlers/node.js +47 -31
- package/sst.mjs +57 -39
- package/support/remix-site-function/edge-server.js +2 -2
package/constructs/AstroSite.js
CHANGED
|
@@ -32,7 +32,7 @@ export class AstroSite extends SsrSite {
|
|
|
32
32
|
super.validateBuildOutput();
|
|
33
33
|
}
|
|
34
34
|
createFunctionForRegional() {
|
|
35
|
-
const { runtime, timeout, memorySize, permissions, environment, bind, cdk, } = this.props;
|
|
35
|
+
const { runtime, timeout, memorySize, permissions, environment, nodejs, bind, cdk, } = this.props;
|
|
36
36
|
const fn = new Function(this, `ServerFunction`, {
|
|
37
37
|
description: "Server handler",
|
|
38
38
|
handler: path.join(this.props.path, "dist", "server", "entry.handler"),
|
|
@@ -42,6 +42,7 @@ export class AstroSite extends SsrSite {
|
|
|
42
42
|
timeout,
|
|
43
43
|
nodejs: {
|
|
44
44
|
format: "esm",
|
|
45
|
+
...nodejs,
|
|
45
46
|
},
|
|
46
47
|
bind,
|
|
47
48
|
environment,
|
|
@@ -53,7 +54,7 @@ export class AstroSite extends SsrSite {
|
|
|
53
54
|
return fn;
|
|
54
55
|
}
|
|
55
56
|
createFunctionForEdge() {
|
|
56
|
-
const { runtime, timeout, memorySize, bind, permissions, environment } = this.props;
|
|
57
|
+
const { runtime, timeout, memorySize, bind, permissions, environment, nodejs, } = this.props;
|
|
57
58
|
return new EdgeFunction(this, `Server`, {
|
|
58
59
|
scopeOverride: this,
|
|
59
60
|
handler: path.join(this.props.path, "dist", "server", "entry.handler"),
|
|
@@ -63,7 +64,10 @@ export class AstroSite extends SsrSite {
|
|
|
63
64
|
bind,
|
|
64
65
|
environment,
|
|
65
66
|
permissions,
|
|
66
|
-
|
|
67
|
+
nodejs: {
|
|
68
|
+
format: "esm",
|
|
69
|
+
...nodejs,
|
|
70
|
+
},
|
|
67
71
|
});
|
|
68
72
|
}
|
|
69
73
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BuildOptions } from "esbuild";
|
|
2
1
|
import { Construct, IConstruct } from "constructs";
|
|
3
2
|
import { Role } from "aws-cdk-lib/aws-iam";
|
|
4
3
|
import { IVersion } from "aws-cdk-lib/aws-lambda";
|
|
5
4
|
import { SSTConstruct } from "./Construct.js";
|
|
5
|
+
import { NodeJSProps } from "./Function.js";
|
|
6
6
|
import { Size } from "./util/size.js";
|
|
7
7
|
import { Duration } from "./util/duration.js";
|
|
8
8
|
import { Permissions } from "./util/permission.js";
|
|
@@ -15,13 +15,15 @@ export interface EdgeFunctionProps {
|
|
|
15
15
|
permissions?: Permissions;
|
|
16
16
|
environment?: Record<string, string>;
|
|
17
17
|
bind?: SSTConstruct[];
|
|
18
|
-
|
|
19
|
-
format: "cjs" | "esm";
|
|
18
|
+
nodejs?: NodeJSProps;
|
|
20
19
|
scopeOverride?: IConstruct;
|
|
21
20
|
}
|
|
22
21
|
export declare class EdgeFunction extends Construct {
|
|
23
22
|
role: Role;
|
|
24
23
|
functionArn: string;
|
|
24
|
+
private function;
|
|
25
|
+
private assetReplacer;
|
|
26
|
+
private assetReplacerPolicy;
|
|
25
27
|
private scope;
|
|
26
28
|
private versionId;
|
|
27
29
|
private bindingEnvs;
|
|
@@ -29,14 +31,15 @@ export declare class EdgeFunction extends Construct {
|
|
|
29
31
|
constructor(scope: Construct, id: string, props: EdgeFunctionProps);
|
|
30
32
|
get currentVersion(): IVersion;
|
|
31
33
|
attachPermissions(permissions: Permissions): void;
|
|
32
|
-
private
|
|
33
|
-
private
|
|
34
|
+
private buildAssetFromHandler;
|
|
35
|
+
private buildAssetFromBundle;
|
|
34
36
|
private bind;
|
|
35
|
-
private createCodeAsset;
|
|
36
37
|
private createCodeReplacer;
|
|
38
|
+
private updateCodeReplacer;
|
|
37
39
|
private createRole;
|
|
38
40
|
private createSingletonBucketInUsEast1;
|
|
39
41
|
private createFunctionInUsEast1;
|
|
42
|
+
private updateFunctionInUsEast1;
|
|
40
43
|
private createVersionInUsEast1;
|
|
41
44
|
private getHandlerExtension;
|
|
42
45
|
private trimFromStart;
|
|
@@ -2,14 +2,16 @@ import fs from "fs";
|
|
|
2
2
|
import url from "url";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import crypto from "crypto";
|
|
5
|
-
import { buildSync } from "esbuild";
|
|
6
5
|
import { Construct } from "constructs";
|
|
7
6
|
import { Effect, Role, Policy, PolicyStatement, CompositePrincipal, ServicePrincipal, ManagedPolicy, } from "aws-cdk-lib/aws-iam";
|
|
8
7
|
import { Version, Code, Runtime, Function as CdkFunction, } from "aws-cdk-lib/aws-lambda";
|
|
9
8
|
import { Asset } from "aws-cdk-lib/aws-s3-assets";
|
|
10
9
|
import { Lazy, Duration as CdkDuration, CustomResource, } from "aws-cdk-lib";
|
|
11
10
|
import { useProject } from "../project.js";
|
|
11
|
+
import { useRuntimeHandlers } from "../runtime/handlers.js";
|
|
12
12
|
import { Stack } from "./Stack.js";
|
|
13
|
+
import { useFunctions } from "./Function.js";
|
|
14
|
+
import { useDeferredTasks } from "./deferred_task.js";
|
|
13
15
|
import { bindEnvironment, bindPermissions, getReferencedSecrets, } from "./util/functionBinding.js";
|
|
14
16
|
import { toCdkSize } from "./util/size.js";
|
|
15
17
|
import { toCdkDuration } from "./util/duration.js";
|
|
@@ -21,6 +23,9 @@ const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
|
21
23
|
export class EdgeFunction extends Construct {
|
|
22
24
|
role;
|
|
23
25
|
functionArn;
|
|
26
|
+
function;
|
|
27
|
+
assetReplacer;
|
|
28
|
+
assetReplacerPolicy;
|
|
24
29
|
scope;
|
|
25
30
|
versionId;
|
|
26
31
|
bindingEnvs;
|
|
@@ -36,29 +41,46 @@ export class EdgeFunction extends Construct {
|
|
|
36
41
|
this.scope = props.scopeOverride || this;
|
|
37
42
|
this.props = {
|
|
38
43
|
...props,
|
|
39
|
-
bundle: props.bundle || "placeholder",
|
|
40
44
|
environment: props.environment || {},
|
|
41
45
|
permissions: props.permissions || [],
|
|
42
46
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
const { assetBucket, assetKey, handlerFilename } = (props.bundle
|
|
48
|
+
? // Case: bundle is pre-built
|
|
49
|
+
() => {
|
|
50
|
+
const { asset, handlerFilename } = this.buildAssetFromBundle(props.bundle, props.handler);
|
|
51
|
+
return {
|
|
52
|
+
assetBucket: asset.s3BucketName,
|
|
53
|
+
assetKey: asset.s3ObjectKey,
|
|
54
|
+
handlerFilename,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
: // Case: bundle is NOT pre-built
|
|
58
|
+
() => {
|
|
59
|
+
this.buildAssetFromHandler((asset, handlerFilename) => {
|
|
60
|
+
this.updateCodeReplacer(asset.s3BucketName, asset.s3ObjectKey, handlerFilename);
|
|
61
|
+
this.updateFunctionInUsEast1(asset.s3BucketName, asset.s3ObjectKey);
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
assetBucket: "placeholder",
|
|
65
|
+
assetKey: "placeholder",
|
|
66
|
+
handlerFilename: "placeholder",
|
|
67
|
+
};
|
|
68
|
+
})();
|
|
49
69
|
// Bind first b/e function's environment variables cannot be added after
|
|
50
70
|
this.bindingEnvs = {};
|
|
51
71
|
this.bind(props.bind || []);
|
|
52
|
-
const
|
|
53
|
-
const assetReplacer = this.createCodeReplacer(asset, handlerFilename);
|
|
72
|
+
const { assetReplacer, assetReplacerPolicy } = this.createCodeReplacer(assetBucket, assetKey, handlerFilename);
|
|
54
73
|
this.role = this.createRole();
|
|
55
|
-
const
|
|
56
|
-
const { fn, fnArn } = this.createFunctionInUsEast1(
|
|
74
|
+
const lambdaBucket = this.createSingletonBucketInUsEast1();
|
|
75
|
+
const { fn, fnArn } = this.createFunctionInUsEast1(assetBucket, assetKey, lambdaBucket);
|
|
57
76
|
const { versionId } = this.createVersionInUsEast1(fn, fnArn);
|
|
58
77
|
// Deploy after the code is updated
|
|
59
78
|
fn.node.addDependency(assetReplacer);
|
|
79
|
+
this.function = fn;
|
|
60
80
|
this.functionArn = fnArn;
|
|
61
81
|
this.versionId = versionId;
|
|
82
|
+
this.assetReplacer = assetReplacer;
|
|
83
|
+
this.assetReplacerPolicy = assetReplacerPolicy;
|
|
62
84
|
}
|
|
63
85
|
get currentVersion() {
|
|
64
86
|
return Version.fromVersionArn(this, `${this.node.id}FunctionVersion`, `${this.functionArn}:${this.versionId}`);
|
|
@@ -66,60 +88,35 @@ export class EdgeFunction extends Construct {
|
|
|
66
88
|
attachPermissions(permissions) {
|
|
67
89
|
attachPermissionsToRole(this.role, permissions);
|
|
68
90
|
}
|
|
69
|
-
|
|
70
|
-
const {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
banner: {
|
|
96
|
-
js: [
|
|
97
|
-
`import { createRequire as topLevelCreateRequire } from 'module';`,
|
|
98
|
-
`const require = topLevelCreateRequire(import.meta.url);`,
|
|
99
|
-
`import { fileURLToPath as topLevelFileUrlToPath } from "url"`,
|
|
100
|
-
`const __dirname = topLevelFileUrlToPath(new URL(".", import.meta.url))`,
|
|
101
|
-
`process.env = { ...process.env, ..."{{ _SST_FUNCTION_ENVIRONMENT_ }}" };`,
|
|
102
|
-
].join("\n"),
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
: {
|
|
106
|
-
format: "cjs",
|
|
107
|
-
target: "node14",
|
|
108
|
-
}),
|
|
109
|
-
outfile: path.join(outputPath, outputFilename + outputFileExt),
|
|
110
|
-
...override,
|
|
91
|
+
buildAssetFromHandler(onBundled) {
|
|
92
|
+
const { nodejs } = this.props;
|
|
93
|
+
useFunctions().add(this.node.addr, {
|
|
94
|
+
...this.props,
|
|
95
|
+
nodejs: {
|
|
96
|
+
...nodejs,
|
|
97
|
+
banner: [
|
|
98
|
+
`process.env = { ...process.env, ..."{{ _SST_FUNCTION_ENVIRONMENT_ }}" };`,
|
|
99
|
+
nodejs?.banner || "",
|
|
100
|
+
].join("\n"),
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
useDeferredTasks().add(async () => {
|
|
104
|
+
// Build function
|
|
105
|
+
const bundle = await useRuntimeHandlers().build(this.node.addr, "deploy");
|
|
106
|
+
// create wrapper that calls the handler
|
|
107
|
+
if (bundle.type === "error")
|
|
108
|
+
throw new Error(`There was a problem bundling the SSR function for the "${this.scope.node.id}" Site.`);
|
|
109
|
+
const asset = new Asset(this.scope, `FunctionAsset`, {
|
|
110
|
+
path: bundle.out,
|
|
111
|
+
});
|
|
112
|
+
// Get handler filename
|
|
113
|
+
const isESM = (nodejs?.format || "esm") === "esm";
|
|
114
|
+
const parsed = path.parse(bundle.handler);
|
|
115
|
+
const handlerFilename = `${parsed.dir}/${parsed.name}${isESM ? ".mjs" : ".cjs"}`;
|
|
116
|
+
onBundled(asset, handlerFilename);
|
|
111
117
|
});
|
|
112
|
-
if (result.errors.length > 0) {
|
|
113
|
-
result.errors.forEach((error) => console.error(error));
|
|
114
|
-
throw new Error(`There was a problem bundling the SSR function for the "${this.scope.node.id}" Site.`);
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
bundle: outputPath,
|
|
118
|
-
handler: outputHandler,
|
|
119
|
-
handlerFilename: outputFilename + outputFileExt,
|
|
120
|
-
};
|
|
121
118
|
}
|
|
122
|
-
|
|
119
|
+
buildAssetFromBundle(bundle, handler) {
|
|
123
120
|
// We expose an environment variable token which is used by the code
|
|
124
121
|
// replacer to inject the environment variables assigned to the
|
|
125
122
|
// EdgeFunction construct.
|
|
@@ -132,14 +129,17 @@ export class EdgeFunction extends Construct {
|
|
|
132
129
|
// support runtime environment variables. A downside of this approach
|
|
133
130
|
// is that environment variables cannot be toggled after deployment,
|
|
134
131
|
// each change to one requires a redeployment.
|
|
135
|
-
const { bundle, handler } = this.props;
|
|
136
132
|
const { dir: inputPath, name: inputFilename, ext: inputHandlerFunction, } = path.parse(handler);
|
|
137
133
|
const inputFileExt = this.getHandlerExtension(path.join(bundle, inputPath, inputFilename));
|
|
138
134
|
const handlerFilename = handler.replace(inputHandlerFunction, inputFileExt);
|
|
139
135
|
const filePath = path.join(bundle, handlerFilename);
|
|
140
136
|
const fileData = fs.readFileSync(filePath, "utf8");
|
|
141
137
|
fs.writeFileSync(filePath, `process.env = { ...process.env, ..."{{ _SST_FUNCTION_ENVIRONMENT_ }}" };\n${fileData}`);
|
|
142
|
-
|
|
138
|
+
// Create asset
|
|
139
|
+
const asset = new Asset(this.scope, `FunctionAsset`, {
|
|
140
|
+
path: bundle,
|
|
141
|
+
});
|
|
142
|
+
return { handlerFilename, asset };
|
|
143
143
|
}
|
|
144
144
|
bind(constructs) {
|
|
145
145
|
const app = this.node.root;
|
|
@@ -168,13 +168,7 @@ export class EdgeFunction extends Construct {
|
|
|
168
168
|
}
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
const { bundle } = this.props;
|
|
173
|
-
return new Asset(this.scope, `FunctionAsset`, {
|
|
174
|
-
path: bundle,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
createCodeReplacer(asset, handlerFilename) {
|
|
171
|
+
createCodeReplacer(assetBucket, assetKey, handlerFilename) {
|
|
178
172
|
const { environment } = this.props;
|
|
179
173
|
const replacements = [
|
|
180
174
|
{
|
|
@@ -200,7 +194,7 @@ export class EdgeFunction extends Construct {
|
|
|
200
194
|
new PolicyStatement({
|
|
201
195
|
effect: Effect.ALLOW,
|
|
202
196
|
actions: ["s3:GetObject", "s3:PutObject"],
|
|
203
|
-
resources: [`arn:${stack.partition}:s3:::${
|
|
197
|
+
resources: [`arn:${stack.partition}:s3:::${assetBucket}/*`],
|
|
204
198
|
}),
|
|
205
199
|
],
|
|
206
200
|
});
|
|
@@ -209,13 +203,23 @@ export class EdgeFunction extends Construct {
|
|
|
209
203
|
serviceToken: stack.customResourceHandler.functionArn,
|
|
210
204
|
resourceType: "Custom::AssetReplacer",
|
|
211
205
|
properties: {
|
|
212
|
-
bucket:
|
|
213
|
-
key:
|
|
206
|
+
bucket: assetBucket,
|
|
207
|
+
key: assetKey,
|
|
214
208
|
replacements,
|
|
215
209
|
},
|
|
216
210
|
});
|
|
217
211
|
resource.node.addDependency(policy);
|
|
218
|
-
return resource;
|
|
212
|
+
return { assetReplacer: resource, assetReplacerPolicy: policy };
|
|
213
|
+
}
|
|
214
|
+
updateCodeReplacer(assetBucket, assetKey, handlerFilename) {
|
|
215
|
+
const stack = Stack.of(this);
|
|
216
|
+
const cfnReplacer = this.assetReplacer.node
|
|
217
|
+
.defaultChild;
|
|
218
|
+
cfnReplacer.addPropertyOverride("bucket", assetBucket);
|
|
219
|
+
cfnReplacer.addPropertyOverride("key", assetKey);
|
|
220
|
+
cfnReplacer.addPropertyOverride("replacements.0.files", handlerFilename);
|
|
221
|
+
const cfnPolicy = this.assetReplacerPolicy.node.defaultChild;
|
|
222
|
+
cfnPolicy.addPropertyOverride("PolicyDocument.Statement.0.Resource", `arn:${stack.partition}:s3:::${assetBucket}/*`);
|
|
219
223
|
}
|
|
220
224
|
createRole() {
|
|
221
225
|
const { permissions } = this.props;
|
|
@@ -268,7 +272,7 @@ export class EdgeFunction extends Construct {
|
|
|
268
272
|
});
|
|
269
273
|
return resource;
|
|
270
274
|
}
|
|
271
|
-
createFunctionInUsEast1(
|
|
275
|
+
createFunctionInUsEast1(assetBucket, assetKey, lambdaBucket) {
|
|
272
276
|
const { handler, runtime, timeout, memorySize } = this.props;
|
|
273
277
|
// Do not recreate if exist
|
|
274
278
|
const providerId = "EdgeLambdaProvider";
|
|
@@ -301,13 +305,13 @@ export class EdgeFunction extends Construct {
|
|
|
301
305
|
resourceType: "Custom::SSTEdgeLambda",
|
|
302
306
|
properties: {
|
|
303
307
|
FunctionNamePrefix: `${Stack.of(this).stackName}-${resId}`,
|
|
304
|
-
FunctionBucket:
|
|
308
|
+
FunctionBucket: lambdaBucket.getAttString("BucketName"),
|
|
305
309
|
FunctionParams: {
|
|
306
310
|
Description: `${this.node.id} handler`,
|
|
307
311
|
Handler: handler,
|
|
308
312
|
Code: {
|
|
309
|
-
S3Bucket:
|
|
310
|
-
S3Key:
|
|
313
|
+
S3Bucket: assetBucket,
|
|
314
|
+
S3Key: assetKey,
|
|
311
315
|
},
|
|
312
316
|
Runtime: runtime === "nodejs14.x"
|
|
313
317
|
? Runtime.NODEJS_14_X.name
|
|
@@ -326,6 +330,13 @@ export class EdgeFunction extends Construct {
|
|
|
326
330
|
});
|
|
327
331
|
return { fn, fnArn: fn.getAttString("FunctionArn") };
|
|
328
332
|
}
|
|
333
|
+
updateFunctionInUsEast1(assetBucket, assetKey) {
|
|
334
|
+
const cfnLambda = this.function.node.defaultChild;
|
|
335
|
+
cfnLambda.addPropertyOverride("FunctionParams.Code", {
|
|
336
|
+
S3Bucket: assetBucket,
|
|
337
|
+
S3Key: assetKey,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
329
340
|
createVersionInUsEast1(fn, fnArn) {
|
|
330
341
|
// Do not recreate if exist
|
|
331
342
|
const providerId = "EdgeLambdaVersionProvider";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Construct } from "constructs";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import { Function as CdkFunction } from "aws-cdk-lib/aws-lambda";
|
|
3
|
+
import { Distribution, CachePolicy } from "aws-cdk-lib/aws-cloudfront";
|
|
4
4
|
import { SsrSite, SsrSiteProps } from "./SsrSite.js";
|
|
5
5
|
import { Size } from "./util/size.js";
|
|
6
|
-
export interface NextjsSiteProps extends Omit<SsrSiteProps, "edge"> {
|
|
6
|
+
export interface NextjsSiteProps extends Omit<SsrSiteProps, "edge" | "nodejs"> {
|
|
7
7
|
imageOptimization?: {
|
|
8
8
|
/**
|
|
9
9
|
* The amount of memory in MB allocated for image optimization function.
|
|
@@ -41,10 +41,10 @@ export declare class NextjsSite extends SsrSite {
|
|
|
41
41
|
clientBuildOutputDir: string;
|
|
42
42
|
clientBuildVersionedSubDir: string;
|
|
43
43
|
};
|
|
44
|
-
protected createFunctionForRegional():
|
|
44
|
+
protected createFunctionForRegional(): CdkFunction;
|
|
45
45
|
private createImageOptimizationFunctionForRegional;
|
|
46
46
|
private createMiddlewareEdgeFunctionForRegional;
|
|
47
|
-
protected createCloudFrontDistributionForRegional():
|
|
48
|
-
protected createCloudFrontServerCachePolicy():
|
|
47
|
+
protected createCloudFrontDistributionForRegional(): Distribution;
|
|
48
|
+
protected createCloudFrontServerCachePolicy(): CachePolicy;
|
|
49
49
|
protected generateBuildId(): string;
|
|
50
50
|
}
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -2,10 +2,10 @@ import fs from "fs";
|
|
|
2
2
|
import url from "url";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { Fn, Duration as CdkDuration, RemovalPolicy } from "aws-cdk-lib";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
5
|
+
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
6
|
+
import { Function as CdkFunction, Code, Runtime, Architecture, FunctionUrlAuthType, } from "aws-cdk-lib/aws-lambda";
|
|
7
|
+
import { Distribution, ViewerProtocolPolicy, AllowedMethods, LambdaEdgeEventType, CachedMethods, CachePolicy, CacheQueryStringBehavior, CacheCookieBehavior, CacheHeaderBehavior, } from "aws-cdk-lib/aws-cloudfront";
|
|
8
|
+
import { S3Origin, HttpOrigin, OriginGroup, } from "aws-cdk-lib/aws-cloudfront-origins";
|
|
9
9
|
import { SsrFunction } from "./SsrFunction.js";
|
|
10
10
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
11
11
|
import { SsrSite } from "./SsrSite.js";
|
|
@@ -55,22 +55,22 @@ export class NextjsSite extends SsrSite {
|
|
|
55
55
|
}
|
|
56
56
|
createImageOptimizationFunctionForRegional() {
|
|
57
57
|
const { imageOptimization, path: sitePath } = this.props;
|
|
58
|
-
return new
|
|
58
|
+
return new CdkFunction(this, `ImageFunction`, {
|
|
59
59
|
description: "Image optimization handler for Next.js",
|
|
60
60
|
handler: "index.handler",
|
|
61
61
|
currentVersionOptions: {
|
|
62
62
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
63
63
|
},
|
|
64
|
-
logRetention:
|
|
65
|
-
code:
|
|
66
|
-
runtime:
|
|
64
|
+
logRetention: RetentionDays.THREE_DAYS,
|
|
65
|
+
code: Code.fromAsset(path.join(sitePath, ".open-next/image-optimization-function")),
|
|
66
|
+
runtime: Runtime.NODEJS_18_X,
|
|
67
67
|
memorySize: imageOptimization?.memorySize
|
|
68
68
|
? typeof imageOptimization.memorySize === "string"
|
|
69
69
|
? toCdkSize(imageOptimization.memorySize).toMebibytes()
|
|
70
70
|
: imageOptimization.memorySize
|
|
71
71
|
: 1536,
|
|
72
72
|
timeout: CdkDuration.seconds(25),
|
|
73
|
-
architecture:
|
|
73
|
+
architecture: Architecture.ARM_64,
|
|
74
74
|
environment: {
|
|
75
75
|
BUCKET_NAME: this.cdk.bucket.bucketName,
|
|
76
76
|
},
|
|
@@ -94,29 +94,31 @@ export class NextjsSite extends SsrSite {
|
|
|
94
94
|
memorySize: 128,
|
|
95
95
|
permissions,
|
|
96
96
|
environment,
|
|
97
|
-
|
|
97
|
+
nodejs: {
|
|
98
|
+
format: "esm",
|
|
99
|
+
},
|
|
98
100
|
});
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
createCloudFrontDistributionForRegional() {
|
|
102
104
|
const { cdk } = this.props;
|
|
103
105
|
const cfDistributionProps = cdk?.distribution || {};
|
|
104
|
-
const s3Origin = new
|
|
106
|
+
const s3Origin = new S3Origin(this.cdk.bucket);
|
|
105
107
|
// Create server behavior
|
|
106
108
|
const middlewareFn = this.createMiddlewareEdgeFunctionForRegional();
|
|
107
109
|
const serverFnUrl = this.serverLambdaForRegional.addFunctionUrl({
|
|
108
|
-
authType:
|
|
110
|
+
authType: FunctionUrlAuthType.NONE,
|
|
109
111
|
});
|
|
110
112
|
const serverBehavior = {
|
|
111
|
-
viewerProtocolPolicy:
|
|
112
|
-
origin: new
|
|
113
|
-
allowedMethods:
|
|
114
|
-
cachedMethods:
|
|
113
|
+
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
114
|
+
origin: new HttpOrigin(Fn.parseDomainName(serverFnUrl.url)),
|
|
115
|
+
allowedMethods: AllowedMethods.ALLOW_ALL,
|
|
116
|
+
cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS,
|
|
115
117
|
compress: true,
|
|
116
118
|
cachePolicy: cdk?.serverCachePolicy ?? this.createCloudFrontServerCachePolicy(),
|
|
117
119
|
edgeLambdas: middlewareFn && [
|
|
118
120
|
{
|
|
119
|
-
eventType:
|
|
121
|
+
eventType: LambdaEdgeEventType.VIEWER_REQUEST,
|
|
120
122
|
functionVersion: middlewareFn.currentVersion,
|
|
121
123
|
},
|
|
122
124
|
],
|
|
@@ -124,37 +126,37 @@ export class NextjsSite extends SsrSite {
|
|
|
124
126
|
// Create image optimization behavior
|
|
125
127
|
const imageFn = this.createImageOptimizationFunctionForRegional();
|
|
126
128
|
const imageFnUrl = imageFn.addFunctionUrl({
|
|
127
|
-
authType:
|
|
129
|
+
authType: FunctionUrlAuthType.NONE,
|
|
128
130
|
});
|
|
129
131
|
const imageBehavior = {
|
|
130
|
-
viewerProtocolPolicy:
|
|
131
|
-
origin: new
|
|
132
|
-
allowedMethods:
|
|
133
|
-
cachedMethods:
|
|
132
|
+
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
133
|
+
origin: new HttpOrigin(Fn.parseDomainName(imageFnUrl.url)),
|
|
134
|
+
allowedMethods: AllowedMethods.ALLOW_ALL,
|
|
135
|
+
cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS,
|
|
134
136
|
compress: true,
|
|
135
137
|
cachePolicy: serverBehavior.cachePolicy,
|
|
136
138
|
};
|
|
137
139
|
// Create statics behavior
|
|
138
140
|
const staticFileBehaviour = {
|
|
139
141
|
origin: s3Origin,
|
|
140
|
-
viewerProtocolPolicy:
|
|
141
|
-
allowedMethods:
|
|
142
|
-
cachedMethods:
|
|
142
|
+
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
143
|
+
allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
|
|
144
|
+
cachedMethods: CachedMethods.CACHE_GET_HEAD_OPTIONS,
|
|
143
145
|
compress: true,
|
|
144
|
-
cachePolicy:
|
|
146
|
+
cachePolicy: CachePolicy.CACHING_OPTIMIZED,
|
|
145
147
|
};
|
|
146
148
|
// Create default behavior
|
|
147
149
|
// default handler for requests that don't match any other path:
|
|
148
150
|
// - try lambda handler first first
|
|
149
151
|
// - if failed, fall back to S3
|
|
150
|
-
const fallbackOriginGroup = new
|
|
152
|
+
const fallbackOriginGroup = new OriginGroup({
|
|
151
153
|
primaryOrigin: serverBehavior.origin,
|
|
152
154
|
fallbackOrigin: s3Origin,
|
|
153
155
|
fallbackStatusCodes: [404],
|
|
154
156
|
});
|
|
155
157
|
const defaultBehavior = {
|
|
156
158
|
origin: fallbackOriginGroup,
|
|
157
|
-
viewerProtocolPolicy:
|
|
159
|
+
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
158
160
|
compress: true,
|
|
159
161
|
cachePolicy: serverBehavior.cachePolicy,
|
|
160
162
|
edgeLambdas: serverBehavior.edgeLambdas,
|
|
@@ -208,7 +210,7 @@ export class NextjsSite extends SsrSite {
|
|
|
208
210
|
* - Cache-Control: public, max-age=0, must-revalidate
|
|
209
211
|
* - x-vercel-cache: MISS
|
|
210
212
|
*/
|
|
211
|
-
return new
|
|
213
|
+
return new Distribution(this, "Distribution", {
|
|
212
214
|
// these values can be overwritten by cfDistributionProps
|
|
213
215
|
defaultRootObject: "",
|
|
214
216
|
// Override props.
|
|
@@ -227,16 +229,16 @@ export class NextjsSite extends SsrSite {
|
|
|
227
229
|
});
|
|
228
230
|
}
|
|
229
231
|
createCloudFrontServerCachePolicy() {
|
|
230
|
-
return new
|
|
231
|
-
queryStringBehavior:
|
|
232
|
-
headerBehavior:
|
|
232
|
+
return new CachePolicy(this, "ServerCache", {
|
|
233
|
+
queryStringBehavior: CacheQueryStringBehavior.all(),
|
|
234
|
+
headerBehavior: CacheHeaderBehavior.allowList(
|
|
233
235
|
// required by image optimization request
|
|
234
236
|
"accept",
|
|
235
237
|
// required by server request
|
|
236
238
|
"x-op-middleware-request-headers", "x-op-middleware-response-headers", "x-nextjs-data", "x-middleware-prefetch",
|
|
237
239
|
// required by server request (in-place routing)
|
|
238
240
|
"rsc", "next-router-prefetch", "next-router-state-tree"),
|
|
239
|
-
cookieBehavior:
|
|
241
|
+
cookieBehavior: CacheCookieBehavior.all(),
|
|
240
242
|
defaultTtl: CdkDuration.days(0),
|
|
241
243
|
maxTtl: CdkDuration.days(365),
|
|
242
244
|
minTtl: CdkDuration.days(0),
|
package/constructs/RemixSite.js
CHANGED
|
@@ -89,7 +89,7 @@ export class RemixSite extends SsrSite {
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
createFunctionForRegional() {
|
|
92
|
-
const { runtime, timeout, memorySize, permissions, environment, bind, cdk, } = this.props;
|
|
92
|
+
const { runtime, timeout, memorySize, permissions, environment, bind, nodejs, cdk, } = this.props;
|
|
93
93
|
const { handler, esbuild } = this.createServerLambdaBundle("regional-server.js");
|
|
94
94
|
const fn = new Function(this, `ServerFunction`, {
|
|
95
95
|
description: "Server handler",
|
|
@@ -100,8 +100,12 @@ export class RemixSite extends SsrSite {
|
|
|
100
100
|
timeout,
|
|
101
101
|
nodejs: {
|
|
102
102
|
format: "cjs",
|
|
103
|
-
|
|
104
|
-
esbuild
|
|
103
|
+
...nodejs,
|
|
104
|
+
esbuild: {
|
|
105
|
+
...esbuild,
|
|
106
|
+
...nodejs?.esbuild,
|
|
107
|
+
inject: [...(nodejs?.esbuild?.inject || []), ...esbuild.inject],
|
|
108
|
+
},
|
|
105
109
|
},
|
|
106
110
|
bind,
|
|
107
111
|
environment,
|
|
@@ -113,7 +117,7 @@ export class RemixSite extends SsrSite {
|
|
|
113
117
|
return fn;
|
|
114
118
|
}
|
|
115
119
|
createFunctionForEdge() {
|
|
116
|
-
const { runtime, timeout, memorySize, bind, permissions, environment } = this.props;
|
|
120
|
+
const { runtime, timeout, memorySize, bind, permissions, environment, nodejs, } = this.props;
|
|
117
121
|
const { handler, esbuild } = this.createServerLambdaBundle("edge-server.js");
|
|
118
122
|
return new EdgeFunction(this, `Server`, {
|
|
119
123
|
scopeOverride: this,
|
|
@@ -124,8 +128,15 @@ export class RemixSite extends SsrSite {
|
|
|
124
128
|
bind,
|
|
125
129
|
environment,
|
|
126
130
|
permissions,
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
nodejs: {
|
|
132
|
+
format: "cjs",
|
|
133
|
+
...nodejs,
|
|
134
|
+
esbuild: {
|
|
135
|
+
...esbuild,
|
|
136
|
+
...nodejs?.esbuild,
|
|
137
|
+
inject: [...(nodejs?.esbuild?.inject || []), ...esbuild.inject],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
129
140
|
});
|
|
130
141
|
}
|
|
131
142
|
}
|
|
@@ -23,7 +23,7 @@ export class SolidStartSite extends SsrSite {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
createFunctionForRegional() {
|
|
26
|
-
const { runtime, timeout, memorySize, bind, permissions, environment, cdk, } = this.props;
|
|
26
|
+
const { runtime, timeout, memorySize, bind, nodejs, permissions, environment, cdk, } = this.props;
|
|
27
27
|
// Create function
|
|
28
28
|
const fn = new Function(this, `ServerFunction`, {
|
|
29
29
|
description: "Server handler",
|
|
@@ -34,6 +34,7 @@ export class SolidStartSite extends SsrSite {
|
|
|
34
34
|
timeout,
|
|
35
35
|
nodejs: {
|
|
36
36
|
format: "esm",
|
|
37
|
+
...nodejs,
|
|
37
38
|
},
|
|
38
39
|
bind,
|
|
39
40
|
environment,
|
|
@@ -45,7 +46,7 @@ export class SolidStartSite extends SsrSite {
|
|
|
45
46
|
return fn;
|
|
46
47
|
}
|
|
47
48
|
createFunctionForEdge() {
|
|
48
|
-
const { runtime, timeout, memorySize, bind, permissions, environment } = this.props;
|
|
49
|
+
const { runtime, timeout, memorySize, bind, permissions, environment, nodejs, } = this.props;
|
|
49
50
|
return new EdgeFunction(this, `Server`, {
|
|
50
51
|
scopeOverride: this,
|
|
51
52
|
handler: path.join(this.props.path, "dist", "server", "index.handler"),
|
|
@@ -55,7 +56,10 @@ export class SolidStartSite extends SsrSite {
|
|
|
55
56
|
bind,
|
|
56
57
|
permissions,
|
|
57
58
|
environment,
|
|
58
|
-
|
|
59
|
+
nodejs: {
|
|
60
|
+
format: "esm",
|
|
61
|
+
...nodejs,
|
|
62
|
+
},
|
|
59
63
|
});
|
|
60
64
|
}
|
|
61
65
|
}
|
package/constructs/SsrSite.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Distribution, ICachePolicy, BehaviorOptions, CachePolicy } from "aws-cd
|
|
|
6
6
|
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
|
|
7
7
|
import { S3Origin } from "aws-cdk-lib/aws-cloudfront-origins";
|
|
8
8
|
import { SSTConstruct } from "./Construct.js";
|
|
9
|
+
import { NodeJSProps } from "./Function.js";
|
|
9
10
|
import { EdgeFunction } from "./EdgeFunction.js";
|
|
10
11
|
import { BaseSiteDomainProps, BaseSiteReplaceProps, BaseSiteCdkDistributionProps } from "./BaseSite.js";
|
|
11
12
|
import { Size } from "./util/size.js";
|
|
@@ -17,6 +18,8 @@ export type SsrBuildConfig = {
|
|
|
17
18
|
clientBuildOutputDir: string;
|
|
18
19
|
clientBuildVersionedSubDir: string;
|
|
19
20
|
};
|
|
21
|
+
export interface SsrSiteNodeJSProps extends NodeJSProps {
|
|
22
|
+
}
|
|
20
23
|
export interface SsrDomainProps extends BaseSiteDomainProps {
|
|
21
24
|
}
|
|
22
25
|
export interface SsrSiteReplaceProps extends BaseSiteReplaceProps {
|
|
@@ -103,6 +106,10 @@ export interface SsrSiteProps {
|
|
|
103
106
|
* ```
|
|
104
107
|
*/
|
|
105
108
|
runtime?: "nodejs14.x" | "nodejs16.x" | "nodejs18.x";
|
|
109
|
+
/**
|
|
110
|
+
* Used to configure nodejs function properties
|
|
111
|
+
*/
|
|
112
|
+
nodejs?: SsrSiteNodeJSProps;
|
|
106
113
|
/**
|
|
107
114
|
* Attaches the given list of permissions to the SSR function. Configuring this property is equivalent to calling `attachPermissions()` after the site is created.
|
|
108
115
|
* @example
|
package/package.json
CHANGED
package/runtime/handlers/node.js
CHANGED
|
@@ -99,11 +99,16 @@ export const useNodeHandler = Context.memo(async () => {
|
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
101
|
const { external, ...override } = nodejs.esbuild || {};
|
|
102
|
+
const forceExternal = [
|
|
103
|
+
"sharp",
|
|
104
|
+
"pg-native",
|
|
105
|
+
...(isESM || input.props.runtime === "nodejs18.x" ? [] : ["aws-sdk"]),
|
|
106
|
+
];
|
|
102
107
|
const options = {
|
|
103
108
|
entryPoints: [file],
|
|
104
109
|
platform: "node",
|
|
105
110
|
external: [
|
|
106
|
-
...
|
|
111
|
+
...forceExternal,
|
|
107
112
|
...(nodejs.install || []),
|
|
108
113
|
...(external || []),
|
|
109
114
|
],
|
|
@@ -144,39 +149,50 @@ export const useNodeHandler = Context.memo(async () => {
|
|
|
144
149
|
try {
|
|
145
150
|
const result = await esbuild.build(options);
|
|
146
151
|
// Install node_modules
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
const installPackages = [
|
|
153
|
+
...(nodejs.install || []),
|
|
154
|
+
...forceExternal
|
|
155
|
+
.filter((pkg) => pkg !== "aws-sdk")
|
|
156
|
+
.filter((pkg) => !external?.includes(pkg))
|
|
157
|
+
.filter((pkg) => Object.values(result.metafile?.inputs || {}).some(({ imports }) => imports.some(({ path }) => path === pkg))),
|
|
158
|
+
];
|
|
159
|
+
async function find(dir, target) {
|
|
160
|
+
if (dir === "/")
|
|
161
|
+
throw new VisibleError("Could not find a package.json file");
|
|
162
|
+
if (await fs
|
|
163
|
+
.access(path.join(dir, target))
|
|
164
|
+
.then(() => true)
|
|
165
|
+
.catch(() => false))
|
|
166
|
+
return dir;
|
|
167
|
+
return find(path.join(dir, ".."), target);
|
|
168
|
+
}
|
|
169
|
+
if (input.mode === "deploy" && installPackages) {
|
|
170
|
+
const src = await find(parsed.dir, "package.json");
|
|
171
|
+
const json = JSON.parse(await fs
|
|
172
|
+
.readFile(path.join(src, "package.json"))
|
|
173
|
+
.then((x) => x.toString()));
|
|
174
|
+
fs.writeFile(path.join(input.out, "package.json"), JSON.stringify({
|
|
175
|
+
dependencies: Object.fromEntries(installPackages.map((x) => [x, json.dependencies?.[x] || "*"])),
|
|
176
|
+
}));
|
|
177
|
+
const cmd = ["npm install"];
|
|
178
|
+
if (installPackages.includes("sharp")) {
|
|
179
|
+
cmd.push("--platform=linux", input.props.architecture === "arm_64"
|
|
180
|
+
? "--arch=arm64"
|
|
181
|
+
: "--arch=x64");
|
|
157
182
|
}
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
.readFile(path.join(src, "package.json"))
|
|
162
|
-
.then((x) => x.toString()));
|
|
163
|
-
fs.writeFile(path.join(input.out, "package.json"), JSON.stringify({
|
|
164
|
-
dependencies: Object.fromEntries(nodejs.install?.map((x) => [x, json.dependencies?.[x] || "*"])),
|
|
165
|
-
}));
|
|
166
|
-
await new Promise((resolve) => {
|
|
167
|
-
const process = exec("npm install", {
|
|
168
|
-
cwd: input.out,
|
|
169
|
-
});
|
|
170
|
-
process.on("exit", () => resolve());
|
|
183
|
+
await new Promise((resolve) => {
|
|
184
|
+
const process = exec(cmd.join(" "), {
|
|
185
|
+
cwd: input.out,
|
|
171
186
|
});
|
|
187
|
+
process.on("exit", () => resolve());
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
if (input.mode === "start") {
|
|
191
|
+
const dir = path.join(await find(parsed.dir, "package.json"), "node_modules");
|
|
192
|
+
try {
|
|
193
|
+
await fs.symlink(path.resolve(dir), path.resolve(path.join(input.out, "node_modules")), "dir");
|
|
172
194
|
}
|
|
173
|
-
|
|
174
|
-
const dir = path.join(await find(parsed.dir, "package.json"), "node_modules");
|
|
175
|
-
try {
|
|
176
|
-
await fs.symlink(path.resolve(dir), path.resolve(path.join(input.out, "node_modules")), "dir");
|
|
177
|
-
}
|
|
178
|
-
catch { }
|
|
179
|
-
}
|
|
195
|
+
catch { }
|
|
180
196
|
}
|
|
181
197
|
cache[input.functionID] = result;
|
|
182
198
|
return {
|
package/sst.mjs
CHANGED
|
@@ -4974,11 +4974,16 @@ var init_node = __esm({
|
|
|
4974
4974
|
};
|
|
4975
4975
|
}
|
|
4976
4976
|
const { external, ...override } = nodejs.esbuild || {};
|
|
4977
|
+
const forceExternal = [
|
|
4978
|
+
"sharp",
|
|
4979
|
+
"pg-native",
|
|
4980
|
+
...isESM || input.props.runtime === "nodejs18.x" ? [] : ["aws-sdk"]
|
|
4981
|
+
];
|
|
4977
4982
|
const options = {
|
|
4978
4983
|
entryPoints: [file],
|
|
4979
4984
|
platform: "node",
|
|
4980
4985
|
external: [
|
|
4981
|
-
...
|
|
4986
|
+
...forceExternal,
|
|
4982
4987
|
...nodejs.install || [],
|
|
4983
4988
|
...external || []
|
|
4984
4989
|
],
|
|
@@ -5014,47 +5019,60 @@ var init_node = __esm({
|
|
|
5014
5019
|
};
|
|
5015
5020
|
try {
|
|
5016
5021
|
const result = await esbuild2.build(options);
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5022
|
+
const installPackages = [
|
|
5023
|
+
...nodejs.install || [],
|
|
5024
|
+
...forceExternal.filter((pkg) => pkg !== "aws-sdk").filter((pkg) => !external?.includes(pkg)).filter(
|
|
5025
|
+
(pkg) => Object.values(result.metafile?.inputs || {}).some(
|
|
5026
|
+
({ imports }) => imports.some(({ path: path20 }) => path20 === pkg)
|
|
5027
|
+
)
|
|
5028
|
+
)
|
|
5029
|
+
];
|
|
5030
|
+
async function find2(dir, target2) {
|
|
5031
|
+
if (dir === "/")
|
|
5032
|
+
throw new VisibleError("Could not find a package.json file");
|
|
5033
|
+
if (await fs10.access(path10.join(dir, target2)).then(() => true).catch(() => false))
|
|
5034
|
+
return dir;
|
|
5035
|
+
return find2(path10.join(dir, ".."), target2);
|
|
5036
|
+
}
|
|
5037
|
+
if (input.mode === "deploy" && installPackages) {
|
|
5038
|
+
const src = await find2(parsed.dir, "package.json");
|
|
5039
|
+
const json = JSON.parse(
|
|
5040
|
+
await fs10.readFile(path10.join(src, "package.json")).then((x) => x.toString())
|
|
5041
|
+
);
|
|
5042
|
+
fs10.writeFile(
|
|
5043
|
+
path10.join(input.out, "package.json"),
|
|
5044
|
+
JSON.stringify({
|
|
5045
|
+
dependencies: Object.fromEntries(
|
|
5046
|
+
installPackages.map((x) => [x, json.dependencies?.[x] || "*"])
|
|
5047
|
+
)
|
|
5048
|
+
})
|
|
5049
|
+
);
|
|
5050
|
+
const cmd = ["npm install"];
|
|
5051
|
+
if (installPackages.includes("sharp")) {
|
|
5052
|
+
cmd.push(
|
|
5053
|
+
"--platform=linux",
|
|
5054
|
+
input.props.architecture === "arm_64" ? "--arch=arm64" : "--arch=x64"
|
|
5037
5055
|
);
|
|
5038
|
-
await new Promise((resolve) => {
|
|
5039
|
-
const process2 = exec2("npm install", {
|
|
5040
|
-
cwd: input.out
|
|
5041
|
-
});
|
|
5042
|
-
process2.on("exit", () => resolve());
|
|
5043
|
-
});
|
|
5044
5056
|
}
|
|
5045
|
-
|
|
5046
|
-
const
|
|
5047
|
-
|
|
5048
|
-
|
|
5057
|
+
await new Promise((resolve) => {
|
|
5058
|
+
const process2 = exec2(cmd.join(" "), {
|
|
5059
|
+
cwd: input.out
|
|
5060
|
+
});
|
|
5061
|
+
process2.on("exit", () => resolve());
|
|
5062
|
+
});
|
|
5063
|
+
}
|
|
5064
|
+
if (input.mode === "start") {
|
|
5065
|
+
const dir = path10.join(
|
|
5066
|
+
await find2(parsed.dir, "package.json"),
|
|
5067
|
+
"node_modules"
|
|
5068
|
+
);
|
|
5069
|
+
try {
|
|
5070
|
+
await fs10.symlink(
|
|
5071
|
+
path10.resolve(dir),
|
|
5072
|
+
path10.resolve(path10.join(input.out, "node_modules")),
|
|
5073
|
+
"dir"
|
|
5049
5074
|
);
|
|
5050
|
-
|
|
5051
|
-
await fs10.symlink(
|
|
5052
|
-
path10.resolve(dir),
|
|
5053
|
-
path10.resolve(path10.join(input.out, "node_modules")),
|
|
5054
|
-
"dir"
|
|
5055
|
-
);
|
|
5056
|
-
} catch {
|
|
5057
|
-
}
|
|
5075
|
+
} catch {
|
|
5058
5076
|
}
|
|
5059
5077
|
}
|
|
5060
5078
|
cache[input.functionID] = result;
|
|
@@ -9,9 +9,9 @@ installGlobals();
|
|
|
9
9
|
import {
|
|
10
10
|
Headers as NodeHeaders,
|
|
11
11
|
Request as NodeRequest,
|
|
12
|
+
createRequestHandler as createNodeRequestHandler,
|
|
12
13
|
readableStreamToString,
|
|
13
14
|
} from "@remix-run/node";
|
|
14
|
-
import { createRequestHandler as createRemixRequestHandler } from "@remix-run/server-runtime";
|
|
15
15
|
import { URL } from "url";
|
|
16
16
|
|
|
17
17
|
// Import the server build that was produced by `remix build`;
|
|
@@ -146,7 +146,7 @@ async function convertNodeResponseToCf(nodeResponse) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
function createCfHandler(build) {
|
|
149
|
-
const requestHandler =
|
|
149
|
+
const requestHandler = createNodeRequestHandler(build, process.env.NODE_ENV);
|
|
150
150
|
|
|
151
151
|
return async (event) => {
|
|
152
152
|
const request = convertCfRequestToNode(event);
|