@aws/nx-plugin 0.82.1 → 0.83.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 (54) hide show
  1. package/LICENSE-THIRD-PARTY +34 -6
  2. package/package.json +1 -1
  3. package/src/infra/app/__snapshots__/generator.spec.ts.snap +4 -4
  4. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +148 -56
  5. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +53 -3
  6. package/src/py/mcp-server/generator.js +1 -0
  7. package/src/py/mcp-server/generator.js.map +1 -1
  8. package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +53 -3
  9. package/src/py/strands-agent/generator.js +1 -0
  10. package/src/py/strands-agent/generator.js.map +1 -1
  11. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +108 -50
  12. package/src/smithy/ts/api/generator.js +2 -0
  13. package/src/smithy/ts/api/generator.js.map +1 -1
  14. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +256 -128
  15. package/src/trpc/backend/generator.js +2 -0
  16. package/src/trpc/backend/generator.js.map +1 -1
  17. package/src/ts/lambda-function/generator.js +2 -0
  18. package/src/ts/lambda-function/generator.js.map +1 -1
  19. package/src/ts/lib/vitest.js +2 -0
  20. package/src/ts/lib/vitest.js.map +1 -1
  21. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +54 -3
  22. package/src/ts/mcp-server/generator.js +7 -1
  23. package/src/ts/mcp-server/generator.js.map +1 -1
  24. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +372 -26
  25. package/src/ts/react-website/app/generator.js +5 -1
  26. package/src/ts/react-website/app/generator.js.map +1 -1
  27. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +2 -2
  28. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -0
  29. package/src/ts/strands-agent/__snapshots__/generator.spec.ts.snap +52 -3
  30. package/src/ts/strands-agent/generator.js +3 -1
  31. package/src/ts/strands-agent/generator.js.map +1 -1
  32. package/src/utils/__snapshots__/shared-constructs.spec.ts.snap +157 -5
  33. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +14 -0
  34. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +37 -2
  35. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +1 -1
  36. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +19 -17
  37. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +28 -21
  38. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +4 -3
  39. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +24 -5
  40. package/src/utils/api-constructs/files/cdk/core/api/utils/utils.ts.template +4 -1
  41. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +11 -2
  42. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +11 -2
  43. package/src/utils/files/common/constructs/src/core/runtime-config.ts.template +157 -5
  44. package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +100 -0
  45. package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +19 -17
  46. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +12 -5
  47. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +2 -2
  48. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +2 -0
  49. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +2 -1
  50. package/src/utils/versions.d.ts +6 -1
  51. package/src/utils/versions.js +5 -0
  52. package/src/utils/versions.js.map +1 -1
  53. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +8 -3
  54. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +10 -1
@@ -360,14 +360,14 @@ import {
360
360
  FunctionProps,
361
361
  Tracing,
362
362
  } from 'aws-cdk-lib/aws-lambda';
363
+ import { RuntimeConfig } from '../../core/runtime-config.js';
363
364
  import {
364
365
  AuthorizationType,
365
- Cors,
366
366
  LambdaIntegration,
367
367
  ResponseTransferMode,
368
368
  CognitoUserPoolsAuthorizer,
369
369
  } from 'aws-cdk-lib/aws-apigateway';
370
- import { Duration } from 'aws-cdk-lib';
370
+ import { Aspects, Duration } from 'aws-cdk-lib';
371
371
  import {
372
372
  PolicyDocument,
373
373
  PolicyStatement,
@@ -380,7 +380,7 @@ import {
380
380
  IntegrationBuilder,
381
381
  RestApiIntegration,
382
382
  } from '../../core/api/utils.js';
383
- import { RestApi } from '../../core/api/rest-api.js';
383
+ import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
384
384
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
385
385
  import { AppRouter, appRouter } from ':proj/test-api';
386
386
 
@@ -415,6 +415,8 @@ export interface TestApiProps<
415
415
  export class TestApi<
416
416
  TIntegrations extends ApiIntegrations<Operations, RestApiIntegration>,
417
417
  > extends RestApi<Operations, TIntegrations> {
418
+ private allowedOrigins: readonly string[] = ['*'];
419
+
418
420
  /**
419
421
  * Creates default integrations for all operations, which implement each operation as
420
422
  * its own individual lambda function.
@@ -423,6 +425,7 @@ export class TestApi<
423
425
  * @returns An IntegrationBuilder with default lambda integrations
424
426
  */
425
427
  public static defaultIntegrations = (scope: Construct) => {
428
+ const rc = RuntimeConfig.ensure(scope);
426
429
  return IntegrationBuilder.rest({
427
430
  pattern: 'isolated',
428
431
  operations: routerToOperations(appRouter),
@@ -441,10 +444,12 @@ export class TestApi<
441
444
  tracing: Tracing.ACTIVE,
442
445
  environment: {
443
446
  AWS_CONNECTION_REUSE_ENABLED: '1',
447
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
444
448
  },
445
449
  },
446
450
  buildDefaultIntegration: (op, props: FunctionProps) => {
447
451
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
452
+ rc.grantReadAppConfig(handler);
448
453
  return {
449
454
  handler,
450
455
  integration: new LambdaIntegration(handler, {
@@ -468,10 +473,6 @@ export class TestApi<
468
473
  cognitoUserPools: [props.identity.userPool],
469
474
  }),
470
475
  },
471
- defaultCorsPreflightOptions: {
472
- allowOrigins: Cors.ALL_ORIGINS,
473
- allowMethods: Cors.ALL_METHODS,
474
- },
475
476
  deployOptions: {
476
477
  tracingEnabled: true,
477
478
  },
@@ -489,32 +490,42 @@ export class TestApi<
489
490
  operations: routerToOperations(appRouter),
490
491
  ...props,
491
492
  });
493
+ Aspects.of(this).add(new AddCorsPreflightAspect(() => this.allowedOrigins));
492
494
  }
493
495
 
494
496
  /**
495
- * Restricts CORS to the website CloudFront distribution domains
497
+ * Restricts CORS to the provided origins
496
498
  *
497
- * Configures the CloudFront distribution domains as the only permitted CORS origins
498
- * (other than local host) in the AWS Lambda integrations
499
+ * Configures the provided CloudFront distribution domains or origin strings
500
+ * as the only permitted CORS origins in API Gateway preflight responses and the
501
+ * AWS Lambda integrations.
499
502
  *
500
- * Note that this restriction is not applied to preflight OPTIONS
501
- *
502
- * @param websites - The CloudFront distribution to grant CORS from
503
+ * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
503
504
  */
504
505
  public restrictCorsTo(
505
- ...websites: { cloudFrontDistribution: Distribution }[]
506
+ ...origins: (
507
+ | string
508
+ | Distribution
509
+ | { cloudFrontDistribution: Distribution }
510
+ )[]
506
511
  ) {
507
- const allowedOrigins = websites
508
- .map(
509
- ({ cloudFrontDistribution }) =>
510
- \`https://\${cloudFrontDistribution.distributionDomainName}\`,
511
- )
512
- .join(',');
512
+ const allowedOrigins = origins.map((origin) =>
513
+ typeof origin === 'string'
514
+ ? origin
515
+ : 'cloudFrontDistribution' in origin
516
+ ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
517
+ : \`https://\${origin.distributionDomainName}\`,
518
+ );
519
+
520
+ this.allowedOrigins = allowedOrigins;
513
521
 
514
522
  // Set ALLOWED_ORIGINS environment variable for all Lambda integrations
515
523
  Object.values(this.integrations).forEach((integration) => {
516
524
  if ('handler' in integration && integration.handler instanceof Function) {
517
- integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
525
+ integration.handler.addEnvironment(
526
+ 'ALLOWED_ORIGINS',
527
+ allowedOrigins.join(','),
528
+ );
518
529
  }
519
530
  });
520
531
  }
@@ -562,6 +573,7 @@ import {
562
573
  Tracing,
563
574
  } from 'aws-cdk-lib/aws-lambda';
564
575
  import { Duration } from 'aws-cdk-lib';
576
+ import { RuntimeConfig } from '../../core/runtime-config.js';
565
577
  import { CorsHttpMethod, CfnApi } from 'aws-cdk-lib/aws-apigatewayv2';
566
578
  import { HttpUserPoolAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
567
579
  import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
@@ -615,6 +627,7 @@ export class TestApi<
615
627
  * @returns An IntegrationBuilder with default lambda integrations
616
628
  */
617
629
  public static defaultIntegrations = (scope: Construct) => {
630
+ const rc = RuntimeConfig.ensure(scope);
618
631
  return IntegrationBuilder.http({
619
632
  pattern: 'isolated',
620
633
  operations: routerToOperations(appRouter),
@@ -633,10 +646,12 @@ export class TestApi<
633
646
  tracing: Tracing.ACTIVE,
634
647
  environment: {
635
648
  AWS_CONNECTION_REUSE_ENABLED: '1',
649
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
636
650
  },
637
651
  },
638
652
  buildDefaultIntegration: (op, props: FunctionProps) => {
639
653
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
654
+ rc.grantReadAppConfig(handler);
640
655
  return {
641
656
  handler,
642
657
  integration: new HttpLambdaIntegration(
@@ -679,21 +694,28 @@ export class TestApi<
679
694
  }
680
695
 
681
696
  /**
682
- * Restricts CORS to the website CloudFront distribution domains
697
+ * Restricts CORS to the provided origins
683
698
  *
684
- * Configures the CloudFront distribution domains as the only permitted CORS origins
685
- * (other than local host with default ports) in the API gateway
686
- * The CORS origins are not configured within the AWS Lambda integrations since
687
- * the associated header is controlled by API Gateway v2
699
+ * Configures the provided CloudFront distribution domains or origin strings
700
+ * as the only permitted CORS origins
701
+ * in the API gateway. The CORS origins are not configured within the AWS Lambda
702
+ * integrations since the associated header is controlled by API Gateway v2.
688
703
  *
689
- * @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
704
+ * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
690
705
  */
691
706
  public restrictCorsTo(
692
- ...websites: { cloudFrontDistribution: Distribution }[]
707
+ ...origins: (
708
+ | string
709
+ | Distribution
710
+ | { cloudFrontDistribution: Distribution }
711
+ )[]
693
712
  ) {
694
- const allowedOrigins = websites.map(
695
- ({ cloudFrontDistribution }) =>
696
- \`https://\${cloudFrontDistribution.distributionDomainName}\`,
713
+ const allowedOrigins = origins.map((origin) =>
714
+ typeof origin === 'string'
715
+ ? origin
716
+ : 'cloudFrontDistribution' in origin
717
+ ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
718
+ : \`https://\${origin.distributionDomainName}\`,
697
719
  );
698
720
 
699
721
  const cfnApi = this.api.node.defaultChild;
@@ -704,11 +726,7 @@ export class TestApi<
704
726
  }
705
727
 
706
728
  cfnApi.corsConfiguration = {
707
- allowOrigins: [
708
- 'http://localhost:4200',
709
- 'http://localhost:4300',
710
- ...allowedOrigins,
711
- ],
729
+ allowOrigins: allowedOrigins,
712
730
  allowMethods: [CorsHttpMethod.ANY],
713
731
  allowHeaders: [
714
732
  'authorization',
@@ -758,13 +776,13 @@ import {
758
776
  FunctionProps,
759
777
  Tracing,
760
778
  } from 'aws-cdk-lib/aws-lambda';
779
+ import { RuntimeConfig } from '../../core/runtime-config.js';
761
780
  import {
762
781
  AuthorizationType,
763
- Cors,
764
782
  LambdaIntegration,
765
783
  ResponseTransferMode,
766
784
  } from 'aws-cdk-lib/aws-apigateway';
767
- import { Duration } from 'aws-cdk-lib';
785
+ import { Aspects, Duration } from 'aws-cdk-lib';
768
786
  import {
769
787
  PolicyDocument,
770
788
  PolicyStatement,
@@ -776,7 +794,7 @@ import {
776
794
  IntegrationBuilder,
777
795
  RestApiIntegration,
778
796
  } from '../../core/api/utils.js';
779
- import { RestApi } from '../../core/api/rest-api.js';
797
+ import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
780
798
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
781
799
  import { AppRouter, appRouter } from ':proj/test-api';
782
800
 
@@ -805,6 +823,8 @@ export interface TestApiProps<
805
823
  export class TestApi<
806
824
  TIntegrations extends ApiIntegrations<Operations, RestApiIntegration>,
807
825
  > extends RestApi<Operations, TIntegrations> {
826
+ private allowedOrigins: readonly string[] = ['*'];
827
+
808
828
  /**
809
829
  * Creates default integrations for all operations, which implement each operation as
810
830
  * its own individual lambda function.
@@ -813,6 +833,7 @@ export class TestApi<
813
833
  * @returns An IntegrationBuilder with default lambda integrations
814
834
  */
815
835
  public static defaultIntegrations = (scope: Construct) => {
836
+ const rc = RuntimeConfig.ensure(scope);
816
837
  return IntegrationBuilder.rest({
817
838
  pattern: 'isolated',
818
839
  operations: routerToOperations(appRouter),
@@ -831,10 +852,12 @@ export class TestApi<
831
852
  tracing: Tracing.ACTIVE,
832
853
  environment: {
833
854
  AWS_CONNECTION_REUSE_ENABLED: '1',
855
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
834
856
  },
835
857
  },
836
858
  buildDefaultIntegration: (op, props: FunctionProps) => {
837
859
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
860
+ rc.grantReadAppConfig(handler);
838
861
  return {
839
862
  handler,
840
863
  integration: new LambdaIntegration(handler, {
@@ -855,10 +878,6 @@ export class TestApi<
855
878
  defaultMethodOptions: {
856
879
  authorizationType: AuthorizationType.NONE,
857
880
  },
858
- defaultCorsPreflightOptions: {
859
- allowOrigins: Cors.ALL_ORIGINS,
860
- allowMethods: Cors.ALL_METHODS,
861
- },
862
881
  deployOptions: {
863
882
  tracingEnabled: true,
864
883
  },
@@ -876,32 +895,42 @@ export class TestApi<
876
895
  operations: routerToOperations(appRouter),
877
896
  ...props,
878
897
  });
898
+ Aspects.of(this).add(new AddCorsPreflightAspect(() => this.allowedOrigins));
879
899
  }
880
900
 
881
901
  /**
882
- * Restricts CORS to the website CloudFront distribution domains
902
+ * Restricts CORS to the provided origins
883
903
  *
884
- * Configures the CloudFront distribution domains as the only permitted CORS origins
885
- * (other than local host) in the AWS Lambda integrations
904
+ * Configures the provided CloudFront distribution domains or origin strings
905
+ * as the only permitted CORS origins in API Gateway preflight responses and the
906
+ * AWS Lambda integrations.
886
907
  *
887
- * Note that this restriction is not applied to preflight OPTIONS
888
- *
889
- * @param websites - The CloudFront distribution to grant CORS from
908
+ * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
890
909
  */
891
910
  public restrictCorsTo(
892
- ...websites: { cloudFrontDistribution: Distribution }[]
911
+ ...origins: (
912
+ | string
913
+ | Distribution
914
+ | { cloudFrontDistribution: Distribution }
915
+ )[]
893
916
  ) {
894
- const allowedOrigins = websites
895
- .map(
896
- ({ cloudFrontDistribution }) =>
897
- \`https://\${cloudFrontDistribution.distributionDomainName}\`,
898
- )
899
- .join(',');
917
+ const allowedOrigins = origins.map((origin) =>
918
+ typeof origin === 'string'
919
+ ? origin
920
+ : 'cloudFrontDistribution' in origin
921
+ ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
922
+ : \`https://\${origin.distributionDomainName}\`,
923
+ );
924
+
925
+ this.allowedOrigins = allowedOrigins;
900
926
 
901
927
  // Set ALLOWED_ORIGINS environment variable for all Lambda integrations
902
928
  Object.values(this.integrations).forEach((integration) => {
903
929
  if ('handler' in integration && integration.handler instanceof Function) {
904
- integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
930
+ integration.handler.addEnvironment(
931
+ 'ALLOWED_ORIGINS',
932
+ allowedOrigins.join(','),
933
+ );
905
934
  }
906
935
  });
907
936
  }
@@ -945,6 +974,7 @@ import {
945
974
  Tracing,
946
975
  } from 'aws-cdk-lib/aws-lambda';
947
976
  import { Duration } from 'aws-cdk-lib';
977
+ import { RuntimeConfig } from '../../core/runtime-config.js';
948
978
  import {
949
979
  CorsHttpMethod,
950
980
  CfnApi,
@@ -993,6 +1023,7 @@ export class TestApi<
993
1023
  * @returns An IntegrationBuilder with default lambda integrations
994
1024
  */
995
1025
  public static defaultIntegrations = (scope: Construct) => {
1026
+ const rc = RuntimeConfig.ensure(scope);
996
1027
  return IntegrationBuilder.http({
997
1028
  pattern: 'isolated',
998
1029
  operations: routerToOperations(appRouter),
@@ -1011,10 +1042,12 @@ export class TestApi<
1011
1042
  tracing: Tracing.ACTIVE,
1012
1043
  environment: {
1013
1044
  AWS_CONNECTION_REUSE_ENABLED: '1',
1045
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
1014
1046
  },
1015
1047
  },
1016
1048
  buildDefaultIntegration: (op, props: FunctionProps) => {
1017
1049
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1050
+ rc.grantReadAppConfig(handler);
1018
1051
  return {
1019
1052
  handler,
1020
1053
  integration: new HttpLambdaIntegration(
@@ -1051,21 +1084,28 @@ export class TestApi<
1051
1084
  }
1052
1085
 
1053
1086
  /**
1054
- * Restricts CORS to the website CloudFront distribution domains
1087
+ * Restricts CORS to the provided origins
1055
1088
  *
1056
- * Configures the CloudFront distribution domains as the only permitted CORS origins
1057
- * (other than local host with default ports) in the API gateway
1058
- * The CORS origins are not configured within the AWS Lambda integrations since
1059
- * the associated header is controlled by API Gateway v2
1089
+ * Configures the provided CloudFront distribution domains or origin strings
1090
+ * as the only permitted CORS origins
1091
+ * in the API gateway. The CORS origins are not configured within the AWS Lambda
1092
+ * integrations since the associated header is controlled by API Gateway v2.
1060
1093
  *
1061
- * @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
1094
+ * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
1062
1095
  */
1063
1096
  public restrictCorsTo(
1064
- ...websites: { cloudFrontDistribution: Distribution }[]
1097
+ ...origins: (
1098
+ | string
1099
+ | Distribution
1100
+ | { cloudFrontDistribution: Distribution }
1101
+ )[]
1065
1102
  ) {
1066
- const allowedOrigins = websites.map(
1067
- ({ cloudFrontDistribution }) =>
1068
- \`https://\${cloudFrontDistribution.distributionDomainName}\`,
1103
+ const allowedOrigins = origins.map((origin) =>
1104
+ typeof origin === 'string'
1105
+ ? origin
1106
+ : 'cloudFrontDistribution' in origin
1107
+ ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
1108
+ : \`https://\${origin.distributionDomainName}\`,
1069
1109
  );
1070
1110
 
1071
1111
  const cfnApi = this.api.node.defaultChild;
@@ -1076,11 +1116,7 @@ export class TestApi<
1076
1116
  }
1077
1117
 
1078
1118
  cfnApi.corsConfiguration = {
1079
- allowOrigins: [
1080
- 'http://localhost:4200',
1081
- 'http://localhost:4300',
1082
- ...allowedOrigins,
1083
- ],
1119
+ allowOrigins: allowedOrigins,
1084
1120
  allowMethods: [CorsHttpMethod.ANY],
1085
1121
  allowHeaders: [
1086
1122
  'authorization',
@@ -1236,10 +1272,11 @@ export class HttpApi<
1236
1272
  });
1237
1273
 
1238
1274
  // Register the API URL in runtime configuration for client discovery
1239
- RuntimeConfig.ensure(this).config.apis = {
1240
- ...RuntimeConfig.ensure(this).config.apis!,
1275
+ const rc = RuntimeConfig.ensure(this);
1276
+ rc.set('connection', 'apis', {
1277
+ ...rc.get('connection').apis,
1241
1278
  [apiName]: this.defaultStage.url!,
1242
- };
1279
+ });
1243
1280
  }
1244
1281
 
1245
1282
  /**
@@ -1264,6 +1301,7 @@ import {
1264
1301
  Tracing,
1265
1302
  } from 'aws-cdk-lib/aws-lambda';
1266
1303
  import { Duration } from 'aws-cdk-lib';
1304
+ import { RuntimeConfig } from '../../core/runtime-config.js';
1267
1305
  import { CorsHttpMethod, CfnApi } from 'aws-cdk-lib/aws-apigatewayv2';
1268
1306
  import { HttpIamAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
1269
1307
  import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
@@ -1310,6 +1348,7 @@ export class TestApi<
1310
1348
  * @returns An IntegrationBuilder with default lambda integrations
1311
1349
  */
1312
1350
  public static defaultIntegrations = (scope: Construct) => {
1351
+ const rc = RuntimeConfig.ensure(scope);
1313
1352
  return IntegrationBuilder.http({
1314
1353
  pattern: 'isolated',
1315
1354
  operations: routerToOperations(appRouter),
@@ -1328,10 +1367,12 @@ export class TestApi<
1328
1367
  tracing: Tracing.ACTIVE,
1329
1368
  environment: {
1330
1369
  AWS_CONNECTION_REUSE_ENABLED: '1',
1370
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
1331
1371
  },
1332
1372
  },
1333
1373
  buildDefaultIntegration: (op, props: FunctionProps) => {
1334
1374
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1375
+ rc.grantReadAppConfig(handler);
1335
1376
  return {
1336
1377
  handler,
1337
1378
  integration: new HttpLambdaIntegration(
@@ -1368,21 +1409,28 @@ export class TestApi<
1368
1409
  }
1369
1410
 
1370
1411
  /**
1371
- * Restricts CORS to the website CloudFront distribution domains
1412
+ * Restricts CORS to the provided origins
1372
1413
  *
1373
- * Configures the CloudFront distribution domains as the only permitted CORS origins
1374
- * (other than local host with default ports) in the API gateway
1375
- * The CORS origins are not configured within the AWS Lambda integrations since
1376
- * the associated header is controlled by API Gateway v2
1414
+ * Configures the provided CloudFront distribution domains or origin strings
1415
+ * as the only permitted CORS origins
1416
+ * in the API gateway. The CORS origins are not configured within the AWS Lambda
1417
+ * integrations since the associated header is controlled by API Gateway v2.
1377
1418
  *
1378
- * @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
1419
+ * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
1379
1420
  */
1380
1421
  public restrictCorsTo(
1381
- ...websites: { cloudFrontDistribution: Distribution }[]
1422
+ ...origins: (
1423
+ | string
1424
+ | Distribution
1425
+ | { cloudFrontDistribution: Distribution }
1426
+ )[]
1382
1427
  ) {
1383
- const allowedOrigins = websites.map(
1384
- ({ cloudFrontDistribution }) =>
1385
- \`https://\${cloudFrontDistribution.distributionDomainName}\`,
1428
+ const allowedOrigins = origins.map((origin) =>
1429
+ typeof origin === 'string'
1430
+ ? origin
1431
+ : 'cloudFrontDistribution' in origin
1432
+ ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
1433
+ : \`https://\${origin.distributionDomainName}\`,
1386
1434
  );
1387
1435
 
1388
1436
  const cfnApi = this.api.node.defaultChild;
@@ -1393,11 +1441,7 @@ export class TestApi<
1393
1441
  }
1394
1442
 
1395
1443
  cfnApi.corsConfiguration = {
1396
- allowOrigins: [
1397
- 'http://localhost:4200',
1398
- 'http://localhost:4300',
1399
- ...allowedOrigins,
1400
- ],
1444
+ allowOrigins: allowedOrigins,
1401
1445
  allowMethods: [CorsHttpMethod.ANY],
1402
1446
  allowHeaders: [
1403
1447
  'authorization',
@@ -1846,13 +1890,16 @@ export class IntegrationBuilder<
1846
1890
  `;
1847
1891
 
1848
1892
  exports[`trpc backend generator > should set up shared constructs for rest > rest-api.ts 1`] = `
1849
- "import { Construct } from 'constructs';
1893
+ "import { Construct, IConstruct } from 'constructs';
1850
1894
  import {
1895
+ Cors,
1896
+ Resource,
1851
1897
  RestApi as _RestApi,
1852
1898
  RestApiProps as _RestApiProps,
1853
1899
  IResource,
1854
1900
  Stage,
1855
1901
  } from 'aws-cdk-lib/aws-apigateway';
1902
+ import { IAspect } from 'aws-cdk-lib';
1856
1903
  import { RuntimeConfig } from '../runtime-config.js';
1857
1904
  import {
1858
1905
  ApiIntegrations,
@@ -1951,7 +1998,7 @@ export class RestApi<
1951
1998
  };
1952
1999
 
1953
2000
  // Create API resources and methods for each operation
1954
- (Object.entries(operations) as [TOperation, OperationDetails][]).map(
2001
+ (Object.entries(operations) as [TOperation, OperationDetails][]).forEach(
1955
2002
  ([op, details]) => {
1956
2003
  const integration = resolveIntegration(op);
1957
2004
  const resource = this.getOrCreateResource(
@@ -1970,10 +2017,11 @@ export class RestApi<
1970
2017
  );
1971
2018
 
1972
2019
  // Register the API URL in runtime configuration for client discovery
1973
- RuntimeConfig.ensure(this).config.apis = {
1974
- ...RuntimeConfig.ensure(this).config.apis!,
2020
+ const rc = RuntimeConfig.ensure(this);
2021
+ rc.set('connection', 'apis', {
2022
+ ...rc.get('connection').apis,
1975
2023
  [apiName]: this.api.url!,
1976
- };
2024
+ });
1977
2025
  }
1978
2026
 
1979
2027
  /**
@@ -1995,6 +2043,21 @@ export class RestApi<
1995
2043
  return this.getOrCreateResource(childResource, pathParts);
1996
2044
  }
1997
2045
  }
2046
+
2047
+ export class AddCorsPreflightAspect implements IAspect {
2048
+ private getAllowedOrigins: () => readonly string[];
2049
+ constructor(getAllowedOrigins: () => readonly string[]) {
2050
+ this.getAllowedOrigins = getAllowedOrigins;
2051
+ }
2052
+ public visit(node: IConstruct): void {
2053
+ if (node instanceof Resource) {
2054
+ node.addCorsPreflight({
2055
+ allowOrigins: [...this.getAllowedOrigins()],
2056
+ allowMethods: Cors.ALL_METHODS,
2057
+ });
2058
+ }
2059
+ }
2060
+ }
1998
2061
  "
1999
2062
  `;
2000
2063
 
@@ -2009,13 +2072,13 @@ import {
2009
2072
  FunctionProps,
2010
2073
  Tracing,
2011
2074
  } from 'aws-cdk-lib/aws-lambda';
2075
+ import { RuntimeConfig } from '../../core/runtime-config.js';
2012
2076
  import {
2013
2077
  AuthorizationType,
2014
- Cors,
2015
2078
  LambdaIntegration,
2016
2079
  ResponseTransferMode,
2017
2080
  } from 'aws-cdk-lib/aws-apigateway';
2018
- import { Duration } from 'aws-cdk-lib';
2081
+ import { Aspects, Duration } from 'aws-cdk-lib';
2019
2082
  import {
2020
2083
  PolicyDocument,
2021
2084
  PolicyStatement,
@@ -2029,7 +2092,7 @@ import {
2029
2092
  IntegrationBuilder,
2030
2093
  RestApiIntegration,
2031
2094
  } from '../../core/api/utils.js';
2032
- import { RestApi } from '../../core/api/rest-api.js';
2095
+ import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
2033
2096
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
2034
2097
  import { AppRouter, appRouter } from ':proj/test-api';
2035
2098
 
@@ -2058,6 +2121,8 @@ export interface TestApiProps<
2058
2121
  export class TestApi<
2059
2122
  TIntegrations extends ApiIntegrations<Operations, RestApiIntegration>,
2060
2123
  > extends RestApi<Operations, TIntegrations> {
2124
+ private allowedOrigins: readonly string[] = ['*'];
2125
+
2061
2126
  /**
2062
2127
  * Creates default integrations for all operations, which implement each operation as
2063
2128
  * its own individual lambda function.
@@ -2066,6 +2131,7 @@ export class TestApi<
2066
2131
  * @returns An IntegrationBuilder with default lambda integrations
2067
2132
  */
2068
2133
  public static defaultIntegrations = (scope: Construct) => {
2134
+ const rc = RuntimeConfig.ensure(scope);
2069
2135
  return IntegrationBuilder.rest({
2070
2136
  pattern: 'isolated',
2071
2137
  operations: routerToOperations(appRouter),
@@ -2084,10 +2150,12 @@ export class TestApi<
2084
2150
  tracing: Tracing.ACTIVE,
2085
2151
  environment: {
2086
2152
  AWS_CONNECTION_REUSE_ENABLED: '1',
2153
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
2087
2154
  },
2088
2155
  },
2089
2156
  buildDefaultIntegration: (op, props: FunctionProps) => {
2090
2157
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
2158
+ rc.grantReadAppConfig(handler);
2091
2159
  return {
2092
2160
  handler,
2093
2161
  integration: new LambdaIntegration(handler, {
@@ -2108,10 +2176,6 @@ export class TestApi<
2108
2176
  defaultMethodOptions: {
2109
2177
  authorizationType: AuthorizationType.IAM,
2110
2178
  },
2111
- defaultCorsPreflightOptions: {
2112
- allowOrigins: Cors.ALL_ORIGINS,
2113
- allowMethods: Cors.ALL_METHODS,
2114
- },
2115
2179
  deployOptions: {
2116
2180
  tracingEnabled: true,
2117
2181
  },
@@ -2129,32 +2193,42 @@ export class TestApi<
2129
2193
  operations: routerToOperations(appRouter),
2130
2194
  ...props,
2131
2195
  });
2196
+ Aspects.of(this).add(new AddCorsPreflightAspect(() => this.allowedOrigins));
2132
2197
  }
2133
2198
 
2134
2199
  /**
2135
- * Restricts CORS to the website CloudFront distribution domains
2136
- *
2137
- * Configures the CloudFront distribution domains as the only permitted CORS origins
2138
- * (other than local host) in the AWS Lambda integrations
2200
+ * Restricts CORS to the provided origins
2139
2201
  *
2140
- * Note that this restriction is not applied to preflight OPTIONS
2202
+ * Configures the provided CloudFront distribution domains or origin strings
2203
+ * as the only permitted CORS origins in API Gateway preflight responses and the
2204
+ * AWS Lambda integrations.
2141
2205
  *
2142
- * @param websites - The CloudFront distribution to grant CORS from
2206
+ * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
2143
2207
  */
2144
2208
  public restrictCorsTo(
2145
- ...websites: { cloudFrontDistribution: Distribution }[]
2209
+ ...origins: (
2210
+ | string
2211
+ | Distribution
2212
+ | { cloudFrontDistribution: Distribution }
2213
+ )[]
2146
2214
  ) {
2147
- const allowedOrigins = websites
2148
- .map(
2149
- ({ cloudFrontDistribution }) =>
2150
- \`https://\${cloudFrontDistribution.distributionDomainName}\`,
2151
- )
2152
- .join(',');
2215
+ const allowedOrigins = origins.map((origin) =>
2216
+ typeof origin === 'string'
2217
+ ? origin
2218
+ : 'cloudFrontDistribution' in origin
2219
+ ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
2220
+ : \`https://\${origin.distributionDomainName}\`,
2221
+ );
2222
+
2223
+ this.allowedOrigins = allowedOrigins;
2153
2224
 
2154
2225
  // Set ALLOWED_ORIGINS environment variable for all Lambda integrations
2155
2226
  Object.values(this.integrations).forEach((integration) => {
2156
2227
  if ('handler' in integration && integration.handler instanceof Function) {
2157
- integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
2228
+ integration.handler.addEnvironment(
2229
+ 'ALLOWED_ORIGINS',
2230
+ allowedOrigins.join(','),
2231
+ );
2158
2232
  }
2159
2233
  });
2160
2234
  }
@@ -3108,12 +3182,21 @@ resource "aws_apigatewayv2_route" "proxy_routes" {
3108
3182
  module "add_url_to_runtime_config" {
3109
3183
  source = "../../../core/runtime-config/entry"
3110
3184
 
3111
- key_path = "apis.TestApi"
3112
- value = module.http_api.stage_invoke_url
3185
+ namespace = "connection"
3186
+ key = "apis"
3187
+ value = { "TestApi" = module.http_api.stage_invoke_url }
3113
3188
 
3114
3189
  depends_on = [module.http_api]
3115
3190
  }
3116
3191
 
3192
+ module "appconfig" {
3193
+ source = "../../../core/runtime-config/appconfig"
3194
+
3195
+ application_name = "TestApi-runtime-config"
3196
+
3197
+ depends_on = [module.add_url_to_runtime_config]
3198
+ }
3199
+
3117
3200
  # Lambda permission for API Gateway to invoke the function
3118
3201
  resource "aws_lambda_permission" "api_gateway_invoke" {
3119
3202
  statement_id = "AllowExecutionFromAPIGateway"
@@ -3717,12 +3800,21 @@ resource "aws_apigatewayv2_route" "proxy_routes" {
3717
3800
  module "add_url_to_runtime_config" {
3718
3801
  source = "../../../core/runtime-config/entry"
3719
3802
 
3720
- key_path = "apis.TestApi"
3721
- value = module.http_api.stage_invoke_url
3803
+ namespace = "connection"
3804
+ key = "apis"
3805
+ value = { "TestApi" = module.http_api.stage_invoke_url }
3722
3806
 
3723
3807
  depends_on = [module.http_api]
3724
3808
  }
3725
3809
 
3810
+ module "appconfig" {
3811
+ source = "../../../core/runtime-config/appconfig"
3812
+
3813
+ application_name = "TestApi-runtime-config"
3814
+
3815
+ depends_on = [module.add_url_to_runtime_config]
3816
+ }
3817
+
3726
3818
  # Lambda permission for API Gateway to invoke the function
3727
3819
  resource "aws_lambda_permission" "api_gateway_invoke" {
3728
3820
  statement_id = "AllowExecutionFromAPIGateway"
@@ -4328,12 +4420,21 @@ resource "aws_apigatewayv2_route" "proxy_routes" {
4328
4420
  module "add_url_to_runtime_config" {
4329
4421
  source = "../../../core/runtime-config/entry"
4330
4422
 
4331
- key_path = "apis.TestApi"
4332
- value = module.http_api.stage_invoke_url
4423
+ namespace = "connection"
4424
+ key = "apis"
4425
+ value = { "TestApi" = module.http_api.stage_invoke_url }
4333
4426
 
4334
4427
  depends_on = [module.http_api]
4335
4428
  }
4336
4429
 
4430
+ module "appconfig" {
4431
+ source = "../../../core/runtime-config/appconfig"
4432
+
4433
+ application_name = "TestApi-runtime-config"
4434
+
4435
+ depends_on = [module.add_url_to_runtime_config]
4436
+ }
4437
+
4337
4438
  # Lambda permission for API Gateway to invoke the function
4338
4439
  resource "aws_lambda_permission" "api_gateway_invoke" {
4339
4440
  statement_id = "AllowExecutionFromAPIGateway"
@@ -4968,12 +5069,21 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
4968
5069
  module "add_url_to_runtime_config" {
4969
5070
  source = "../../../core/runtime-config/entry"
4970
5071
 
4971
- key_path = "apis.TestApi"
4972
- value = aws_api_gateway_stage.api_stage.invoke_url
5072
+ namespace = "connection"
5073
+ key = "apis"
5074
+ value = { "TestApi" = aws_api_gateway_stage.api_stage.invoke_url }
4973
5075
 
4974
5076
  depends_on = [aws_api_gateway_stage.api_stage]
4975
5077
  }
4976
5078
 
5079
+ module "appconfig" {
5080
+ source = "../../../core/runtime-config/appconfig"
5081
+
5082
+ application_name = "TestApi-runtime-config"
5083
+
5084
+ depends_on = [module.add_url_to_runtime_config]
5085
+ }
5086
+
4977
5087
  # Outputs
4978
5088
 
4979
5089
  # API Gateway Outputs (from core module)
@@ -5600,12 +5710,21 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
5600
5710
  module "add_url_to_runtime_config" {
5601
5711
  source = "../../../core/runtime-config/entry"
5602
5712
 
5603
- key_path = "apis.TestApi"
5604
- value = aws_api_gateway_stage.api_stage.invoke_url
5713
+ namespace = "connection"
5714
+ key = "apis"
5715
+ value = { "TestApi" = aws_api_gateway_stage.api_stage.invoke_url }
5605
5716
 
5606
5717
  depends_on = [aws_api_gateway_stage.api_stage]
5607
5718
  }
5608
5719
 
5720
+ module "appconfig" {
5721
+ source = "../../../core/runtime-config/appconfig"
5722
+
5723
+ application_name = "TestApi-runtime-config"
5724
+
5725
+ depends_on = [module.add_url_to_runtime_config]
5726
+ }
5727
+
5609
5728
  # Outputs
5610
5729
 
5611
5730
  # API Gateway Outputs (from core module)
@@ -6223,12 +6342,21 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
6223
6342
  module "add_url_to_runtime_config" {
6224
6343
  source = "../../../core/runtime-config/entry"
6225
6344
 
6226
- key_path = "apis.TestApi"
6227
- value = aws_api_gateway_stage.api_stage.invoke_url
6345
+ namespace = "connection"
6346
+ key = "apis"
6347
+ value = { "TestApi" = aws_api_gateway_stage.api_stage.invoke_url }
6228
6348
 
6229
6349
  depends_on = [aws_api_gateway_stage.api_stage]
6230
6350
  }
6231
6351
 
6352
+ module "appconfig" {
6353
+ source = "../../../core/runtime-config/appconfig"
6354
+
6355
+ application_name = "TestApi-runtime-config"
6356
+
6357
+ depends_on = [module.add_url_to_runtime_config]
6358
+ }
6359
+
6232
6360
  # Outputs
6233
6361
 
6234
6362
  # API Gateway Outputs (from core module)