sst 2.38.2 → 2.38.4

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.
@@ -2,6 +2,7 @@ import { readFileSync, existsSync, readdirSync, statSync } from "fs";
2
2
  import { join } from "path";
3
3
  import { SsrSite, } from "./SsrSite.js";
4
4
  import { AllowedMethods } from "aws-cdk-lib/aws-cloudfront";
5
+ import { getStringifiedRouteTree } from "./util/astroRouteCompressor.js";
5
6
  const BUILD_META_FILE_NAME = "sst.buildMeta.json";
6
7
  /**
7
8
  * The `AstroSite` construct is a higher level CDK construct that makes it easy to create a Astro app.
@@ -28,40 +29,30 @@ export class AstroSite extends SsrSite {
28
29
  return JSON.parse(readFileSync(filePath, "utf-8"));
29
30
  }
30
31
  static getCFRoutingFunction({ routes, pageResolution, }) {
31
- const serializedRoutes = routes.map((route) => ({
32
- rt: route.route,
33
- pt: new RegExp(route.pattern),
34
- t: route.type[1],
35
- pr: route.prerender === true ? true : undefined,
36
- rp: route.redirectPath,
37
- rs: route.redirectStatus,
38
- }));
39
- function objectToString(obj) {
40
- return `{ ${Object.entries(obj)
41
- .filter(([_, value]) => value !== undefined)
42
- .map(([key, value]) => `${key}: ${typeof value === "string" ? `'${value}'` : value}`)
43
- .join(", ")} }`;
44
- }
45
32
  return `
46
- var routes = [${serializedRoutes.map(objectToString).join(", ")}]
47
- var match = routes.find((route) => route.pt.test(request.uri));
48
- if (match) {
49
- if (match.t === "r") {
50
- var redirectPath = match.rp;
51
- (match.pt.exec(request.uri) || []).forEach((match, index) => {
52
- redirectPath = redirectPath.replace(\`\\\${\${index}}\`, match)
33
+ var routeData = ${getStringifiedRouteTree(routes)};
34
+ var findMatch = (path, routeData) => {
35
+ var match = routeData.find((route) => route[0].test(path));
36
+ return match && Array.isArray(match[1]) ? findMatch(path, match[1]) : match;
37
+ };
38
+
39
+ var matchedRoute = findMatch(request.uri, routeData);
40
+ if (matchedRoute) {
41
+ if (!matchedRoute[1]) {
42
+ ${pageResolution === "file"
43
+ ? `request.uri = request.uri === "/" ? "/index.html" : request.uri.replace(/\\/?$/, ".html");`
44
+ : `request.uri = request.uri.replace(/\\/?$/, "/index.html");`}
45
+ } else if (matchedRoute[1] === 2) {
46
+ var redirectPath = matchedRoute[2];
47
+ matchedRoute[0].exec(request.uri).forEach((match, index) => {
48
+ redirectPath = redirectPath.replace(\`\\\${\${index}}\`, match);
53
49
  });
54
50
  return {
55
- statusCode: match.rs || 308,
51
+ statusCode: matchedRoute[3] || 308,
56
52
  headers: { location: { value: redirectPath } },
57
53
  };
58
- } else if (match.t === "p" && match.pr) {
59
- ${pageResolution === "file"
60
- ? `request.uri = request.uri === "/" ? "/index.html" : request.uri.replace(/\\/?$/, ".html");`
61
- : `request.uri = request.uri.replace(/\\/?$/, "/index.html");`}
62
54
  }
63
- }
64
- `;
55
+ }`;
65
56
  }
66
57
  plan() {
67
58
  const { path: sitePath } = this.props;
@@ -83,7 +74,7 @@ export class AstroSite extends SsrSite {
83
74
  ],
84
75
  },
85
76
  serverCfFunctionHostOnly: {
86
- constructId: "CloudFrontFunction",
77
+ constructId: "CloudFrontFunctionHostOnly",
87
78
  injections: [this.useCloudFrontFunctionHostHeaderInjection()],
88
79
  },
89
80
  },
@@ -30,6 +30,7 @@ import { getParameterPath, } from "./util/functionBinding.js";
30
30
  import { useProject } from "../project.js";
31
31
  import { VisibleError } from "../error.js";
32
32
  import { RetentionDays } from "aws-cdk-lib/aws-logs";
33
+ import { transformSync } from "esbuild";
33
34
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
34
35
  /**
35
36
  * The `SsrSite` construct is a higher level CDK construct that makes it easy to create modern web apps with Server Side Rendering capabilities.
@@ -371,13 +372,18 @@ export class SsrSite extends Construct {
371
372
  function createCloudFrontFunctions() {
372
373
  const functions = {};
373
374
  Object.entries(plan.cloudFrontFunctions ?? {}).forEach(([name, { constructId, injections }]) => {
374
- functions[name] = new CfFunction(self, constructId, {
375
- code: CfFunctionCode.fromInline(`
375
+ const rawCode = `
376
376
  function handler(event) {
377
377
  var request = event.request;
378
378
  ${injections.join("\n")}
379
379
  return request;
380
- }`),
380
+ }`;
381
+ const minifiedCode = transformSync(rawCode, {
382
+ minify: true,
383
+ target: "es5",
384
+ });
385
+ functions[name] = new CfFunction(self, constructId, {
386
+ code: CfFunctionCode.fromInline(minifiedCode.code),
381
387
  });
382
388
  });
383
389
  return functions;
@@ -0,0 +1,10 @@
1
+ import type { BuildMetaConfig } from "astro-sst/build-meta";
2
+ type TreeNode = {
3
+ branches: Record<string, TreeNode>;
4
+ nodes: BuildMetaConfig["routes"][number][];
5
+ };
6
+ type FlattenedRoute = [string] | [string, 1] | [string, 2, string | undefined, number | undefined];
7
+ type FlattenedRouteTree = Array<FlattenedRoute | [string, FlattenedRouteTree]>;
8
+ export declare function flattenRouteTree(tree: TreeNode, parentKey?: string): FlattenedRouteTree;
9
+ export declare function getStringifiedRouteTree(routes: BuildMetaConfig["routes"]): string;
10
+ export {};
@@ -0,0 +1,75 @@
1
+ function buildRouteTree(routes, level = 0) {
2
+ const routeTree = routes.reduce((tree, route) => {
3
+ const routePatternWithoutCaptureGroups = route.pattern
4
+ .replace(/\((?:\?:)?(.*?[^\\])\)/g, (_, content) => content.trim())
5
+ .replace(/\/\^/g, "")
6
+ .replace(/\$\//g, "");
7
+ const routeParts = routePatternWithoutCaptureGroups
8
+ .split(/(?=\\\/)/g)
9
+ .filter((part) => part !== "/^" && part !== "/$/");
10
+ tree.branches[routeParts[level]] = tree.branches[routeParts[level]] || {
11
+ branches: {},
12
+ nodes: [],
13
+ };
14
+ tree.branches[routeParts[level]].nodes.push(route);
15
+ return tree;
16
+ }, { branches: {}, nodes: [] });
17
+ for (const [key, branch] of Object.entries(routeTree.branches)) {
18
+ if (!branch.nodes.some((node) => node.prerender || node.type === "redirect")) {
19
+ delete routeTree.branches[key];
20
+ }
21
+ else if (branch.nodes.length > 1) {
22
+ routeTree.branches[key] = buildRouteTree(branch.nodes, level + 1);
23
+ branch.nodes = [];
24
+ }
25
+ }
26
+ return routeTree;
27
+ }
28
+ export function flattenRouteTree(tree, parentKey = "") {
29
+ const flatTree = [];
30
+ for (const [key, branch] of Object.entries(tree.branches)) {
31
+ if (branch.nodes.length === 1) {
32
+ const node = branch.nodes[0];
33
+ if (node.type === "page") {
34
+ flatTree.push([node.pattern]);
35
+ }
36
+ if (node.type === "endpoint") {
37
+ flatTree.push([node.pattern, 1]);
38
+ }
39
+ else if (node.type === "redirect") {
40
+ flatTree.push([
41
+ node.pattern,
42
+ 2,
43
+ node.redirectPath,
44
+ node.redirectStatus,
45
+ ]);
46
+ }
47
+ }
48
+ else {
49
+ const flatKey = parentKey + key;
50
+ flatTree.push([flatKey, flattenRouteTree(branch, flatKey)]);
51
+ }
52
+ }
53
+ return flatTree;
54
+ }
55
+ function stringifyFlattenedRouteTree(tree) {
56
+ return `[${tree
57
+ .map((tuple) => {
58
+ if (Array.isArray(tuple[1])) {
59
+ return `[/^${tuple[0]}/,${stringifyFlattenedRouteTree(tuple[1])}]`;
60
+ }
61
+ if (typeof tuple[1] === "undefined") {
62
+ return `[${tuple[0]}]`;
63
+ }
64
+ else if (tuple[1] === 1) {
65
+ return `[${tuple[0]},1]`;
66
+ }
67
+ return `[${tuple[0]},2,"${tuple[2]}"${tuple[3] ? `,${tuple[3]}` : ""}]`;
68
+ })
69
+ .join(",")}]`;
70
+ }
71
+ export function getStringifiedRouteTree(routes) {
72
+ const tree = buildRouteTree(routes);
73
+ const flatTree = flattenRouteTree(tree);
74
+ return stringifyFlattenedRouteTree(flatTree);
75
+ }
package/iot.js CHANGED
@@ -114,7 +114,7 @@ export const useIOT = lazy(async () => {
114
114
  Logger.debug("IoT closed");
115
115
  });
116
116
  device.on("reconnect", () => {
117
- Logger.debug("IoT reconnected");
117
+ Logger.debug("IoT reconnecting...");
118
118
  });
119
119
  device.on("message", (_topic, buffer) => {
120
120
  const fragment = JSON.parse(buffer.toString());
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.38.2",
4
+ "version": "2.38.4",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },
@@ -120,7 +120,7 @@
120
120
  "@types/ws": "^8.5.3",
121
121
  "@types/yargs": "^17.0.13",
122
122
  "archiver": "^5.3.1",
123
- "astro-sst": "2.38.2",
123
+ "astro-sst": "2.38.4",
124
124
  "async": "^3.2.4",
125
125
  "tsx": "^3.12.1",
126
126
  "typescript": "^5.2.2",
@@ -206,9 +206,25 @@ export const useNodeHandler = () => {
206
206
  }));
207
207
  const cmd = ["npm install"];
208
208
  if (installPackages.includes("sharp")) {
209
- cmd.push("--platform=linux", input.props.architecture === "arm_64"
209
+ /**
210
+ * TODO: This is a workaround for issues that sharp v0.33.0 has
211
+ * with cross platform builds. This can be removed once sharp
212
+ * releases a new version with the fix.
213
+ */
214
+ cmd.push("--platform=linux", "--omit=dev", "--no-optional", input.props.architecture === "arm_64"
210
215
  ? "--arch=arm64"
211
- : "--arch=x64");
216
+ : "--arch=x64", "--force sharp@0.32.6");
217
+ /**
218
+ * Once the above issue is resolved, the code below can be used.
219
+ */
220
+ // cmd.push(
221
+ // "--platform=linux",
222
+ // "--omit=dev",
223
+ // "--no-optional",
224
+ // ...input.props.architecture === "arm_64"
225
+ // ? ["--arch=arm64", "--force @img/sharp-linux-arm64"]
226
+ // : ["--arch=x64", "--force @img/sharp-linux-x64"],
227
+ // );
212
228
  }
213
229
  await new Promise((resolve, reject) => {
214
230
  exec(cmd.join(" "), { cwd: input.out }, (error) => {