sst 2.0.35 → 2.0.37

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.
Files changed (60) hide show
  1. package/bootstrap.js +1 -1
  2. package/constructs/Api.d.ts +2 -10
  3. package/constructs/Api.js +2 -2
  4. package/constructs/ApiGatewayV1Api.d.ts +2 -10
  5. package/constructs/ApiGatewayV1Api.js +2 -2
  6. package/constructs/App.d.ts +0 -2
  7. package/constructs/App.js +3 -7
  8. package/constructs/AppSyncApi.d.ts +2 -10
  9. package/constructs/AppSyncApi.js +2 -2
  10. package/constructs/Auth.js +10 -7
  11. package/constructs/Bucket.d.ts +2 -12
  12. package/constructs/Bucket.js +2 -2
  13. package/constructs/EventBus.d.ts +2 -12
  14. package/constructs/EventBus.js +2 -2
  15. package/constructs/Function.d.ts +3 -12
  16. package/constructs/Function.js +10 -6
  17. package/constructs/Job.d.ts +3 -13
  18. package/constructs/Job.js +9 -7
  19. package/constructs/KinesisStream.d.ts +2 -12
  20. package/constructs/KinesisStream.js +2 -2
  21. package/constructs/NextjsSite.js +19 -30
  22. package/constructs/Parameter.d.ts +2 -10
  23. package/constructs/Parameter.js +2 -2
  24. package/constructs/Queue.d.ts +2 -12
  25. package/constructs/Queue.js +2 -2
  26. package/constructs/RDS.d.ts +2 -22
  27. package/constructs/RDS.js +7 -7
  28. package/constructs/Secret.js +2 -4
  29. package/constructs/SsrSite.js +14 -9
  30. package/constructs/StaticSite.js +14 -9
  31. package/constructs/Table.d.ts +2 -12
  32. package/constructs/Table.js +2 -2
  33. package/constructs/Topic.d.ts +2 -12
  34. package/constructs/Topic.js +2 -2
  35. package/constructs/WebSocketApi.d.ts +2 -10
  36. package/constructs/WebSocketApi.js +2 -2
  37. package/constructs/deprecated/NextjsSite.js +4 -4
  38. package/constructs/util/functionBinding.d.ts +14 -3
  39. package/constructs/util/functionBinding.js +45 -11
  40. package/node/api/index.js +5 -5
  41. package/node/auth/auth.js +9 -53
  42. package/node/bucket/index.js +2 -2
  43. package/node/config/index.js +4 -56
  44. package/node/event-bus/index.js +2 -2
  45. package/node/function/index.js +2 -2
  46. package/node/job/index.js +2 -2
  47. package/node/kinesis-stream/index.js +2 -2
  48. package/node/queue/index.js +2 -2
  49. package/node/rds/index.js +2 -2
  50. package/node/site/index.js +6 -52
  51. package/node/table/index.js +2 -2
  52. package/node/topic/index.js +2 -2
  53. package/node/util/index.d.ts +1 -6
  54. package/node/util/index.js +122 -26
  55. package/package.json +1 -1
  56. package/runtime/handlers/node.js +2 -0
  57. package/runtime/server.js +1 -5
  58. package/sst.mjs +6 -6
  59. package/support/bridge/bridge.mjs +23 -23
  60. /package/support/{ssr-site-function-stub → sls-nextjs-site-function-stub}/index.js +0 -0
@@ -1,3 +1,3 @@
1
- import { createProxy, parseEnvironment } from "../util/index.js";
1
+ import { createProxy, getVariables } from "../util/index.js";
2
2
  export const KinesisStream = createProxy("KinesisStream");
3
- Object.assign(KinesisStream, parseEnvironment("KinesisStream", ["streamName"]));
3
+ Object.assign(KinesisStream, getVariables("KinesisStream"));
@@ -1,3 +1,3 @@
1
- import { createProxy, parseEnvironment } from "../util/index.js";
1
+ import { createProxy, getVariables } from "../util/index.js";
2
2
  export const Queue = createProxy("Queue");
3
- Object.assign(Queue, parseEnvironment("Queue", ["queueUrl"]));
3
+ Object.assign(Queue, getVariables("Queue"));
package/node/rds/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { createProxy, parseEnvironment } from "../util/index.js";
1
+ import { createProxy, getVariables } from "../util/index.js";
2
2
  export const RDS = createProxy("RDS");
3
- Object.assign(RDS, parseEnvironment("RDS", ["clusterArn", "secretArn", "defaultDatabaseName"]));
3
+ Object.assign(RDS, getVariables("RDS"));
@@ -1,62 +1,16 @@
1
- import { GetParametersCommand, SSMClient, } from "@aws-sdk/client-ssm";
2
- const ssm = new SSMClient({});
3
- import { createProxy, parseEnvironment, buildSsmPath, ssmNameToConstructId, } from "../util/index.js";
1
+ import { createProxy, getVariables } from "../util/index.js";
4
2
  export const StaticSite = createProxy("StaticSite");
5
3
  export const ReactStaticSite = createProxy("ReactStaticSite");
6
4
  export const ViteStaticSite = createProxy("ViteStaticSite");
7
5
  export const RemixSite = createProxy("RemixSite");
8
6
  export const NextjsSite = createProxy("NextjsSite");
9
- const staticSiteData = parseEnvironment("StaticSite", ["url"]);
10
- const reactSiteData = parseEnvironment("ReactStaticSite", ["url"]);
11
- const viteSiteData = parseEnvironment("ViteStaticSite", ["url"]);
12
- const nextjsSiteData = parseEnvironment("NextjsSite", ["url"]);
13
- const remixSiteData = parseEnvironment("RemixSite", ["url"]);
14
- await replaceWithSsmValues("StaticSite", staticSiteData);
15
- await replaceWithSsmValues("ReactStaticSite", reactSiteData);
16
- await replaceWithSsmValues("ViteStaticSite", viteSiteData);
17
- await replaceWithSsmValues("NextjsSite", nextjsSiteData);
18
- await replaceWithSsmValues("RemixSite", remixSiteData);
7
+ const staticSiteData = getVariables("StaticSite");
8
+ const reactSiteData = getVariables("ReactStaticSite");
9
+ const viteSiteData = getVariables("ViteStaticSite");
10
+ const nextjsSiteData = getVariables("NextjsSite");
11
+ const remixSiteData = getVariables("RemixSite");
19
12
  Object.assign(StaticSite, staticSiteData);
20
13
  Object.assign(ReactStaticSite, reactSiteData);
21
14
  Object.assign(ViteStaticSite, viteSiteData);
22
15
  Object.assign(NextjsSite, nextjsSiteData);
23
16
  Object.assign(RemixSite, remixSiteData);
24
- async function replaceWithSsmValues(className, siteData) {
25
- // Find all the site data that match the prefix
26
- const names = Object.keys(siteData).filter((name) => siteData[name].url === "__FETCH_FROM_SSM__");
27
- if (names.length === 0) {
28
- return;
29
- }
30
- // Fetch all secrets
31
- const results = await loadSsm(className, names);
32
- if (results.invalidParams.length > 0) {
33
- const missingNames = results.invalidParams.map(ssmNameToConstructId);
34
- throw new Error(`The following ${className} were not found: ${missingNames.join(", ")}`);
35
- }
36
- // Store all secrets in a map
37
- for (const item of results.validParams) {
38
- const name = ssmNameToConstructId(item.Name);
39
- // @ts-ignore
40
- siteData[name] = { url: item.Value };
41
- }
42
- }
43
- async function loadSsm(className, names) {
44
- // Split names into chunks of 10
45
- const chunks = [];
46
- for (let i = 0; i < names.length; i += 10) {
47
- chunks.push(names.slice(i, i + 10));
48
- }
49
- // Fetch secrets
50
- const validParams = [];
51
- const invalidParams = [];
52
- await Promise.all(chunks.map(async (chunk) => {
53
- const command = new GetParametersCommand({
54
- Names: chunk.map((name) => buildSsmPath(className, name, "url")),
55
- WithDecryption: true,
56
- });
57
- const result = await ssm.send(command);
58
- validParams.push(...(result.Parameters || []));
59
- invalidParams.push(...(result.InvalidParameters || []));
60
- }));
61
- return { validParams, invalidParams };
62
- }
@@ -1,3 +1,3 @@
1
- import { createProxy, parseEnvironment } from "../util/index.js";
1
+ import { createProxy, getVariables } from "../util/index.js";
2
2
  export const Table = createProxy("Table");
3
- Object.assign(Table, parseEnvironment("Table", ["tableName"]));
3
+ Object.assign(Table, getVariables("Table"));
@@ -1,3 +1,3 @@
1
- import { createProxy, parseEnvironment } from "../util/index.js";
1
+ import { createProxy, getVariables } from "../util/index.js";
2
2
  export const Topic = createProxy("Topic");
3
- Object.assign(Topic, parseEnvironment("Topic", ["topicArn"]));
3
+ Object.assign(Topic, getVariables("Topic"));
@@ -1,7 +1,2 @@
1
1
  export declare function createProxy<T extends object>(constructName: string): T;
2
- export declare function parseEnvironment(constructName: string, props: string[]): Record<string, Record<string, string>>;
3
- export declare function buildSsmPath(constructName: string, id: string, prop: string): string;
4
- export declare function buildSsmFallbackPath(constructName: string, id: string, prop: string): string;
5
- export declare function ssmNameToConstructId(ssmName: string): string;
6
- export declare function ssmFallbackNameToConstructId(ssmName: string): string;
7
- export declare function ssmNameToPropName(ssmName: string): string | undefined;
2
+ export declare function getVariables(constructName: string): Record<string, Record<string, string>>;
@@ -1,3 +1,15 @@
1
+ import { GetParametersCommand, SSMClient, } from "@aws-sdk/client-ssm";
2
+ const ssm = new SSMClient({});
3
+ // Example:
4
+ // {
5
+ // Bucket: {
6
+ // myBucket: {
7
+ // name: "my-bucket",
8
+ // }
9
+ // }
10
+ // }
11
+ let allVariables = {};
12
+ await parseEnvironment();
1
13
  export function createProxy(constructName) {
2
14
  return new Proxy({}, {
3
15
  get(target, prop) {
@@ -13,41 +25,119 @@ export function createProxy(constructName) {
13
25
  },
14
26
  });
15
27
  }
16
- export function parseEnvironment(constructName, props) {
17
- const acc = {};
28
+ export function getVariables(constructName) {
29
+ return allVariables[constructName] || {};
30
+ }
31
+ async function parseEnvironment() {
32
+ const variablesFromSsm = [];
33
+ const variablesFromSecret = [];
18
34
  Object.keys(process.env)
19
- .filter((env) => env.startsWith(buildEnvPrefix(constructName, props[0])))
20
- .forEach((env) => {
21
- const name = env.replace(new RegExp(`^${buildEnvPrefix(constructName, props[0])}`), "");
22
- // @ts-ignore
23
- acc[name] = {};
24
- props.forEach((prop) => {
25
- // @ts-ignore
26
- acc[name][prop] =
27
- process.env[`${buildEnvPrefix(constructName, prop)}${name}`];
28
- });
35
+ .filter((name) => name.startsWith("SST_"))
36
+ .forEach((name) => {
37
+ const variable = parseEnvName(name);
38
+ // Ignore if env var is not in the correct format
39
+ if (!variable.constructName ||
40
+ !variable.constructId ||
41
+ !variable.propName) {
42
+ return;
43
+ }
44
+ const value = process.env[name];
45
+ if (value === "__FETCH_FROM_SSM__") {
46
+ variablesFromSsm.push(variable);
47
+ }
48
+ else if (value.startsWith("__FETCH_FROM_SECRET__:")) {
49
+ variablesFromSecret.push([variable, value.split(":")[1]]);
50
+ }
51
+ else {
52
+ storeVariable(variable, value);
53
+ }
54
+ });
55
+ // Fetch values from SSM
56
+ await fetchValuesFromSSM(variablesFromSsm);
57
+ // Fetch values from Secrets
58
+ variablesFromSecret.forEach(([variable, secretName]) => {
59
+ const value = allVariables["Secret"]?.[secretName]?.value;
60
+ if (value) {
61
+ storeVariable(variable, value);
62
+ }
29
63
  });
30
- return acc;
64
+ return allVariables;
31
65
  }
32
- function buildEnvPrefix(constructName, prop) {
33
- return `SST_${constructName}_${prop}_`;
66
+ async function fetchValuesFromSSM(variablesFromSsm) {
67
+ // Get all env vars that need to be fetched from SSM
68
+ const ssmPaths = variablesFromSsm.map((variable) => buildSsmPath(variable));
69
+ if (ssmPaths.length === 0)
70
+ return;
71
+ // Fetch
72
+ const results = await loadSecrets(ssmPaths);
73
+ results.validParams.forEach((item) => {
74
+ const variable = parseSsmPath(item.Name);
75
+ storeVariable(variable, item.Value);
76
+ });
77
+ // Get all fallback values to be fetched
78
+ const ssmFallbackPaths = results.invalidParams
79
+ .map((name) => parseSsmPath(name))
80
+ .filter((variable) => variable.constructName === "Secret")
81
+ .map((variable) => buildSsmFallbackPath(variable));
82
+ if (ssmFallbackPaths.length === 0)
83
+ return;
84
+ // Fetch fallback values
85
+ const fallbackResults = await loadSecrets(ssmFallbackPaths);
86
+ fallbackResults.validParams.forEach((item) => {
87
+ const variable = parseSsmFallbackPath(item.Name);
88
+ storeVariable(variable, item.Value);
89
+ });
34
90
  }
35
- export function buildSsmPath(constructName, id, prop) {
36
- return `${ssmPrefix()}${constructName}/${id}/${prop}`;
91
+ async function loadSecrets(paths) {
92
+ // Split paths into chunks of 10
93
+ const chunks = [];
94
+ for (let i = 0; i < paths.length; i += 10) {
95
+ chunks.push(paths.slice(i, i + 10));
96
+ }
97
+ // Fetch secrets
98
+ const validParams = [];
99
+ const invalidParams = [];
100
+ await Promise.all(chunks.map(async (chunk) => {
101
+ const command = new GetParametersCommand({
102
+ Names: chunk,
103
+ WithDecryption: true,
104
+ });
105
+ const result = await ssm.send(command);
106
+ validParams.push(...(result.Parameters || []));
107
+ invalidParams.push(...(result.InvalidParameters || []));
108
+ }));
109
+ return { validParams, invalidParams };
37
110
  }
38
- export function buildSsmFallbackPath(constructName, id, prop) {
39
- return `/sst/${process.env.SST_APP}/.fallback/${constructName}/${id}/${prop}`;
111
+ function parseEnvName(env) {
112
+ const [_SST, constructName, propName, ...idParts] = env.split("_");
113
+ return {
114
+ constructName,
115
+ constructId: idParts.join("_"),
116
+ propName,
117
+ };
40
118
  }
41
- export function ssmNameToConstructId(ssmName) {
119
+ function parseSsmPath(path) {
42
120
  const prefix = ssmPrefix();
43
- return ssmName.substring(prefix.length).split("/")[1];
121
+ const parts = path.substring(prefix.length).split("/");
122
+ return {
123
+ constructName: parts[0],
124
+ constructId: parts[1],
125
+ propName: parts[2],
126
+ };
44
127
  }
45
- export function ssmFallbackNameToConstructId(ssmName) {
46
- return ssmName.split("/")[5];
128
+ function parseSsmFallbackPath(path) {
129
+ const parts = path.split("/");
130
+ return {
131
+ constructName: parts[4],
132
+ constructId: parts[5],
133
+ propName: parts[6],
134
+ };
47
135
  }
48
- export function ssmNameToPropName(ssmName) {
49
- const prefix = ssmPrefix();
50
- return ssmName.substring(prefix.length).split("/").pop();
136
+ function buildSsmPath(data) {
137
+ return `${ssmPrefix()}${data.constructName}/${data.constructId}/${data.propName}`;
138
+ }
139
+ function buildSsmFallbackPath(data) {
140
+ return `/sst/${process.env.SST_APP}/.fallback/${data.constructName}/${data.constructId}/${data.propName}`;
51
141
  }
52
142
  function normalizeId(name) {
53
143
  return name.replace(/-/g, "_");
@@ -55,3 +145,9 @@ function normalizeId(name) {
55
145
  function ssmPrefix() {
56
146
  return process.env.SST_SSM_PREFIX || "";
57
147
  }
148
+ function storeVariable(variable, value) {
149
+ const { constructId: id, constructName: c, propName: prop } = variable;
150
+ allVariables[c] = allVariables[c] || {};
151
+ allVariables[c][id] = allVariables[c][id] || {};
152
+ allVariables[c][id][prop] = value;
153
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.0.35",
3
+ "version": "2.0.37",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
@@ -118,6 +118,8 @@ export const useNodeHandler = Context.memo(async () => {
118
118
  js: [
119
119
  `import { createRequire as topLevelCreateRequire } from 'module';`,
120
120
  `const require = topLevelCreateRequire(import.meta.url);`,
121
+ `import { fileURLToPath as topLevelFileUrlToPath } from "url"`,
122
+ `const __dirname = topLevelFileUrlToPath(new URL(".", import.meta.url))`,
121
123
  nodejs.banner || "",
122
124
  ].join("\n"),
123
125
  },
package/runtime/server.js CHANGED
@@ -74,11 +74,7 @@ export const useRuntimeServer = Context.memo(async () => {
74
74
  "Lambda-Runtime-Deadline-Ms": Date.now() + payload.deadline,
75
75
  "Lambda-Runtime-Invoked-Function-Arn": payload.context.invokedFunctionArn,
76
76
  "Lambda-Runtime-Client-Context": JSON.stringify(payload.context.clientContext || {}),
77
- ...(payload.context.identity
78
- ? {
79
- "Lambda-Runtime-Cognito-Identity": JSON.stringify(payload.context.identity),
80
- }
81
- : {}),
77
+ "Lambda-Runtime-Cognito-Identity": JSON.stringify(payload.context.identity || {}),
82
78
  });
83
79
  res.json(payload.event);
84
80
  });
package/sst.mjs CHANGED
@@ -2302,11 +2302,9 @@ var init_server2 = __esm({
2302
2302
  "Lambda-Runtime-Client-Context": JSON.stringify(
2303
2303
  payload.context.clientContext || {}
2304
2304
  ),
2305
- ...payload.context.identity ? {
2306
- "Lambda-Runtime-Cognito-Identity": JSON.stringify(
2307
- payload.context.identity
2308
- )
2309
- } : {}
2305
+ "Lambda-Runtime-Cognito-Identity": JSON.stringify(
2306
+ payload.context.identity || {}
2307
+ )
2310
2308
  });
2311
2309
  res.json(payload.event);
2312
2310
  }
@@ -2711,7 +2709,7 @@ async function bootstrapSST(tags) {
2711
2709
  path8.resolve(__dirname, "support/bootstrap-metadata-function")
2712
2710
  ),
2713
2711
  handler: "index.handler",
2714
- runtime: app.region?.startsWith("us-gov-") ? Runtime.NODEJS_16_X : Runtime.NODEJS_18_X,
2712
+ runtime: project.config.region?.startsWith("us-gov-") ? Runtime.NODEJS_16_X : Runtime.NODEJS_18_X,
2715
2713
  environment: {
2716
2714
  BUCKET_NAME: bucket.bucketName
2717
2715
  },
@@ -4869,6 +4867,8 @@ var init_node = __esm({
4869
4867
  js: [
4870
4868
  `import { createRequire as topLevelCreateRequire } from 'module';`,
4871
4869
  `const require = topLevelCreateRequire(import.meta.url);`,
4870
+ `import { fileURLToPath as topLevelFileUrlToPath } from "url"`,
4871
+ `const __dirname = topLevelFileUrlToPath(new URL(".", import.meta.url))`,
4872
4872
  nodejs.banner || ""
4873
4873
  ].join("\n")
4874
4874
  }