sst 2.0.0-rc.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/bootstrap.d.ts +2 -4
  2. package/bootstrap.js +208 -61
  3. package/bus.d.ts +3 -3
  4. package/bus.js +1 -1
  5. package/cache.js +1 -1
  6. package/cdk/cloudformation-deployments-wrapper.d.ts +3 -0
  7. package/cdk/cloudformation-deployments-wrapper.js +117 -0
  8. package/cdk/cloudformation-deployments.d.ts +19 -4
  9. package/cdk/deploy-stack.d.ts +17 -2
  10. package/cdk/deploy-stack.js +6 -1
  11. package/cli/colors.d.ts +28 -0
  12. package/cli/colors.js +27 -0
  13. package/cli/commands/bind.d.ts +4 -0
  14. package/cli/commands/bind.js +10 -7
  15. package/cli/commands/bootstrap.d.ts +13 -0
  16. package/cli/commands/bootstrap.js +11 -0
  17. package/cli/commands/build.d.ts +6 -2
  18. package/cli/commands/build.js +13 -8
  19. package/cli/commands/console.d.ts +5 -1
  20. package/cli/commands/console.js +8 -6
  21. package/cli/commands/deploy.d.ts +4 -2
  22. package/cli/commands/deploy.js +71 -29
  23. package/cli/commands/dev.d.ts +5 -1
  24. package/cli/commands/dev.js +157 -79
  25. package/cli/commands/diff.d.ts +15 -0
  26. package/cli/commands/diff.js +61 -0
  27. package/cli/commands/env.d.ts +5 -1
  28. package/cli/commands/env.js +14 -15
  29. package/cli/commands/plugins/kysely.js +13 -5
  30. package/cli/commands/plugins/pothos.js +9 -4
  31. package/cli/commands/remove.d.ts +4 -0
  32. package/cli/commands/remove.js +26 -18
  33. package/cli/commands/secrets/get.d.ts +7 -3
  34. package/cli/commands/secrets/get.js +11 -24
  35. package/cli/commands/secrets/list.d.ts +6 -2
  36. package/cli/commands/secrets/list.js +15 -7
  37. package/cli/commands/secrets/remove.d.ts +8 -4
  38. package/cli/commands/secrets/remove.js +18 -16
  39. package/cli/commands/secrets/secrets.js +3 -3
  40. package/cli/commands/secrets/set.d.ts +8 -6
  41. package/cli/commands/secrets/set.js +16 -33
  42. package/cli/commands/telemetry.d.ts +15 -0
  43. package/cli/commands/telemetry.js +17 -0
  44. package/cli/commands/transform.d.ts +15 -0
  45. package/cli/commands/transform.js +55 -0
  46. package/cli/commands/update.d.ts +6 -2
  47. package/cli/commands/update.js +41 -33
  48. package/cli/commands/version.d.ts +13 -0
  49. package/cli/commands/version.js +7 -0
  50. package/cli/local/router.d.ts +6 -6
  51. package/cli/local/router.js +3 -3
  52. package/cli/local/server.d.ts +5 -3
  53. package/cli/local/server.js +21 -14
  54. package/cli/program.d.ts +5 -1
  55. package/cli/program.js +29 -5
  56. package/cli/spinner.js +2 -0
  57. package/cli/sst.js +35 -23
  58. package/cli/telemetry/environment.d.ts +1 -1
  59. package/cli/telemetry/environment.js +1 -1
  60. package/cli/terminal.d.ts +1 -0
  61. package/cli/terminal.js +8 -0
  62. package/cli/ui/deploy.d.ts +3 -2
  63. package/cli/ui/deploy.js +106 -106
  64. package/cli/ui/functions.d.ts +2 -0
  65. package/cli/ui/functions.js +132 -0
  66. package/cli/ui/header.d.ts +5 -0
  67. package/cli/ui/header.js +16 -0
  68. package/cli/ui/stack.d.ts +1 -0
  69. package/cli/ui/stack.js +6 -0
  70. package/config.d.ts +1 -1
  71. package/config.js +8 -8
  72. package/constructs/Api.d.ts +3 -71
  73. package/constructs/Api.js +3 -42
  74. package/constructs/ApiGatewayV1Api.d.ts +3 -3
  75. package/constructs/ApiGatewayV1Api.js +4 -3
  76. package/constructs/App.d.ts +2 -22
  77. package/constructs/App.js +12 -25
  78. package/constructs/AppSyncApi.d.ts +4 -5
  79. package/constructs/AppSyncApi.js +8 -5
  80. package/constructs/AstroSite.d.ts +2 -3
  81. package/constructs/AstroSite.js +43 -53
  82. package/constructs/Auth.js +27 -16
  83. package/constructs/BaseSite.d.ts +10 -10
  84. package/constructs/BaseSite.js +2 -2
  85. package/constructs/Cognito.js +28 -28
  86. package/constructs/EdgeFunction.d.ts +6 -4
  87. package/constructs/EdgeFunction.js +56 -59
  88. package/constructs/EventBus.js +1 -1
  89. package/constructs/Function.d.ts +4 -44
  90. package/constructs/Function.js +14 -50
  91. package/constructs/FunctionalStack.d.ts +2 -2
  92. package/constructs/Job.d.ts +23 -63
  93. package/constructs/Job.js +11 -32
  94. package/constructs/Metadata.d.ts +18 -20
  95. package/constructs/NextjsSite.d.ts +21 -5
  96. package/constructs/NextjsSite.js +67 -101
  97. package/constructs/Queue.js +10 -10
  98. package/constructs/RDS.d.ts +1 -1
  99. package/constructs/RDS.js +1 -1
  100. package/constructs/RemixSite.d.ts +0 -2
  101. package/constructs/RemixSite.js +20 -20
  102. package/constructs/Script.js +1 -1
  103. package/constructs/Secret.js +5 -3
  104. package/constructs/SolidStartSite.d.ts +2 -3
  105. package/constructs/SolidStartSite.js +42 -52
  106. package/constructs/SsrFunction.d.ts +22 -0
  107. package/constructs/SsrFunction.js +113 -0
  108. package/constructs/SsrSite.d.ts +104 -104
  109. package/constructs/SsrSite.js +196 -217
  110. package/constructs/Stack.d.ts +1 -20
  111. package/constructs/Stack.js +3 -65
  112. package/constructs/StaticSite.d.ts +33 -53
  113. package/constructs/StaticSite.js +92 -118
  114. package/constructs/Table.d.ts +1 -1
  115. package/constructs/Table.js +4 -4
  116. package/constructs/Topic.js +1 -1
  117. package/constructs/cdk/certificate-base.d.ts +18 -0
  118. package/constructs/cdk/certificate-base.js +26 -0
  119. package/constructs/cdk/dns-validated-certificate.d.ts +77 -0
  120. package/constructs/cdk/dns-validated-certificate.js +125 -0
  121. package/constructs/cdk/website-redirect.d.ts +53 -0
  122. package/constructs/cdk/website-redirect.js +77 -0
  123. package/constructs/deferred_task.d.ts +1 -1
  124. package/constructs/deprecated/NextjsSite.js +8 -6
  125. package/constructs/index.d.ts +0 -6
  126. package/constructs/index.js +0 -6
  127. package/constructs/util/apiGatewayV1AccessLog.d.ts +1 -1
  128. package/constructs/util/apiGatewayV2AccessLog.js +4 -4
  129. package/constructs/util/apiGatewayV2Domain.js +9 -2
  130. package/constructs/util/appSyncApiDomain.d.ts +1 -1
  131. package/constructs/util/appSyncApiDomain.js +9 -15
  132. package/constructs/util/duration.d.ts +1 -1
  133. package/constructs/util/functionBinding.js +1 -1
  134. package/constructs/util/permission.d.ts +3 -3
  135. package/constructs/util/permission.js +16 -18
  136. package/constructs/util/size.d.ts +1 -1
  137. package/constructs/util/warning.js +2 -2
  138. package/context/context.d.ts +2 -2
  139. package/context/context.js +4 -4
  140. package/context/handler.d.ts +1 -1
  141. package/credentials.d.ts +1 -1
  142. package/credentials.js +42 -6
  143. package/index.d.ts +1 -0
  144. package/index.js +1 -0
  145. package/iot.js +6 -2
  146. package/logger.js +3 -1
  147. package/node/api/index.d.ts +4 -3
  148. package/node/api/index.js +8 -2
  149. package/node/auth/adapter/adapter.d.ts +1 -1
  150. package/node/auth/adapter/facebook.js +1 -1
  151. package/node/auth/adapter/github.js +4 -4
  152. package/node/auth/adapter/google.d.ts +1 -1
  153. package/node/auth/adapter/google.js +2 -2
  154. package/node/auth/adapter/twitch.js +1 -1
  155. package/node/auth/session.d.ts +1 -1
  156. package/node/config/index.d.ts +2 -2
  157. package/node/config/index.js +3 -8
  158. package/node/job/index.d.ts +2 -2
  159. package/node/site/index.js +3 -5
  160. package/package.json +26 -21
  161. package/pothos.js +1 -0
  162. package/project.d.ts +47 -0
  163. package/{app.js → project.js} +60 -53
  164. package/runtime/handlers/dotnet.d.ts +1 -1
  165. package/runtime/handlers/dotnet.js +4 -4
  166. package/runtime/handlers/go.d.ts +1 -1
  167. package/runtime/handlers/go.js +3 -3
  168. package/runtime/handlers/java.d.ts +1 -1
  169. package/runtime/handlers/java.js +4 -4
  170. package/runtime/handlers/node.d.ts +1 -1
  171. package/runtime/handlers/node.js +60 -39
  172. package/runtime/handlers/python.d.ts +1 -1
  173. package/runtime/handlers/python.js +3 -3
  174. package/runtime/handlers.js +15 -12
  175. package/runtime/iot.js +3 -0
  176. package/runtime/runtime.d.ts +4 -0
  177. package/runtime/server.d.ts +3 -3
  178. package/runtime/server.js +11 -5
  179. package/runtime/workers.d.ts +4 -2
  180. package/runtime/workers.js +13 -3
  181. package/site-env.js +2 -1
  182. package/sst.mjs +6357 -20846
  183. package/stacks/app-metadata.d.ts +7 -0
  184. package/stacks/app-metadata.js +78 -0
  185. package/stacks/assembly.d.ts +1 -0
  186. package/stacks/assembly.js +4 -0
  187. package/stacks/build.d.ts +1 -1
  188. package/stacks/build.js +41 -48
  189. package/stacks/deploy.d.ts +1 -0
  190. package/stacks/deploy.js +128 -7
  191. package/stacks/diff.d.ts +8 -0
  192. package/stacks/diff.js +62 -0
  193. package/stacks/index.d.ts +3 -0
  194. package/stacks/index.js +3 -0
  195. package/stacks/metadata.d.ts +2 -0
  196. package/stacks/metadata.js +14 -12
  197. package/stacks/monitor.d.ts +8 -3
  198. package/stacks/monitor.js +38 -4
  199. package/stacks/remove.js +0 -4
  200. package/stacks/synth.d.ts +1 -0
  201. package/stacks/synth.js +27 -13
  202. package/support/base-site-archiver.mjs +1 -1
  203. package/support/bootstrap-metadata-function/index.mjs +68740 -0
  204. package/support/bridge/bridge.mjs +28 -28
  205. package/support/certificate-requestor/index.js +549 -0
  206. package/support/custom-resources/index.mjs +3824 -26567
  207. package/support/dotnet6-bootstrap/release/dotnet-bootstrap.deps.json +1 -1
  208. package/support/dotnet6-bootstrap/release/dotnet-bootstrap.runtimeconfig.json +1 -1
  209. package/support/edge-function/edge-lambda.mjs +2 -2
  210. package/support/job-invoker/index.mjs +26 -0
  211. package/support/nodejs-runtime/index.mjs +75 -72
  212. package/support/rds-migrator/index.mjs +22 -23
  213. package/support/remix-site-function/edge-server.js +1 -1
  214. package/support/script-function/index.mjs +30485 -0
  215. package/support/{edge-function-code-replacer → sls-nextjs-site-function-code-replacer}/lambda-code-updater.py +0 -0
  216. package/support/ssr-site-function-archiver.mjs +96 -0
  217. package/util/process.d.ts +0 -1
  218. package/watcher.js +1 -1
  219. package/app.d.ts +0 -36
  220. package/constructs/DebugApp.d.ts +0 -49
  221. package/constructs/DebugApp.js +0 -63
  222. package/constructs/DebugStack.d.ts +0 -34
  223. package/constructs/DebugStack.js +0 -132
  224. package/constructs/GraphQLApi.d.ts +0 -98
  225. package/constructs/GraphQLApi.js +0 -80
  226. package/constructs/ReactStaticSite.d.ts +0 -20
  227. package/constructs/ReactStaticSite.js +0 -54
  228. package/constructs/Script/cfn-response.d.ts +0 -19
  229. package/constructs/Script/cfn-response.js +0 -77
  230. package/constructs/Script/index.d.ts +0 -1
  231. package/constructs/Script/index.js +0 -78
  232. package/constructs/Script/outbound.d.ts +0 -10
  233. package/constructs/Script/outbound.js +0 -42
  234. package/constructs/Script/util.d.ts +0 -2
  235. package/constructs/Script/util.js +0 -11
  236. package/constructs/ViteStaticSite.d.ts +0 -32
  237. package/constructs/ViteStaticSite.js +0 -66
  238. package/support/astro-site-html-stub/index.html +0 -99
  239. package/support/base-site-archiver.cjs +0 -116
  240. package/support/nextjs-site-html-stub/index.html +0 -99
  241. package/support/remix-site-html-stub/index.html +0 -99
  242. package/support/solid-start-site-html-stub/index.html +0 -99
  243. package/support/static-site-stub/index.html +0 -90
package/cli/ui/deploy.js CHANGED
@@ -3,66 +3,39 @@ import { Box, Text } from "ink";
3
3
  import { useBus } from "../../bus.js";
4
4
  import { Stacks } from "../../stacks/index.js";
5
5
  import inkSpinner from "ink-spinner";
6
- import { useProject } from "../../app.js";
7
- import { blue, bold, green, red } from "colorette";
6
+ import { Colors } from "../colors.js";
7
+ import { useProject } from "../../project.js";
8
8
  // @ts-ignore
9
9
  const { default: Spinner } = inkSpinner;
10
- const FullScreen = (props) => {
11
- const [size, setSize] = useState({
12
- columns: process.stdout.columns,
13
- rows: process.stdout.rows,
14
- });
15
- useEffect(() => {
16
- function onResize() {
17
- setSize({
18
- columns: process.stdout.columns,
19
- rows: process.stdout.rows,
20
- });
21
- }
22
- process.stdout.on("resize", onResize);
23
- return () => {
24
- process.stdout.off("resize", onResize);
25
- };
26
- }, []);
27
- return (React.createElement(Box, { width: size.columns, height: size.rows, flexDirection: "column" }, props.children));
28
- };
29
10
  export const DeploymentUI = (props) => {
30
- const [stacks, setStacks] = useState(Object.fromEntries(props.stacks.map((s) => [s, ""])));
31
11
  const [resources, setResources] = useState({});
32
12
  useEffect(() => {
13
+ Colors.gap();
33
14
  const bus = useBus();
34
- const update = bus.subscribe("stack.updated", (payload) => {
35
- setStacks((prev) => ({
36
- ...prev,
37
- [payload.properties.stackID]: "",
38
- }));
39
- });
40
- const status = bus.subscribe("stack.status", (payload) => {
41
- setStacks((prev) => ({
42
- ...prev,
43
- [payload.properties.stackID]: payload.properties.status,
44
- }));
45
- });
46
- const resourcesSub = bus.subscribe("stack.resources", (payload) => {
15
+ const event = bus.subscribe("stack.event", (payload) => {
16
+ const { event } = payload.properties;
17
+ // if (event.ResourceType === "AWS::CloudFormation::Stack") return;
47
18
  setResources((previous) => {
48
- const existing = previous[payload.properties.stackID] || [];
49
- const filtered = (payload.properties.resources || []).filter((r) => {
50
- if (existing.some((p) => p.LogicalResourceId === r.LogicalResourceId))
51
- return true;
52
- if (!Stacks.isFinal(r.ResourceStatus))
53
- return true;
54
- return false;
55
- });
19
+ if (Stacks.isFinal(event.ResourceStatus)) {
20
+ const readable = logicalIdToCdkPath(props.assembly, event.StackName, event.LogicalResourceId);
21
+ Colors.line(Colors.warning(Colors.prefix), readable
22
+ ? Colors.dim(`${stackNameToId(event.StackName)} ${readable} ${event.ResourceType}`)
23
+ : Colors.dim(`${stackNameToId(event.StackName)} ${event.ResourceType}`), Stacks.isFailed(event.ResourceStatus)
24
+ ? Colors.danger(event.ResourceStatus)
25
+ : Colors.dim(event.ResourceStatus), Stacks.isFailed(event.ResourceStatus) && event.ResourceStatusReason
26
+ ? event.ResourceStatusReason
27
+ : "");
28
+ const { [event.LogicalResourceId]: _, ...next } = previous;
29
+ return next;
30
+ }
56
31
  return {
57
32
  ...previous,
58
- [payload.properties.stackID]: filtered,
33
+ [payload.properties.event.LogicalResourceId]: payload.properties.event,
59
34
  };
60
35
  });
61
36
  });
62
37
  return () => {
63
- bus.unsubscribe(resourcesSub);
64
- bus.unsubscribe(update);
65
- bus.unsubscribe(status);
38
+ bus.unsubscribe(event);
66
39
  };
67
40
  }, []);
68
41
  function color(status) {
@@ -72,71 +45,98 @@ export const DeploymentUI = (props) => {
72
45
  return "green";
73
46
  return "yellow";
74
47
  }
75
- return (React.createElement(FullScreen, null,
76
- React.createElement(Text, null,
77
- "Deploying ",
78
- React.createElement(Text, { color: "bold" }, props.stacks.length),
79
- " stacks for stage ",
80
- React.createElement(Text, { color: "blue" }, useProject().stage)),
81
- Object.entries(stacks).map(([stackID, status]) => {
82
- return (React.createElement(React.Fragment, { key: stackID },
48
+ return (React.createElement(Box, { flexDirection: "column" },
49
+ Object.entries(resources)
50
+ .slice(0, process.stdout.rows - 2)
51
+ .map(([_, evt], index) => {
52
+ const readable = logicalIdToCdkPath(props.assembly, evt.StackName, evt.LogicalResourceId);
53
+ return (React.createElement(Box, { key: index },
83
54
  React.createElement(Text, null,
84
- !Stacks.isFinal(status) && React.createElement(Spinner, null),
85
- Stacks.isSuccess(status) && React.createElement(Text, { color: color(status) }, "\u2714"),
86
- Stacks.isFailed(status) && React.createElement(Text, { color: color(status) }, "\u2716"),
87
- React.createElement(Text, null, " " + stackID),
88
- status && React.createElement(Text, { color: color(status) },
89
- " ",
90
- status)),
91
- resources[stackID]?.map((resource) => (React.createElement(Box, { key: resource.LogicalResourceId },
92
- React.createElement(Text, null,
93
- " ",
94
- !Stacks.isFinal(resource.ResourceStatus || "") && (React.createElement(Spinner, null)),
95
- Stacks.isSuccess(resource.ResourceStatus || "") && (React.createElement(Text, { color: "green" }, "\u2714")),
96
- Stacks.isFailed(resource.ResourceStatus || "") && (React.createElement(Text, { color: "red" }, "\u2716")),
97
- " ",
98
- resource.ResourceType,
99
- " ",
100
- resource.LogicalResourceId,
101
- " ",
102
- resource.ResourceStatusReason,
103
- " "),
104
- React.createElement(Text, { color: color(resource.ResourceStatus || "") }, resource.ResourceStatus))))));
105
- })));
55
+ React.createElement(Spinner, null),
56
+ " ",
57
+ readable
58
+ ? `${stackNameToId(evt.StackName)} ${readable} ${evt.ResourceType}`
59
+ : `${stackNameToId(evt.StackName)} ${evt.ResourceType}`,
60
+ " "),
61
+ React.createElement(Text, { color: color(evt.ResourceStatus || "") }, evt.ResourceStatus)));
62
+ }),
63
+ Object.entries(resources).length === 0 && (React.createElement(Box, null,
64
+ React.createElement(Text, null,
65
+ React.createElement(Spinner, null),
66
+ " ",
67
+ React.createElement(Text, { dimColor: true }, "Deploying..."))))));
106
68
  };
107
- export function printDeploymentResults(results) {
108
- console.log();
109
- console.log(`----------------------------`);
110
- console.log(`| Stack deployment results |`);
111
- console.log(`----------------------------`);
112
- for (const [stack, result] of Object.entries(results)) {
113
- const icon = (() => {
114
- if (Stacks.isSuccess(result.status))
115
- return green("✔");
116
- if (Stacks.isFailed(result.status))
117
- return red("✖");
118
- })();
119
- console.log(`${icon} ${stack}`);
120
- const outputs = Object.entries(result.outputs).filter(([key, _]) => {
121
- if (key.startsWith("Export"))
122
- return false;
123
- if (key.includes("SstSiteEnv"))
124
- return false;
125
- return true;
126
- });
127
- if (outputs.length > 0) {
128
- console.log(` ${blue("Outputs:")}`);
129
- for (const key of Object.keys(Object.fromEntries(outputs)).sort()) {
130
- const value = result.outputs[key];
131
- console.log(bold(` ${key}: ${value}`));
69
+ export function printDeploymentResults(assembly, results, remove) {
70
+ // Print success stacks
71
+ const success = Object.entries(results).filter(([_stack, result]) => Stacks.isSuccess(result.status));
72
+ if (success.length) {
73
+ Colors.gap();
74
+ Colors.line(Colors.success(`✔`), Colors.bold(remove ? ` Removed:` : ` Deployed:`));
75
+ for (const [stack, result] of success) {
76
+ const outputs = Object.entries(result.outputs).filter(([key, _]) => !key.includes("SstSiteEnv"));
77
+ Colors.line(` ${Colors.dim(stackNameToId(stack))}`);
78
+ if (outputs.length > 0) {
79
+ for (const key of Object.keys(Object.fromEntries(outputs)).sort()) {
80
+ const value = result.outputs[key];
81
+ Colors.line(` ${Colors.bold.dim(key + ":")} ${value}`);
82
+ }
132
83
  }
133
84
  }
134
- if (Object.entries(result.errors).length > 0) {
135
- console.log(` ${red("Errors:")}`);
85
+ Colors.gap();
86
+ }
87
+ // Print failed stacks
88
+ const failed = Object.entries(results).filter(([_stack, result]) => Stacks.isFailed(result.status));
89
+ if (failed.length) {
90
+ Colors.gap();
91
+ Colors.line(`${Colors.danger(`✖`)} ${Colors.bold.dim(`Errors`)}`);
92
+ for (const [stack, result] of failed) {
93
+ Colors.line(` ${Colors.dim(stackNameToId(stack))} ${Colors.dim(result.status)}`);
136
94
  for (const [id, error] of Object.entries(result.errors)) {
137
- console.log(bold(` ${id}: ${error}`));
95
+ const readable = logicalIdToCdkPath(assembly, stack, id) || id;
96
+ Colors.line(` ${Colors.danger.bold(readable + ":")} ${error}`);
97
+ const helper = getHelper(error);
98
+ if (helper) {
99
+ Colors.line(` ${Colors.warning.bold("⮑ Hint:")} ${helper}`);
100
+ }
138
101
  }
139
102
  }
103
+ Colors.gap();
104
+ }
105
+ }
106
+ function stackNameToId(stack) {
107
+ const project = useProject();
108
+ const prefix = `${project.config.stage}-${project.config.name}-`;
109
+ return stack.startsWith(prefix) ? stack.substring(prefix.length) : stack;
110
+ }
111
+ function logicalIdToCdkPath(assembly, stack, logicalId) {
112
+ const found = Object.entries(assembly.manifest.artifacts?.[stack].metadata || {}).find(([_key, value]) => value[0]?.type === "aws:cdk:logicalId" && value[0]?.data === logicalId)?.[0];
113
+ if (!found) {
114
+ return;
115
+ }
116
+ return found.split("/").filter(Boolean).slice(1, -1).join("/");
117
+ }
118
+ function getHelper(error) {
119
+ return (getApiAccessLogPermissionsHelper(error) ||
120
+ getAppSyncMultiResolverHelper(error) ||
121
+ getApiLogRoleHelper(error));
122
+ }
123
+ function getApiAccessLogPermissionsHelper(error) {
124
+ // Can run into this issue when enabling access logs for API Gateway
125
+ // note: this should be handled in SST as access log group names are now
126
+ // hardcoded with /aws/vendedlogs/apis prefix.
127
+ if (error.indexOf("Insufficient permissions to enable logging") > -1) {
128
+ return `This is a common deploy error. Check out this GitHub issue for more details - https://github.com/serverless-stack/sst/issues/125`;
129
+ }
130
+ }
131
+ function getAppSyncMultiResolverHelper(error) {
132
+ // Can run into this issue when updating an AppSyncApi resolver
133
+ if (error.indexOf("Only one resolver is allowed per field. (Service: AWSAppSync") > -1) {
134
+ return `This is a common error for deploying AppSync APIs. Check out this GitHub issue for more details - https://github.com/aws/aws-cdk/issues/13269`;
135
+ }
136
+ }
137
+ function getApiLogRoleHelper(error) {
138
+ // Can run into this issue when enabling access logs for WebSocketApi
139
+ if (error.indexOf("CloudWatch Logs role ARN must be set in account settings to enable logging (Service: AmazonApiGatewayV2") > -1) {
140
+ return `This is a common error when configuring Access Log for WebSocket APIs. The AWS API Gateway service in your AWS account does not have permissions to the CloudWatch logs service. Follow this article to create an IAM role for logging to CloudWatch - https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cloudwatch-logs/`;
140
141
  }
141
- console.log();
142
142
  }
@@ -0,0 +1,2 @@
1
+ /// <reference types="react" resolution-mode="require"/>
2
+ export declare function Functions(): JSX.Element;
@@ -0,0 +1,132 @@
1
+ import { dim } from "colorette";
2
+ import { Text } from "ink";
3
+ import inkSpinner from "ink-spinner";
4
+ import React, { useEffect, useState } from "react";
5
+ import { useBus } from "../../bus.js";
6
+ import { useFunctions } from "../../constructs/Function.js";
7
+ import { Colors } from "../colors.js";
8
+ // @ts-ignore
9
+ const { default: Spinner } = inkSpinner;
10
+ export function Functions() {
11
+ const [functions, setFunctions] = useState({});
12
+ useEffect(() => {
13
+ const bus = useBus();
14
+ const invoke = bus.subscribe("function.invoked", (evt) => {
15
+ setFunctions((functions) => {
16
+ setTimeout(() => {
17
+ setFunctions((functions) => {
18
+ const existing = functions[evt.properties.requestID];
19
+ if (!existing)
20
+ return functions;
21
+ return { ...functions };
22
+ });
23
+ }, 500);
24
+ return {
25
+ ...functions,
26
+ [evt.properties.requestID]: {
27
+ requestID: evt.properties.requestID,
28
+ functionID: evt.properties.functionID,
29
+ started: Date.now(),
30
+ logs: [],
31
+ },
32
+ };
33
+ });
34
+ });
35
+ const stdout = bus.subscribe("worker.stdout", (evt) => {
36
+ setFunctions((functions) => {
37
+ const existing = functions[evt.properties.requestID];
38
+ if (!existing)
39
+ return functions;
40
+ return {
41
+ ...functions,
42
+ [evt.properties.requestID]: {
43
+ ...existing,
44
+ logs: [...existing.logs, evt.properties.message],
45
+ },
46
+ };
47
+ });
48
+ });
49
+ // This is all ugly but the timeouts are for UI smootheness
50
+ const success = bus.subscribe("function.success", (evt) => {
51
+ function print(input, diff) {
52
+ setTimeout(() => {
53
+ console.log(Colors.primary(` ➜ `), useFunctions().fromID(input.functionID).handler);
54
+ for (const log of input.logs) {
55
+ console.log(` ${dim(log)}`);
56
+ }
57
+ console.log(` ${dim(`Done in ${diff}ms`)}`);
58
+ console.log();
59
+ }, diff > 500 ? 60 : 0);
60
+ }
61
+ setFunctions((functions) => {
62
+ const { [evt.properties.requestID]: existing, ...next } = functions;
63
+ if (!existing)
64
+ return functions;
65
+ const diff = Date.now() - existing.started;
66
+ if (diff > 500 && diff < 1500) {
67
+ setTimeout(() => {
68
+ setFunctions((functions) => {
69
+ const { [evt.properties.requestID]: existing, ...next } = functions;
70
+ print(existing, diff);
71
+ return next;
72
+ });
73
+ }, 1500 - diff);
74
+ return functions;
75
+ }
76
+ print(existing, diff);
77
+ return next;
78
+ });
79
+ });
80
+ const error = bus.subscribe("function.error", (evt) => {
81
+ function print(input, diff) {
82
+ setTimeout(() => {
83
+ console.log(Colors.primary(` ➜ `), useFunctions().fromID(input.functionID).handler);
84
+ for (const log of input.logs) {
85
+ console.log(` ${dim(log)}`);
86
+ }
87
+ console.log(` ${Colors.danger(evt.properties.errorMessage)}`);
88
+ for (const line of evt.properties.trace || []) {
89
+ console.log(` ${dim(line)}`);
90
+ }
91
+ console.log();
92
+ }, diff > 500 ? 60 : 0);
93
+ }
94
+ setFunctions((functions) => {
95
+ const { [evt.properties.requestID]: existing, ...next } = functions;
96
+ if (!existing)
97
+ return functions;
98
+ const diff = Date.now() - existing.started;
99
+ if (diff > 500 && diff < 1500) {
100
+ setTimeout(() => {
101
+ setFunctions((functions) => {
102
+ const { [evt.properties.requestID]: existing, ...next } = functions;
103
+ print(existing, diff);
104
+ return next;
105
+ });
106
+ }, 1500 - diff);
107
+ return functions;
108
+ }
109
+ print(existing, diff);
110
+ return next;
111
+ });
112
+ });
113
+ return () => {
114
+ bus.unsubscribe(invoke);
115
+ bus.unsubscribe(success);
116
+ bus.unsubscribe(error);
117
+ bus.unsubscribe(stdout);
118
+ };
119
+ }, []);
120
+ return (React.createElement(React.Fragment, null, Object.values(functions)
121
+ .filter((f) => Date.now() - f.started >= 500)
122
+ .map((evt) => (React.createElement(React.Fragment, { key: evt.requestID },
123
+ React.createElement(Text, null,
124
+ " ",
125
+ React.createElement(Spinner, null),
126
+ " ",
127
+ useFunctions().fromID(evt.functionID).handler),
128
+ evt.logs.map((log, index) => (React.createElement(Text, { dimColor: true, key: index },
129
+ " ",
130
+ log))),
131
+ React.createElement(Text, null, " "))))));
132
+ }
@@ -0,0 +1,5 @@
1
+ export declare function printHeader(input: {
2
+ console?: boolean;
3
+ hint?: string;
4
+ }): Promise<void>;
5
+ export declare function printConsole(): void;
@@ -0,0 +1,16 @@
1
+ import { useProject } from "../../project.js";
2
+ import { Colors } from "../colors.js";
3
+ import { useLocalServerConfig } from "../local/server.js";
4
+ export async function printHeader(input) {
5
+ const project = useProject();
6
+ Colors.line(`${Colors.primary.bold(`SST v${project.version}`)} ${input.hint ? Colors.dim(`ready!`) : ""}`);
7
+ Colors.gap();
8
+ Colors.line(`${Colors.primary(`➜`)} ${Colors.bold("App:")} ${project.config.name}`);
9
+ Colors.line(`${Colors.primary(` `)} ${Colors.bold("Stage:")} ${project.config.stage}`);
10
+ if (input.console) {
11
+ const local = await useLocalServerConfig();
12
+ Colors.line(`${Colors.primary(` `)} ${Colors.bold("Console:")} ${Colors.link(local.url)}`);
13
+ }
14
+ Colors.gap();
15
+ }
16
+ export function printConsole() { }
@@ -0,0 +1 @@
1
+ export declare function stackNameToId(stack: string): string;
@@ -0,0 +1,6 @@
1
+ import { useProject } from "../../project.js";
2
+ export function stackNameToId(stack) {
3
+ const project = useProject();
4
+ const prefix = `${project.config.stage}-${project.config.name}-`;
5
+ return stack.startsWith(prefix) ? stack.substring(prefix.length) : stack;
6
+ }
package/config.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare namespace Config {
6
6
  function parameters(): Promise<({
7
7
  type: string;
8
8
  id: string;
9
- prop: string[];
9
+ prop: string;
10
10
  } & {
11
11
  value: string;
12
12
  })[]>;
package/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { DeleteParameterCommand, GetParameterCommand, GetParametersByPathCommand, PutParameterCommand, SSMClient, } from "@aws-sdk/client-ssm";
2
2
  import { GetFunctionConfigurationCommand, LambdaClient, UpdateFunctionConfigurationCommand, } from "@aws-sdk/client-lambda";
3
3
  import { pipe, map } from "remeda";
4
- import { useProject } from "./app.js";
4
+ import { useProject } from "./project.js";
5
5
  import { useAWSClient } from "./credentials.js";
6
6
  import { Stacks } from "./stacks/index.js";
7
7
  export var Config;
@@ -30,7 +30,7 @@ export var Config;
30
30
  }
31
31
  Config.parameters = parameters;
32
32
  function envFor(input) {
33
- return `SST_${input.type}_${input.prop}_${input.id}`;
33
+ return `SST_${input.type}_${input.prop}_${normalizeID(input.id)}`;
34
34
  }
35
35
  Config.envFor = envFor;
36
36
  function pathFor(input) {
@@ -62,9 +62,9 @@ export var Config;
62
62
  const project = useProject();
63
63
  const parameters = await Config.parameters();
64
64
  const env = {
65
- SST_APP: project.name,
66
- SST_STAGE: project.stage,
67
- ...pipe(parameters, map((p) => [`SST_${p.type}_${p.prop}_${p.id}`, p.value]), Object.fromEntries),
65
+ SST_APP: project.config.name,
66
+ SST_STAGE: project.config.stage,
67
+ ...pipe(parameters, map((p) => [envFor(p), p.value]), Object.fromEntries),
68
68
  };
69
69
  return env;
70
70
  }
@@ -156,11 +156,11 @@ const SECRET_UPDATED_AT_ENV = "SST_ADMIN_SECRET_UPDATED_AT";
156
156
  const PREFIX = {
157
157
  get STAGE() {
158
158
  const project = useProject();
159
- return `/sst/${project.name}/${project.stage}/`;
159
+ return `/sst/${project.config.name}/${project.config.stage}/`;
160
160
  },
161
161
  get FALLBACK() {
162
162
  const project = useProject();
163
- return `/sst/${project.name}/${FALLBACK_STAGE}/`;
163
+ return `/sst/${project.config.name}/${FALLBACK_STAGE}/`;
164
164
  },
165
165
  };
166
166
  function parse(ssmName) {
@@ -168,6 +168,6 @@ function parse(ssmName) {
168
168
  return {
169
169
  type: parts[4],
170
170
  id: parts[5],
171
- prop: parts.slice(6),
171
+ prop: parts.slice(6).join("/"),
172
172
  };
173
173
  }
@@ -14,8 +14,8 @@ import * as apigV2Cors from "./util/apiGatewayV2Cors.js";
14
14
  import * as apigV2Domain from "./util/apiGatewayV2Domain.js";
15
15
  import * as apigV2AccessLog from "./util/apiGatewayV2AccessLog.js";
16
16
  declare const PayloadFormatVersions: readonly ["1.0", "2.0"];
17
- export declare type ApiPayloadFormatVersion = typeof PayloadFormatVersions[number];
18
- export declare type ApiAuthorizer = ApiUserPoolAuthorizer | ApiJwtAuthorizer | ApiLambdaAuthorizer;
17
+ export type ApiPayloadFormatVersion = (typeof PayloadFormatVersions)[number];
18
+ export type ApiAuthorizer = ApiUserPoolAuthorizer | ApiJwtAuthorizer | ApiLambdaAuthorizer;
19
19
  interface ApiBaseAuthorizer {
20
20
  /**
21
21
  * The name of the authorizer.
@@ -393,7 +393,7 @@ export interface ApiProps<Authorizers extends Record<string, ApiAuthorizer> = Re
393
393
  httpStages?: Omit<apig.HttpStageProps, "httpApi">[];
394
394
  };
395
395
  }
396
- export declare type ApiRouteProps<AuthorizerKeys> = FunctionInlineDefinition | ApiFunctionRouteProps<AuthorizerKeys> | ApiHttpRouteProps<AuthorizerKeys> | ApiAlbRouteProps<AuthorizerKeys> | ApiGraphQLRouteProps<AuthorizerKeys> | ApiPothosRouteProps<AuthorizerKeys>;
396
+ export type ApiRouteProps<AuthorizerKeys> = FunctionInlineDefinition | ApiFunctionRouteProps<AuthorizerKeys> | ApiHttpRouteProps<AuthorizerKeys> | ApiAlbRouteProps<AuthorizerKeys> | ApiGraphQLRouteProps<AuthorizerKeys>;
397
397
  interface ApiBaseRouteProps<AuthorizerKeys = string> {
398
398
  authorizer?: "none" | "iam" | (string extends AuthorizerKeys ? Omit<AuthorizerKeys, "none" | "iam"> : AuthorizerKeys);
399
399
  authorizationScopes?: string[];
@@ -485,63 +485,6 @@ export interface ApiAlbRouteProps<AuthorizersKeys> extends ApiBaseRouteProps<Aut
485
485
  integration?: apigIntegrations.HttpAlbIntegrationProps;
486
486
  };
487
487
  }
488
- /**
489
- * Specify a route handler that handles GraphQL queries using Pothos
490
- * @deprecated "pothos" routes are deprecated for the Api construct, and will be removed in SST v2. Use "graphql" routes instead. Read more about how to upgrade here — https://docs.sst.dev/upgrade-guide#upgrade-to-v118
491
- * @example
492
- * ```js
493
- * // Change
494
- * api.addRoutes(stack, {
495
- * "POST /graphql": {
496
- * type: "pothos",
497
- * function: {
498
- * handler: "functions/graphql/graphql.ts",
499
- * },
500
- * schema: "backend/functions/graphql/schema.ts",
501
- * output: "graphql/schema.graphql",
502
- * commands: [
503
- * "./genql graphql/graphql.schema graphql/
504
- * ]
505
- * }
506
- * })
507
- *
508
- * // To
509
- * api.addRoutes(stack, {
510
- * "POST /graphql": {
511
- * type: "graphql",
512
- * function: {
513
- * handler: "functions/graphql/graphql.ts",
514
- * },
515
- * pothos: {
516
- * schema: "backend/functions/graphql/schema.ts",
517
- * output: "graphql/schema.graphql",
518
- * commands: [
519
- * "./genql graphql/graphql.schema graphql/
520
- * ]
521
- * }
522
- * }
523
- * })
524
- * ```
525
- */
526
- export interface ApiPothosRouteProps<AuthorizerKeys> extends ApiBaseRouteProps<AuthorizerKeys> {
527
- type: "pothos";
528
- /**
529
- * The function definition used to create the function for this route. Must be a graphql handler
530
- */
531
- function: FunctionDefinition;
532
- /**
533
- * Path to pothos schema
534
- */
535
- schema?: string;
536
- /**
537
- * File to write graphql schema to
538
- */
539
- output?: string;
540
- /**
541
- * Commands to run after generating schema. Useful for code generation steps
542
- */
543
- commands?: string[];
544
- }
545
488
  /**
546
489
  * Specify a route handler that handles GraphQL queries using Pothos
547
490
  *
@@ -752,16 +695,6 @@ export declare class Api<Authorizers extends Record<string, ApiAuthorizer> = Rec
752
695
  schema?: undefined;
753
696
  output?: undefined;
754
697
  commands?: undefined;
755
- } | {
756
- type: "pothos";
757
- route: string;
758
- fn: {
759
- node: string;
760
- stack: string;
761
- } | undefined;
762
- schema: string | undefined;
763
- output: string | undefined;
764
- commands: string[] | undefined;
765
698
  } | {
766
699
  type: "graphql";
767
700
  route: string;
@@ -798,7 +731,6 @@ export declare class Api<Authorizers extends Record<string, ApiAuthorizer> = Rec
798
731
  private addRoute;
799
732
  private createHttpIntegration;
800
733
  private createAlbIntegration;
801
- protected createPothosIntegration(scope: Construct, routeKey: string, routeProps: ApiPothosRouteProps<keyof Authorizers>, postfixName: string): apig.HttpRouteIntegration;
802
734
  protected createGraphQLIntegration(scope: Construct, routeKey: string, routeProps: ApiGraphQLRouteProps<keyof Authorizers>, postfixName: string): apig.HttpRouteIntegration;
803
735
  protected createCdkFunctionIntegration(scope: Construct, routeKey: string, routeProps: ApiFunctionRouteProps<keyof Authorizers>, postfixName: string): apig.HttpRouteIntegration;
804
736
  protected createFunctionIntegration(scope: Construct, routeKey: string, routeProps: ApiFunctionRouteProps<keyof Authorizers>, postfixName: string): apig.HttpRouteIntegration;