sst 2.1.16 → 2.1.18

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 (53) hide show
  1. package/bootstrap.js +1 -1
  2. package/cli/commands/bind.js +1 -1
  3. package/cli/commands/env.js +1 -1
  4. package/constructs/App.js +3 -3
  5. package/constructs/AstroSite.js +8 -41
  6. package/constructs/EdgeFunction.d.ts +19 -21
  7. package/constructs/EdgeFunction.js +235 -167
  8. package/constructs/Function.d.ts +1 -1
  9. package/constructs/Function.js +3 -3
  10. package/constructs/Job.js +2 -2
  11. package/constructs/NextjsSite.d.ts +6 -5
  12. package/constructs/NextjsSite.js +5 -3
  13. package/constructs/RDS.js +1 -1
  14. package/constructs/RemixSite.d.ts +2 -3
  15. package/constructs/RemixSite.js +42 -71
  16. package/constructs/SolidStartSite.js +8 -41
  17. package/constructs/SsrFunction.d.ts +9 -6
  18. package/constructs/SsrFunction.js +61 -50
  19. package/constructs/SsrSite.d.ts +6 -4
  20. package/constructs/SsrSite.js +0 -4
  21. package/constructs/Stack.js +2 -1
  22. package/constructs/future/Auth.d.ts +79 -0
  23. package/constructs/future/Auth.js +116 -0
  24. package/constructs/future/index.d.ts +1 -0
  25. package/constructs/future/index.js +1 -0
  26. package/context/handler.d.ts +1 -1
  27. package/node/api/index.d.ts +27 -4
  28. package/node/api/index.js +64 -2
  29. package/node/auth/index.d.ts +3 -0
  30. package/node/auth/index.js +3 -0
  31. package/node/future/auth/adapter/adapter.d.ts +10 -0
  32. package/node/future/auth/adapter/adapter.js +1 -0
  33. package/node/future/auth/adapter/github.d.ts +16 -0
  34. package/node/future/auth/adapter/github.js +22 -0
  35. package/node/future/auth/adapter/google.d.ts +20 -0
  36. package/node/future/auth/adapter/google.js +10 -0
  37. package/node/future/auth/adapter/link.d.ts +11 -0
  38. package/node/future/auth/adapter/link.js +48 -0
  39. package/node/future/auth/adapter/oauth.d.ts +34 -0
  40. package/node/future/auth/adapter/oauth.js +66 -0
  41. package/node/future/auth/adapter/oidc.d.ts +26 -0
  42. package/node/future/auth/adapter/oidc.js +62 -0
  43. package/node/future/auth/handler.d.ts +18 -0
  44. package/node/future/auth/handler.js +189 -0
  45. package/node/future/auth/index.d.ts +10 -0
  46. package/node/future/auth/index.js +10 -0
  47. package/node/future/auth/session.d.ts +46 -0
  48. package/node/future/auth/session.js +99 -0
  49. package/node/util/index.js +1 -1
  50. package/package.json +4 -1
  51. package/runtime/handlers/node.js +1 -1
  52. package/sst.mjs +4 -4
  53. package/support/nodejs-runtime/index.mjs +62 -14629
@@ -0,0 +1,189 @@
1
+ import { createSigner, createVerifier } from "fast-jwt";
2
+ import { ApiHandler, useCookie, useCookies, useFormValue, usePathParam, useQueryParam, useQueryParams, useResponse, } from "../../api/index.js";
3
+ import { Config } from "../../config/index.js";
4
+ export function AuthHandler(input) {
5
+ return ApiHandler(async (evt) => {
6
+ const step = usePathParam("step");
7
+ if (!step) {
8
+ return {
9
+ statusCode: 200,
10
+ headers: {
11
+ "Content-Type": "text/html",
12
+ },
13
+ body: `
14
+ <html>
15
+ <body>
16
+ ${Object.keys(input.providers).map((name) => {
17
+ return `<a href="/authorize?provider=${name}&response_type=code&client_id=local&redirect_uri=http://localhost:300">${name}</a>`;
18
+ })}
19
+ </body>
20
+ </html>
21
+ `,
22
+ };
23
+ }
24
+ if (step === "token") {
25
+ if (useFormValue("grant_type") !== "authorization_code") {
26
+ return {
27
+ statusCode: 400,
28
+ body: "Invalid grant_type",
29
+ };
30
+ }
31
+ const code = useFormValue("code");
32
+ if (!code) {
33
+ return {
34
+ statusCode: 400,
35
+ body: "Missing code",
36
+ };
37
+ }
38
+ // @ts-expect-error
39
+ const pub = Config[process.env.AUTH_ID + "PublicKey"];
40
+ const verified = createVerifier({
41
+ algorithms: ["RS512"],
42
+ key: pub,
43
+ })(code);
44
+ if (verified.redirect_uri !== useFormValue("redirect_uri")) {
45
+ return {
46
+ statusCode: 400,
47
+ body: "redirect_uri mismatch",
48
+ };
49
+ }
50
+ if (verified.client_id !== useFormValue("client_id")) {
51
+ return {
52
+ statusCode: 400,
53
+ body: "client_id mismatch",
54
+ };
55
+ }
56
+ return {
57
+ statusCode: 200,
58
+ headers: {
59
+ "content-type": "application/json",
60
+ },
61
+ body: JSON.stringify({
62
+ access_token: verified.token,
63
+ }),
64
+ };
65
+ }
66
+ let provider = useCookie("provider");
67
+ if (step === "authorize") {
68
+ provider = useQueryParam("provider");
69
+ if (input.onAuthorize) {
70
+ const result = await input.onAuthorize(evt);
71
+ if (result)
72
+ provider = result;
73
+ }
74
+ if (!provider) {
75
+ return {
76
+ statusCode: 400,
77
+ body: "Missing provider",
78
+ };
79
+ }
80
+ const { response_type, client_id, redirect_uri, state } = useQueryParams();
81
+ if (!provider) {
82
+ return {
83
+ statusCode: 400,
84
+ body: "Missing provider",
85
+ };
86
+ }
87
+ if (!response_type) {
88
+ return {
89
+ statusCode: 400,
90
+ body: "Missing response_type",
91
+ };
92
+ }
93
+ if (!client_id) {
94
+ return {
95
+ statusCode: 400,
96
+ body: "Missing client_id",
97
+ };
98
+ }
99
+ if (!redirect_uri) {
100
+ return {
101
+ statusCode: 400,
102
+ body: "Missing redirect_uri",
103
+ };
104
+ }
105
+ useResponse().cookies({
106
+ provider: provider,
107
+ response_type: response_type,
108
+ client_id: client_id,
109
+ redirect_uri: redirect_uri,
110
+ state: state || "",
111
+ }, {
112
+ maxAge: 60 * 15,
113
+ secure: true,
114
+ sameSite: "None",
115
+ httpOnly: true,
116
+ });
117
+ }
118
+ if (!provider || !input.providers[provider]) {
119
+ return {
120
+ statusCode: 400,
121
+ body: `Was not able to find provider "${String(provider)}"`,
122
+ headers: {
123
+ "Content-Type": "text/html",
124
+ },
125
+ };
126
+ }
127
+ const adapter = input.providers[provider];
128
+ const result = await adapter(evt);
129
+ if (result.type === "step") {
130
+ return result.properties;
131
+ }
132
+ if (result.type === "success") {
133
+ const { type, properties, ...rest } = await input.onSuccess({
134
+ provider,
135
+ ...result.properties,
136
+ });
137
+ // @ts-expect-error
138
+ const priv = Config[process.env.AUTH_ID + "PrivateKey"];
139
+ const signer = createSigner({
140
+ ...rest,
141
+ key: priv,
142
+ algorithm: "RS512",
143
+ });
144
+ const token = signer({
145
+ type,
146
+ properties,
147
+ });
148
+ const { client_id, response_type, redirect_uri, state } = {
149
+ ...useCookies(),
150
+ ...useQueryParams(),
151
+ };
152
+ if (response_type === "token") {
153
+ return {
154
+ statusCode: 302,
155
+ headers: {
156
+ Location: `${redirect_uri}#access_token=${token}&state=${state || ""}`,
157
+ },
158
+ };
159
+ }
160
+ if (response_type === "code") {
161
+ // This allows the code to be reused within a 30 second window
162
+ // The code should be single use but we're making this tradeoff to remain stateless
163
+ // In the future can store this in a dynamo table to ensure single use
164
+ const code = createSigner({
165
+ expiresIn: 1000 * 60 * 5,
166
+ key: priv,
167
+ algorithm: "RS512",
168
+ })({
169
+ client_id,
170
+ redirect_uri,
171
+ token: token,
172
+ });
173
+ return {
174
+ statusCode: 302,
175
+ headers: {
176
+ Location: `${redirect_uri}?code=${code}&state=${state || ""}`,
177
+ },
178
+ };
179
+ }
180
+ return {
181
+ statusCode: 400,
182
+ body: `Unsupported response_type: ${response_type}`,
183
+ };
184
+ }
185
+ if (result.type === "error") {
186
+ return input.onError();
187
+ }
188
+ });
189
+ }
@@ -0,0 +1,10 @@
1
+ export interface AuthResources {
2
+ }
3
+ export declare const Auth: AuthResources;
4
+ export * from "./adapter/oidc.js";
5
+ export * from "./adapter/google.js";
6
+ export * from "./adapter/link.js";
7
+ export * from "./adapter/github.js";
8
+ export * from "./adapter/oauth.js";
9
+ export * from "./session.js";
10
+ export * from "./handler.js";
@@ -0,0 +1,10 @@
1
+ import { createProxy, getVariables } from "../../util/index.js";
2
+ export const Auth = createProxy("Auth");
3
+ Object.assign(Auth, getVariables("Auth"));
4
+ export * from "./adapter/oidc.js";
5
+ export * from "./adapter/google.js";
6
+ export * from "./adapter/link.js";
7
+ export * from "./adapter/github.js";
8
+ export * from "./adapter/oauth.js";
9
+ export * from "./session.js";
10
+ export * from "./handler.js";
@@ -0,0 +1,46 @@
1
+ import { SignerOptions } from "fast-jwt";
2
+ export interface SessionTypes {
3
+ public: {};
4
+ }
5
+ export type SessionValue = {
6
+ [type in keyof SessionTypes]: {
7
+ type: type;
8
+ properties: SessionTypes[type];
9
+ };
10
+ }[keyof SessionTypes];
11
+ export declare function useSession<T = SessionValue>(): T;
12
+ /**
13
+ * Creates a new session token with provided information
14
+ *
15
+ * @example
16
+ * ```js
17
+ * Session.create({
18
+ * type: "user",
19
+ * properties: {
20
+ * userID: "123"
21
+ * }
22
+ * })
23
+ * ```
24
+ */
25
+ declare function create<T extends keyof SessionTypes>(input: {
26
+ type: T;
27
+ properties: SessionTypes[T];
28
+ options?: Partial<SignerOptions>;
29
+ }): string;
30
+ /**
31
+ * Verifies a session token and returns the session data
32
+ *
33
+ * @example
34
+ * ```js
35
+ * Session.verify()
36
+ * ```
37
+ */
38
+ declare function verify<T = SessionValue>(token: string): T | {
39
+ type: string;
40
+ properties: {};
41
+ };
42
+ export declare const Session: {
43
+ create: typeof create;
44
+ verify: typeof verify;
45
+ };
46
+ export {};
@@ -0,0 +1,99 @@
1
+ import { createSigner, createVerifier } from "fast-jwt";
2
+ import { Context } from "../../../context/context.js";
3
+ import { useCookie, useHeader } from "../../api/index.js";
4
+ import { Auth } from "../../auth/index.js";
5
+ import { Config } from "../../config/index.js";
6
+ const SessionMemo = /* @__PURE__ */ Context.memo(() => {
7
+ let token = "";
8
+ const header = useHeader("authorization");
9
+ if (header)
10
+ token = header.substring(7);
11
+ const cookie = useCookie("sst_auth_token");
12
+ if (cookie)
13
+ token = cookie;
14
+ if (token) {
15
+ try {
16
+ const jwt = createVerifier({
17
+ algorithms: ["RS512"],
18
+ key: getPublicKey(),
19
+ })(token);
20
+ return jwt;
21
+ }
22
+ catch {
23
+ return {
24
+ type: "public",
25
+ properties: {},
26
+ };
27
+ }
28
+ }
29
+ return {
30
+ type: "public",
31
+ properties: {},
32
+ };
33
+ });
34
+ // This is a crazy TS hack to prevent the types from being evaluated too soon
35
+ export function useSession() {
36
+ const ctx = SessionMemo();
37
+ return ctx;
38
+ }
39
+ function getPublicKey() {
40
+ const [first] = Object.values(Auth);
41
+ if (!first)
42
+ throw new Error("No auth provider found. Did you forget to add one?");
43
+ return first.publicKey;
44
+ }
45
+ /**
46
+ * Creates a new session token with provided information
47
+ *
48
+ * @example
49
+ * ```js
50
+ * Session.create({
51
+ * type: "user",
52
+ * properties: {
53
+ * userID: "123"
54
+ * }
55
+ * })
56
+ * ```
57
+ */
58
+ function create(input) {
59
+ // @ts-expect-error
60
+ const key = Config[process.env.AUTH_ID + "PrivateKey"];
61
+ const signer = createSigner({
62
+ ...input.options,
63
+ key,
64
+ algorithm: "RS512",
65
+ });
66
+ const token = signer({
67
+ type: input.type,
68
+ properties: input.properties,
69
+ });
70
+ return token;
71
+ }
72
+ /**
73
+ * Verifies a session token and returns the session data
74
+ *
75
+ * @example
76
+ * ```js
77
+ * Session.verify()
78
+ * ```
79
+ */
80
+ function verify(token) {
81
+ if (token) {
82
+ try {
83
+ const jwt = createVerifier({
84
+ algorithms: ["RS512"],
85
+ key: getPublicKey(),
86
+ })(token);
87
+ return jwt;
88
+ }
89
+ catch { }
90
+ }
91
+ return {
92
+ type: "public",
93
+ properties: {},
94
+ };
95
+ }
96
+ export const Session = {
97
+ create,
98
+ verify,
99
+ };
@@ -1,5 +1,5 @@
1
1
  import { GetParametersCommand, SSMClient, } from "@aws-sdk/client-ssm";
2
- const ssm = new SSMClient({});
2
+ const ssm = new SSMClient({ region: process.env.SST_REGION });
3
3
  // Example:
4
4
  // {
5
5
  // Bucket: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.1.16",
3
+ "version": "2.1.18",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
@@ -14,8 +14,10 @@
14
14
  },
15
15
  "exports": {
16
16
  "./constructs/deprecated": "./constructs/deprecated/index.js",
17
+ "./constructs/future": "./constructs/future/index.js",
17
18
  "./constructs": "./constructs/index.js",
18
19
  "./context": "./context/index.js",
20
+ "./node/future/*": "./node/future/*/index.js",
19
21
  "./node/*": "./node/*/index.js",
20
22
  ".": "./index.js",
21
23
  "./*": "./*"
@@ -113,6 +115,7 @@
113
115
  "@types/ws": "^8.5.3",
114
116
  "@types/yargs": "^17.0.13",
115
117
  "tsx": "^3.12.1",
118
+ "typescript": "^4.9.5",
116
119
  "vitest": "^0.28.3"
117
120
  },
118
121
  "peerDependencies": {
@@ -116,7 +116,7 @@ export const useNodeHandler = Context.memo(async () => {
116
116
  ? {
117
117
  format: "esm",
118
118
  target: "esnext",
119
- mainFields: isESM ? ["module", "main"] : undefined,
119
+ mainFields: ["module", "main"],
120
120
  banner: {
121
121
  js: [
122
122
  `import { createRequire as topLevelCreateRequire } from 'module';`,
package/sst.mjs CHANGED
@@ -2919,7 +2919,7 @@ async function bootstrapCDK() {
2919
2919
  AWS_PROFILE: profile
2920
2920
  },
2921
2921
  stdio: "pipe",
2922
- shell: process.env.SHELL || true
2922
+ shell: true
2923
2923
  }
2924
2924
  );
2925
2925
  let stderr = "";
@@ -4990,7 +4990,7 @@ var init_node = __esm({
4990
4990
  ...isESM ? {
4991
4991
  format: "esm",
4992
4992
  target: "esnext",
4993
- mainFields: isESM ? ["module", "main"] : void 0,
4993
+ mainFields: ["module", "main"],
4994
4994
  banner: {
4995
4995
  js: [
4996
4996
  `import { createRequire as topLevelCreateRequire } from 'module';`,
@@ -6720,7 +6720,7 @@ var env = (program2) => program2.command(
6720
6720
  AWS_REGION: project.config.region
6721
6721
  },
6722
6722
  stdio: "inherit",
6723
- shell: process.env.SHELL || true
6723
+ shell: true
6724
6724
  });
6725
6725
  process.exitCode = result.status || void 0;
6726
6726
  break;
@@ -7061,7 +7061,7 @@ var bind = (program2) => program2.command(
7061
7061
  AWS_REGION: project.config.region
7062
7062
  },
7063
7063
  stdio: "inherit",
7064
- shell: process.env.SHELL || true
7064
+ shell: true
7065
7065
  });
7066
7066
  process.exitCode = result.status || void 0;
7067
7067
  }