sst 2.11.17 → 2.12.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.
package/bootstrap.js CHANGED
@@ -127,6 +127,11 @@ export async function bootstrapSST() {
127
127
  synthesizer: new DefaultStackSynthesizer({
128
128
  qualifier: cdk?.qualifier,
129
129
  fileAssetsBucketName: cdk?.fileAssetsBucketName,
130
+ deployRoleArn: cdk?.deployRoleArn,
131
+ fileAssetPublishingRoleArn: cdk?.fileAssetPublishingRoleArn,
132
+ imageAssetPublishingRoleArn: cdk?.imageAssetPublishingRoleArn,
133
+ cloudFormationExecutionRole: cdk?.cloudFormationExecutionRole,
134
+ lookupRoleArn: cdk?.lookupRoleArn,
130
135
  }),
131
136
  });
132
137
  // Add tags to stack
@@ -210,6 +210,11 @@ export class Stack extends CDKStack {
210
210
  return new DefaultStackSynthesizer({
211
211
  qualifier: config.cdk?.qualifier,
212
212
  fileAssetsBucketName: config.cdk?.fileAssetsBucketName,
213
+ deployRoleArn: config.cdk?.deployRoleArn,
214
+ fileAssetPublishingRoleArn: config.cdk?.fileAssetPublishingRoleArn,
215
+ imageAssetPublishingRoleArn: config.cdk?.imageAssetPublishingRoleArn,
216
+ cloudFormationExecutionRole: config.cdk?.cloudFormationExecutionRole,
217
+ lookupRoleArn: config.cdk?.lookupRoleArn,
213
218
  });
214
219
  }
215
220
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1,11 +1,13 @@
1
1
  import { APIGatewayProxyStructuredResultV2 } from "aws-lambda";
2
2
  export declare function LinkAdapter(config: {
3
3
  onLink: (link: string, claims: Record<string, any>) => Promise<APIGatewayProxyStructuredResultV2>;
4
- onError: (error: any) => Promise<APIGatewayProxyStructuredResultV2>;
5
4
  }): () => Promise<{
6
5
  type: "step";
7
6
  properties: APIGatewayProxyStructuredResultV2;
8
7
  } | {
9
8
  type: "success";
10
9
  properties: any;
10
+ } | {
11
+ type: "error";
12
+ properties?: undefined;
11
13
  }>;
@@ -2,16 +2,16 @@ import { createSigner, createVerifier } from "fast-jwt";
2
2
  import { Config } from "../../../config/index.js";
3
3
  import { useDomainName, usePathParam, useQueryParam, useQueryParams, } from "../../../api/index.js";
4
4
  export function LinkAdapter(config) {
5
- // @ts-expect-error
6
- const key = Config[process.env.AUTH_ID + "PrivateKey"];
7
- // @ts-expect-error
8
- const publicKey = Config[process.env.AUTH_ID + "PublicKey"];
9
- const signer = createSigner({
10
- expiresIn: 1000 * 60 * 10,
11
- key,
12
- algorithm: "RS512",
13
- });
14
5
  return async function () {
6
+ // @ts-expect-error
7
+ const key = Config[process.env.AUTH_ID + "PrivateKey"];
8
+ // @ts-expect-error
9
+ const publicKey = Config[process.env.AUTH_ID + "PublicKey"];
10
+ const signer = createSigner({
11
+ expiresIn: 1000 * 60 * 10,
12
+ key,
13
+ algorithm: "RS512",
14
+ });
15
15
  const callback = "https://" + useDomainName() + "/callback";
16
16
  const step = usePathParam("step");
17
17
  if (step === "authorize") {
@@ -38,13 +38,10 @@ export function LinkAdapter(config) {
38
38
  properties: jwt,
39
39
  };
40
40
  }
41
- catch (ex) {
42
- return {
43
- type: "step",
44
- properties: await config.onError(ex),
45
- };
46
- }
41
+ catch (ex) { }
47
42
  }
48
- throw new Error("Invalid auth request");
43
+ return {
44
+ type: "error",
45
+ };
49
46
  };
50
47
  }
@@ -2,6 +2,25 @@ import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from "aws-l
2
2
  import { Adapter } from "./adapter/adapter.js";
3
3
  import { SignerOptions } from "fast-jwt";
4
4
  import { SessionValue } from "./session.js";
5
+ declare const onSuccessResponse: {
6
+ session(input: SessionCreateInput): {
7
+ type: "session";
8
+ properties: SessionCreateInput;
9
+ };
10
+ http(input: APIGatewayProxyStructuredResultV2): {
11
+ type: "http";
12
+ properties: APIGatewayProxyStructuredResultV2;
13
+ };
14
+ provider(provider: string): {
15
+ type: "http";
16
+ properties: {
17
+ statusCode: number;
18
+ headers: {
19
+ Location: string;
20
+ };
21
+ };
22
+ };
23
+ };
5
24
  export declare function AuthHandler<Providers extends Record<string, Adapter<any>>, Result = {
6
25
  [key in keyof Providers]: {
7
26
  provider: key;
@@ -12,7 +31,8 @@ export declare function AuthHandler<Providers extends Record<string, Adapter<any
12
31
  providers: Providers;
13
32
  clients: () => Promise<Record<string, string>>;
14
33
  onAuthorize?: (event: APIGatewayProxyEventV2) => Promise<void | keyof Providers>;
15
- onSuccess: (input: Result) => Promise<SessionCreateInput>;
34
+ onSuccess: (input: Result, response: typeof onSuccessResponse) => Promise<ReturnType<(typeof onSuccessResponse)[keyof typeof onSuccessResponse]>>;
16
35
  onError: () => Promise<APIGatewayProxyStructuredResultV2>;
17
36
  }): (event: APIGatewayProxyEventV2, context: import("aws-lambda").Context) => Promise<APIGatewayProxyStructuredResultV2>;
18
37
  export type SessionCreateInput = SessionValue & Partial<SignerOptions>;
38
+ export {};
@@ -1,6 +1,37 @@
1
1
  import { createSigner, createVerifier } from "fast-jwt";
2
2
  import { ApiHandler, useCookie, useCookies, useFormValue, usePathParam, useQueryParam, useQueryParams, useResponse, } from "../../api/index.js";
3
3
  import { Config } from "../../config/index.js";
4
+ const onSuccessResponse = {
5
+ session(input) {
6
+ return {
7
+ type: "session",
8
+ properties: input,
9
+ };
10
+ },
11
+ http(input) {
12
+ return {
13
+ type: "http",
14
+ properties: input,
15
+ };
16
+ },
17
+ provider(provider) {
18
+ return {
19
+ type: "http",
20
+ properties: {
21
+ statusCode: 302,
22
+ headers: {
23
+ Location: "/authorize?" +
24
+ new URLSearchParams({
25
+ provider,
26
+ response_type: useCookie("response_type"),
27
+ client_id: useCookie("client_id"),
28
+ redirect_uri: useCookie("redirect_uri"),
29
+ }).toString(),
30
+ },
31
+ },
32
+ };
33
+ },
34
+ };
4
35
  export function AuthHandler(input) {
5
36
  return ApiHandler(async (evt) => {
6
37
  const step = usePathParam("step");
@@ -13,6 +44,9 @@ export function AuthHandler(input) {
13
44
  },
14
45
  body: `
15
46
  <html>
47
+ <head>
48
+ <link rel="icon" href="data:,">
49
+ </head>
16
50
  <body>
17
51
  <table>
18
52
  <tr>${Object.keys(clients).map((client) => `<td>${client}</td>`)}</tr>
@@ -30,6 +64,11 @@ export function AuthHandler(input) {
30
64
  `,
31
65
  };
32
66
  }
67
+ if (step === "favicon.ico") {
68
+ return {
69
+ statusCode: 404,
70
+ };
71
+ }
33
72
  if (step === "token") {
34
73
  if (useFormValue("grant_type") !== "authorization_code") {
35
74
  return {
@@ -139,70 +178,77 @@ export function AuthHandler(input) {
139
178
  return result.properties;
140
179
  }
141
180
  if (result.type === "success") {
142
- const { type, properties, ...rest } = await input.onSuccess({
181
+ const onSuccess = await input.onSuccess({
143
182
  provider,
144
183
  ...result.properties,
145
- });
146
- // @ts-expect-error
147
- const priv = Config[process.env.AUTH_ID + "PrivateKey"];
148
- const signer = createSigner({
149
- ...rest,
150
- key: priv,
151
- algorithm: "RS512",
152
- });
153
- const token = signer({
154
- type,
155
- properties,
156
- });
157
- useResponse().cookie({
158
- key: "sst_auth_token",
159
- value: token,
160
- maxAge: 10 * 365 * 24 * 60 * 60,
161
- secure: true,
162
- sameSite: "None",
163
- httpOnly: true,
164
- });
165
- const { client_id, response_type, redirect_uri, state } = {
166
- ...useCookies(),
167
- ...useQueryParams(),
168
- };
169
- if (response_type === "token") {
170
- const location = new URL(redirect_uri);
171
- location.hash = `access_token=${token}&state=${state || ""}`;
172
- return {
173
- statusCode: 302,
174
- headers: {
175
- Location: location.href,
176
- },
177
- };
178
- }
179
- if (response_type === "code") {
180
- // This allows the code to be reused within a 30 second window
181
- // The code should be single use but we're making this tradeoff to remain stateless
182
- // In the future can store this in a dynamo table to ensure single use
183
- const code = createSigner({
184
- expiresIn: 1000 * 60 * 5,
184
+ }, onSuccessResponse);
185
+ console.log("onSuccess", onSuccess);
186
+ if (onSuccess.type === "session") {
187
+ const { type, properties, ...rest } = onSuccess.properties;
188
+ // @ts-expect-error
189
+ const priv = Config[process.env.AUTH_ID + "PrivateKey"];
190
+ const signer = createSigner({
191
+ ...rest,
185
192
  key: priv,
186
193
  algorithm: "RS512",
187
- })({
188
- client_id,
189
- redirect_uri,
190
- token: token,
191
194
  });
192
- const location = new URL(redirect_uri);
193
- location.searchParams.set("code", code);
194
- location.searchParams.set("state", state || "");
195
+ const token = signer({
196
+ type,
197
+ properties,
198
+ });
199
+ useResponse().cookie({
200
+ key: "sst_auth_token",
201
+ value: token,
202
+ maxAge: 10 * 365 * 24 * 60 * 60,
203
+ secure: true,
204
+ sameSite: "None",
205
+ httpOnly: true,
206
+ });
207
+ const { client_id, response_type, redirect_uri, state } = {
208
+ ...useCookies(),
209
+ ...useQueryParams(),
210
+ };
211
+ if (response_type === "token") {
212
+ const location = new URL(redirect_uri);
213
+ location.hash = `access_token=${token}&state=${state || ""}`;
214
+ return {
215
+ statusCode: 302,
216
+ headers: {
217
+ Location: location.href,
218
+ },
219
+ };
220
+ }
221
+ if (response_type === "code") {
222
+ // This allows the code to be reused within a 30 second window
223
+ // The code should be single use but we're making this tradeoff to remain stateless
224
+ // In the future can store this in a dynamo table to ensure single use
225
+ const code = createSigner({
226
+ expiresIn: 1000 * 60 * 5,
227
+ key: priv,
228
+ algorithm: "RS512",
229
+ })({
230
+ client_id,
231
+ redirect_uri,
232
+ token: token,
233
+ });
234
+ const location = new URL(redirect_uri);
235
+ location.searchParams.set("code", code);
236
+ location.searchParams.set("state", state || "");
237
+ return {
238
+ statusCode: 302,
239
+ headers: {
240
+ Location: location.href,
241
+ },
242
+ };
243
+ }
195
244
  return {
196
- statusCode: 302,
197
- headers: {
198
- Location: location.href,
199
- },
245
+ statusCode: 400,
246
+ body: `Unsupported response_type: ${response_type}`,
200
247
  };
201
248
  }
202
- return {
203
- statusCode: 400,
204
- body: `Unsupported response_type: ${response_type}`,
205
- };
249
+ if (onSuccess.type === "http") {
250
+ return onSuccess.properties;
251
+ }
206
252
  }
207
253
  if (result.type === "error") {
208
254
  return input.onError();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.11.17",
4
+ "version": "2.12.0",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },
package/project.d.ts CHANGED
@@ -24,6 +24,11 @@ export interface ConfigOptions {
24
24
  fileAssetsBucketName?: string;
25
25
  customPermissionsBoundary?: string;
26
26
  publicAccessBlockConfiguration?: boolean;
27
+ deployRoleArn?: string;
28
+ fileAssetPublishingRoleArn?: string;
29
+ imageAssetPublishingRoleArn?: string;
30
+ cloudFormationExecutionRole?: string;
31
+ lookupRoleArn?: string;
27
32
  };
28
33
  }
29
34
  declare const DEFAULTS: {
package/sst.mjs CHANGED
@@ -284,6 +284,7 @@ async function load(input, shallow) {
284
284
  let contents = await fs3.readFile(args.path).then((x) => x.toString());
285
285
  const ast = babel.parse(contents, {
286
286
  sourceType: "module",
287
+ filename: "sst.config.ts",
287
288
  plugins: [ts]
288
289
  });
289
290
  babel.traverse(ast, {
@@ -5310,7 +5311,12 @@ async function bootstrapSST() {
5310
5311
  },
5311
5312
  synthesizer: new DefaultStackSynthesizer({
5312
5313
  qualifier: cdk?.qualifier,
5313
- fileAssetsBucketName: cdk?.fileAssetsBucketName
5314
+ fileAssetsBucketName: cdk?.fileAssetsBucketName,
5315
+ deployRoleArn: cdk?.deployRoleArn,
5316
+ fileAssetPublishingRoleArn: cdk?.fileAssetPublishingRoleArn,
5317
+ imageAssetPublishingRoleArn: cdk?.imageAssetPublishingRoleArn,
5318
+ cloudFormationExecutionRole: cdk?.cloudFormationExecutionRole,
5319
+ lookupRoleArn: cdk?.lookupRoleArn
5314
5320
  })
5315
5321
  });
5316
5322
  for (const [key, value] of Object.entries(bootstrap2?.tags || {})) {
package/stacks/build.js CHANGED
@@ -51,6 +51,7 @@ export async function load(input, shallow) {
51
51
  .then((x) => x.toString());
52
52
  const ast = babel.parse(contents, {
53
53
  sourceType: "module",
54
+ filename: "sst.config.ts",
54
55
  plugins: [ts],
55
56
  });
56
57
  babel.traverse(ast, {