sst 2.1.26 → 2.1.28

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.
@@ -5,18 +5,15 @@ import * as fs from "fs/promises";
5
5
  import { DatabaseMetadata, EnumCollection, PostgresDialect, MysqlDialect, Serializer, Transformer, } from "kysely-codegen";
6
6
  import { Context } from "../../../context/context.js";
7
7
  import { useBus } from "../../../bus.js";
8
- import { useProject } from "../../../project.js";
9
8
  import { Logger } from "../../../logger.js";
10
- import { useAWSClient, useAWSCredentials, } from "../../../credentials.js";
9
+ import { useAWSClient, } from "../../../credentials.js";
11
10
  export const useKyselyTypeGenerator = Context.memo(async () => {
12
11
  let databases = [];
13
12
  const bus = useBus();
14
- const project = useProject();
15
13
  async function generate(db) {
16
14
  if (!db.types)
17
15
  return;
18
16
  Logger.debug("Generating types for", db.migratorID);
19
- const credentials = await useAWSCredentials();
20
17
  const k = new Kysely({
21
18
  dialect: new DataApiDialect({
22
19
  mode: db.engine.includes("postgres") ? "postgres" : "mysql",
@@ -93,7 +90,7 @@ export const useKyselyTypeGenerator = Context.memo(async () => {
93
90
  const db = databases.find((db) => db.migratorID === evt.properties.functionID);
94
91
  if (!db)
95
92
  return;
96
- generate(db);
93
+ generate(db).catch(() => { });
97
94
  });
98
95
  Logger.debug("Loaded kyseley type generator");
99
96
  });
@@ -2,10 +2,11 @@ import { Construct } from "constructs";
2
2
  import * as acm from "aws-cdk-lib/aws-certificatemanager";
3
3
  import * as apig from "@aws-cdk/aws-apigatewayv2-alpha";
4
4
  import * as apigAuthorizers from "@aws-cdk/aws-apigatewayv2-authorizers-alpha";
5
- import * as apigIntegrations from "@aws-cdk/aws-apigatewayv2-integrations-alpha";
5
+ import { HttpUrlIntegrationProps, HttpAlbIntegrationProps, HttpNlbIntegrationProps } from "@aws-cdk/aws-apigatewayv2-integrations-alpha";
6
6
  import * as elb from "aws-cdk-lib/aws-elasticloadbalancingv2";
7
7
  import * as lambda from "aws-cdk-lib/aws-lambda";
8
8
  import * as logs from "aws-cdk-lib/aws-logs";
9
+ import { HttpAwsIntegrationProps } from "./cdk/HttpAwsIntegration.js";
9
10
  import { SSTConstruct } from "./Construct.js";
10
11
  import { Function as Fn, FunctionProps, FunctionInlineDefinition, FunctionDefinition } from "./Function.js";
11
12
  import { FunctionBindingProps } from "./util/functionBinding.js";
@@ -16,6 +17,8 @@ import * as apigV2Domain from "./util/apiGatewayV2Domain.js";
16
17
  import * as apigV2AccessLog from "./util/apiGatewayV2AccessLog.js";
17
18
  declare const PayloadFormatVersions: readonly ["1.0", "2.0"];
18
19
  export type ApiPayloadFormatVersion = (typeof PayloadFormatVersions)[number];
20
+ export interface CdkHttpAwsIntegrationProps extends HttpAwsIntegrationProps {
21
+ }
19
22
  export type ApiAuthorizer = ApiUserPoolAuthorizer | ApiJwtAuthorizer | ApiLambdaAuthorizer;
20
23
  interface ApiBaseAuthorizer {
21
24
  /**
@@ -394,7 +397,7 @@ export interface ApiProps<Authorizers extends Record<string, ApiAuthorizer> = Re
394
397
  httpStages?: Omit<apig.HttpStageProps, "httpApi">[];
395
398
  };
396
399
  }
397
- export type ApiRouteProps<AuthorizerKeys> = FunctionInlineDefinition | ApiFunctionRouteProps<AuthorizerKeys> | ApiHttpRouteProps<AuthorizerKeys> | ApiAlbRouteProps<AuthorizerKeys> | ApiNlbRouteProps<AuthorizerKeys> | ApiGraphQLRouteProps<AuthorizerKeys>;
400
+ export type ApiRouteProps<AuthorizerKeys> = FunctionInlineDefinition | ApiFunctionRouteProps<AuthorizerKeys> | ApiAwsRouteProps<AuthorizerKeys> | ApiHttpRouteProps<AuthorizerKeys> | ApiAlbRouteProps<AuthorizerKeys> | ApiNlbRouteProps<AuthorizerKeys> | ApiGraphQLRouteProps<AuthorizerKeys>;
398
401
  interface ApiBaseRouteProps<AuthorizerKeys = string> {
399
402
  authorizer?: "none" | "iam" | (string extends AuthorizerKeys ? Omit<AuthorizerKeys, "none" | "iam"> : AuthorizerKeys);
400
403
  authorizationScopes?: string[];
@@ -432,6 +435,37 @@ export interface ApiFunctionRouteProps<AuthorizersKeys = string> extends ApiBase
432
435
  function?: lambda.IFunction;
433
436
  };
434
437
  }
438
+ /**
439
+ * Specify a function route handler and configure additional options
440
+ *
441
+ * @example
442
+ * ```js
443
+ * api.addRoutes(stack, {
444
+ * "GET /notes/{id}": {
445
+ * type: "aws",
446
+ * cdk: {
447
+ * integration: {
448
+ * subtype: "EventBridge-PutEvents",
449
+ * parameterMapping: ParameterMapping.fromObject({
450
+ * Source: MappingValue.custom("$request.body.source"),
451
+ * DetailType: MappingValue.custom("$request.body.detailType"),
452
+ * Detail: MappingValue.custom("$request.body.detail"),
453
+ * }),
454
+ * }
455
+ * }
456
+ * }
457
+ * });
458
+ * ```
459
+ */
460
+ export interface ApiAwsRouteProps<AuthorizersKeys> extends ApiBaseRouteProps<AuthorizersKeys> {
461
+ /**
462
+ * This is a constant
463
+ */
464
+ type: "aws";
465
+ cdk: {
466
+ integration: Omit<CdkHttpAwsIntegrationProps, "credentials">;
467
+ };
468
+ }
435
469
  /**
436
470
  * Specify a route handler that forwards to another URL
437
471
  *
@@ -458,7 +492,7 @@ export interface ApiHttpRouteProps<AuthorizersKeys> extends ApiBaseRouteProps<Au
458
492
  /**
459
493
  * Override the underlying CDK integration
460
494
  */
461
- integration: apigIntegrations.HttpUrlIntegrationProps;
495
+ integration: HttpUrlIntegrationProps;
462
496
  };
463
497
  }
464
498
  /**
@@ -483,7 +517,7 @@ export interface ApiAlbRouteProps<AuthorizersKeys> extends ApiBaseRouteProps<Aut
483
517
  * The listener to the application load balancer used for the integration.
484
518
  */
485
519
  albListener: elb.IApplicationListener;
486
- integration?: apigIntegrations.HttpAlbIntegrationProps;
520
+ integration?: HttpAlbIntegrationProps;
487
521
  };
488
522
  }
489
523
  /**
@@ -508,7 +542,7 @@ export interface ApiNlbRouteProps<AuthorizersKeys> extends ApiBaseRouteProps<Aut
508
542
  * The listener to the application load balancer used for the integration.
509
543
  */
510
544
  nlbListener: elb.INetworkListener;
511
- integration?: apigIntegrations.HttpNlbIntegrationProps;
545
+ integration?: HttpNlbIntegrationProps;
512
546
  };
513
547
  }
514
548
  /**
@@ -732,7 +766,7 @@ export declare class Api<Authorizers extends Record<string, ApiAuthorizer> = Rec
732
766
  output: string | undefined;
733
767
  commands: string[] | undefined;
734
768
  } | {
735
- type: "lambda_function" | "url" | "alb" | "nlb";
769
+ type: "lambda_function" | "aws" | "url" | "alb" | "nlb";
736
770
  route: string;
737
771
  fn?: undefined;
738
772
  schema?: undefined;
@@ -746,6 +780,7 @@ export declare class Api<Authorizers extends Record<string, ApiAuthorizer> = Rec
746
780
  private createHttpApi;
747
781
  private addAuthorizers;
748
782
  private addRoute;
783
+ private createAwsProxyIntegration;
749
784
  private createHttpIntegration;
750
785
  private createAlbIntegration;
751
786
  private createNlbIntegration;
package/constructs/Api.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { Construct } from "constructs";
2
2
  import * as cdkLib from "aws-cdk-lib";
3
3
  import * as cognito from "aws-cdk-lib/aws-cognito";
4
+ import { Role, ServicePrincipal, PolicyDocument, PolicyStatement, } from "aws-cdk-lib/aws-iam";
4
5
  import * as apig from "@aws-cdk/aws-apigatewayv2-alpha";
5
6
  import * as apigAuthorizers from "@aws-cdk/aws-apigatewayv2-authorizers-alpha";
6
- import * as apigIntegrations from "@aws-cdk/aws-apigatewayv2-integrations-alpha";
7
+ import { HttpUrlIntegration, HttpAlbIntegration, HttpNlbIntegration, HttpLambdaIntegration, } from "@aws-cdk/aws-apigatewayv2-integrations-alpha";
8
+ import { HttpAwsIntegration, } from "./cdk/HttpAwsIntegration.js";
7
9
  import { Stack } from "./Stack.js";
8
10
  import { getFunctionRef, isCDKConstruct } from "./Construct.js";
9
11
  import { Function as Fn, } from "./Function.js";
@@ -438,6 +440,12 @@ export class Api extends Construct {
438
440
  this.createFunctionIntegration(scope, routeKey, routeProps, postfixName),
439
441
  ];
440
442
  }
443
+ if (routeValue.type === "aws") {
444
+ return [
445
+ routeValue,
446
+ this.createAwsProxyIntegration(scope, routeKey, routeValue, postfixName),
447
+ ];
448
+ }
441
449
  if (routeValue.type === "alb") {
442
450
  return [
443
451
  routeValue,
@@ -476,7 +484,7 @@ export class Api extends Construct {
476
484
  }
477
485
  if ("handler" in routeValue)
478
486
  throw new Error(`Function definition must be nested under the "function" key in the route props for "${routeKey}". ie. { function: { handler: "myfunc.handler" } }`);
479
- throw new Error(`Invalid route type for "${routeKey}". Must be one of: alb, nlb, url, or function`);
487
+ throw new Error(`Invalid route type "${routeValue.type}" for "${routeKey}".`);
480
488
  })();
481
489
  const { authorizationType, authorizer, authorizationScopes } = this.buildRouteAuth(routeProps);
482
490
  const route = new apig.HttpRoute(scope, `Route_${postfixName}`, {
@@ -502,11 +510,45 @@ export class Api extends Construct {
502
510
  cfnRoute.authorizationType = "NONE";
503
511
  }
504
512
  }
513
+ createAwsProxyIntegration(scope, routeKey, routeProps, postfixName) {
514
+ // Create IAM role for API Gateway to call the AWS services
515
+ const [service, serviceApi] = routeProps.cdk.integration.subtype.split("-");
516
+ const servicePrefix = {
517
+ EventBridge: "events",
518
+ SQS: "sqs",
519
+ AppConfig: "appconfig",
520
+ Kinesis: "kinesis",
521
+ StepFunctions: "states",
522
+ }[service];
523
+ const role = new Role(scope, `IntegrationRole_${postfixName}`, {
524
+ assumedBy: new ServicePrincipal("apigateway.amazonaws.com"),
525
+ inlinePolicies: {
526
+ Policy: new PolicyDocument({
527
+ statements: [
528
+ new PolicyStatement({
529
+ actions: [`${servicePrefix}:${serviceApi}`],
530
+ resources: ["*"],
531
+ }),
532
+ ],
533
+ }),
534
+ },
535
+ });
536
+ // Create integration
537
+ const integration = new HttpAwsIntegration(`Integration_${postfixName}`, {
538
+ ...routeProps.cdk.integration,
539
+ credentials: apig.IntegrationCredentials.fromRole(role),
540
+ });
541
+ // Store route
542
+ this.routesData[routeKey] = {
543
+ type: "aws",
544
+ };
545
+ return integration;
546
+ }
505
547
  createHttpIntegration(scope, routeKey, routeProps, postfixName) {
506
548
  ///////////////////
507
549
  // Create integration
508
550
  ///////////////////
509
- const integration = new apigIntegrations.HttpUrlIntegration(`Integration_${postfixName}`, routeProps.url, routeProps.cdk?.integration);
551
+ const integration = new HttpUrlIntegration(`Integration_${postfixName}`, routeProps.url, routeProps.cdk?.integration);
510
552
  // Store route
511
553
  this.routesData[routeKey] = {
512
554
  type: "url",
@@ -518,7 +560,7 @@ export class Api extends Construct {
518
560
  ///////////////////
519
561
  // Create integration
520
562
  ///////////////////
521
- const integration = new apigIntegrations.HttpAlbIntegration(`Integration_${postfixName}`, routeProps.cdk?.albListener, routeProps.cdk?.integration);
563
+ const integration = new HttpAlbIntegration(`Integration_${postfixName}`, routeProps.cdk?.albListener, routeProps.cdk?.integration);
522
564
  // Store route
523
565
  this.routesData[routeKey] = {
524
566
  type: "alb",
@@ -530,7 +572,7 @@ export class Api extends Construct {
530
572
  ///////////////////
531
573
  // Create integration
532
574
  ///////////////////
533
- const integration = new apigIntegrations.HttpNlbIntegration(`Integration_${postfixName}`, routeProps.cdk?.nlbListener, routeProps.cdk?.integration);
575
+ const integration = new HttpNlbIntegration(`Integration_${postfixName}`, routeProps.cdk?.nlbListener, routeProps.cdk?.integration);
534
576
  // Store route
535
577
  this.routesData[routeKey] = {
536
578
  type: "nlb",
@@ -576,7 +618,7 @@ export class Api extends Construct {
576
618
  ///////////////////
577
619
  // Create integration
578
620
  ///////////////////
579
- const integration = new apigIntegrations.HttpLambdaIntegration(`Integration_${postfixName}`, lambda, {
621
+ const integration = new HttpLambdaIntegration(`Integration_${postfixName}`, lambda, {
580
622
  payloadFormatVersion: integrationPayloadFormatVersion,
581
623
  });
582
624
  // Store route
@@ -615,7 +657,7 @@ export class Api extends Construct {
615
657
  ///////////////////
616
658
  // Create integration
617
659
  ///////////////////
618
- const integration = new apigIntegrations.HttpLambdaIntegration(`Integration_${postfixName}`, lambda, {
660
+ const integration = new HttpLambdaIntegration(`Integration_${postfixName}`, lambda, {
619
661
  payloadFormatVersion: integrationPayloadFormatVersion,
620
662
  });
621
663
  // Store route
@@ -0,0 +1,32 @@
1
+ import { HttpIntegrationSubtype, HttpRouteIntegrationBindOptions, HttpRouteIntegrationConfig, HttpRouteIntegration, ParameterMapping, IntegrationCredentials } from "@aws-cdk/aws-apigatewayv2-alpha";
2
+ /**
3
+ * Properties to initialize a new `HttpProxyIntegration`.
4
+ */
5
+ export interface HttpAwsIntegrationProps {
6
+ /**
7
+ * Specifies the AWS service action to invoke
8
+ */
9
+ readonly subtype: HttpIntegrationSubtype;
10
+ /**
11
+ * Specifies how to transform HTTP requests before sending them to the backend
12
+ */
13
+ readonly parameterMapping: ParameterMapping;
14
+ /**
15
+ * The credentials with which to invoke the integration.
16
+ *
17
+ * @default - no credentials, use resource-based permissions on supported AWS services
18
+ */
19
+ readonly credentials: IntegrationCredentials;
20
+ }
21
+ /**
22
+ * The HTTP Proxy integration resource for HTTP API
23
+ */
24
+ export declare class HttpAwsIntegration extends HttpRouteIntegration {
25
+ private readonly props;
26
+ /**
27
+ * @param id id of the underlying integration construct
28
+ * @param props properties to configure the integration
29
+ */
30
+ constructor(id: string, props: HttpAwsIntegrationProps);
31
+ bind(_: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig;
32
+ }
@@ -0,0 +1,24 @@
1
+ import { HttpIntegrationType, HttpRouteIntegration, PayloadFormatVersion, } from "@aws-cdk/aws-apigatewayv2-alpha";
2
+ /**
3
+ * The HTTP Proxy integration resource for HTTP API
4
+ */
5
+ export class HttpAwsIntegration extends HttpRouteIntegration {
6
+ props;
7
+ /**
8
+ * @param id id of the underlying integration construct
9
+ * @param props properties to configure the integration
10
+ */
11
+ constructor(id, props) {
12
+ super(id);
13
+ this.props = props;
14
+ }
15
+ bind(_) {
16
+ return {
17
+ payloadFormatVersion: PayloadFormatVersion.VERSION_1_0,
18
+ type: HttpIntegrationType.AWS_PROXY,
19
+ subtype: this.props.subtype,
20
+ parameterMapping: this.props.parameterMapping,
21
+ credentials: this.props.credentials,
22
+ };
23
+ }
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.1.26",
3
+ "version": "2.1.28",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
package/sst.mjs CHANGED
@@ -6329,18 +6329,15 @@ var init_kysely = __esm({
6329
6329
  "use strict";
6330
6330
  init_context();
6331
6331
  init_bus();
6332
- init_project();
6333
6332
  init_logger();
6334
6333
  init_credentials();
6335
6334
  useKyselyTypeGenerator = Context.memo(async () => {
6336
6335
  let databases = [];
6337
6336
  const bus = useBus();
6338
- const project = useProject();
6339
6337
  async function generate2(db) {
6340
6338
  if (!db.types)
6341
6339
  return;
6342
6340
  Logger.debug("Generating types for", db.migratorID);
6343
- const credentials = await useAWSCredentials();
6344
6341
  const k = new Kysely({
6345
6342
  dialect: new DataApiDialect({
6346
6343
  mode: db.engine.includes("postgres") ? "postgres" : "mysql",
@@ -6413,7 +6410,8 @@ var init_kysely = __esm({
6413
6410
  );
6414
6411
  if (!db)
6415
6412
  return;
6416
- generate2(db);
6413
+ generate2(db).catch(() => {
6414
+ });
6417
6415
  });
6418
6416
  Logger.debug("Loaded kyseley type generator");
6419
6417
  });
@@ -6758,7 +6756,7 @@ var env = (program2) => program2.command(
6758
6756
  const fs19 = await import("fs/promises");
6759
6757
  const { SiteEnv } = await Promise.resolve().then(() => (init_site_env(), site_env_exports));
6760
6758
  const { spawnSync } = await import("child_process");
6761
- const { useAWSCredentials: useAWSCredentials2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
6759
+ const { useAWSCredentials: useAWSCredentials3 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
6762
6760
  const { useProject: useProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
6763
6761
  let spinner;
6764
6762
  while (true) {
@@ -6774,7 +6772,7 @@ var env = (program2) => program2.command(
6774
6772
  const sites = await SiteEnv.values();
6775
6773
  const env2 = sites[process.cwd()] || {};
6776
6774
  const project = useProject2();
6777
- const credentials = await useAWSCredentials2();
6775
+ const credentials = await useAWSCredentials3();
6778
6776
  const joined = args.command?.join(" ");
6779
6777
  if (!joined)
6780
6778
  throw new VisibleError(
@@ -7139,11 +7137,11 @@ var bind = (program2) => program2.command(
7139
7137
  async (args) => {
7140
7138
  const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
7141
7139
  const { spawnSync } = await import("child_process");
7142
- const { useAWSCredentials: useAWSCredentials2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
7140
+ const { useAWSCredentials: useAWSCredentials3 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
7143
7141
  const { useProject: useProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
7144
7142
  const env2 = await Config2.env();
7145
7143
  const project = useProject2();
7146
- const credentials = await useAWSCredentials2();
7144
+ const credentials = await useAWSCredentials3();
7147
7145
  const joined = args.command?.join(" ");
7148
7146
  if (!joined)
7149
7147
  throw new VisibleError("Command is required, e.g. sst bind env");