@aws/nx-plugin 1.0.0-rc.49 → 1.0.0-rc.50

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 (41) hide show
  1. package/LICENSE-THIRD-PARTY +436 -29
  2. package/migrations.json +17 -1
  3. package/package.json +2 -1
  4. package/src/migrations/latest/modernize-function-props-cast/migration.d.ts +6 -0
  5. package/src/migrations/latest/modernize-function-props-cast/migration.js +66 -0
  6. package/src/migrations/latest/modernize-function-props-cast/migration.js.map +1 -0
  7. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.d.ts +6 -0
  8. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js +110 -0
  9. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +1 -0
  10. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.d.ts +6 -0
  11. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js +129 -0
  12. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
  13. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +1 -0
  14. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +25 -15
  15. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +1 -0
  16. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +26 -16
  17. package/src/terraform/project/files/application/scripts/bootstrap.ts.template +40 -1
  18. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +75 -45
  19. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +1 -0
  20. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +1 -0
  21. package/src/ts/nx-migration/files/migration.ts.template +6 -0
  22. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +1 -0
  23. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +43 -0
  24. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +11 -14
  25. package/src/utils/__snapshots__/shared-constructs.spec.ts.snap +21 -0
  26. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +12 -7
  27. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +13 -8
  28. package/src/utils/files/common/constructs/src/core/cloudfront.ts.template +14 -0
  29. package/src/utils/files/common/constructs/src/core/index.ts.template +1 -0
  30. package/src/utils/format.js +118 -240
  31. package/src/utils/format.js.map +1 -1
  32. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +7 -14
  33. package/src/utils/ruff.d.ts +59 -0
  34. package/src/utils/ruff.js +140 -0
  35. package/src/utils/ruff.js.map +1 -0
  36. package/src/utils/toml.d.ts +5 -0
  37. package/src/utils/toml.js +10 -0
  38. package/src/utils/toml.js.map +1 -1
  39. package/src/utils/warm-ruff-cache.d.ts +0 -8
  40. package/src/utils/warm-ruff-cache.js +0 -30
  41. package/src/utils/warm-ruff-cache.js.map +0 -1
@@ -380,6 +380,7 @@ import {
380
380
  IntegrationBuilder,
381
381
  RestApiIntegration,
382
382
  } from '../../core/api/utils.js';
383
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
383
384
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
384
385
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
385
386
  import { AppRouter, appRouter } from '@proj/test-api';
@@ -435,7 +436,7 @@ export class TestApi<
435
436
  return IntegrationBuilder.rest({
436
437
  pattern: 'isolated',
437
438
  operations: routerToOperations(appRouter),
438
- defaultIntegrationOptions: <FunctionProps>{
439
+ defaultIntegrationOptions: {
439
440
  runtime: Runtime.NODEJS_LATEST,
440
441
  handler: 'index.handler',
441
442
  code: Code.fromAsset(
@@ -448,7 +449,7 @@ export class TestApi<
448
449
  ),
449
450
  timeout: Duration.seconds(30),
450
451
  tracing: Tracing.ACTIVE,
451
- },
452
+ } as FunctionProps,
452
453
  buildDefaultIntegration: (op, props: FunctionProps) => {
453
454
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
454
455
  handler.addEnvironment(
@@ -507,7 +508,9 @@ export class TestApi<
507
508
  *
508
509
  * Configures the provided CloudFront distribution domains or origin strings
509
510
  * as the only permitted CORS origins in API Gateway preflight responses and the
510
- * AWS Lambda integrations.
511
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
512
+ * CloudFront distribution are included automatically alongside its default
513
+ * \`*.cloudfront.net\` domain.
511
514
  *
512
515
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
513
516
  */
@@ -518,12 +521,14 @@ export class TestApi<
518
521
  | { cloudFrontDistribution: Distribution }
519
522
  )[]
520
523
  ) {
521
- const allowedOrigins = origins.map((origin) =>
524
+ const allowedOrigins = origins.flatMap((origin) =>
522
525
  typeof origin === 'string'
523
- ? origin
524
- : 'cloudFrontDistribution' in origin
525
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
526
- : \`https://\${origin.distributionDomainName}\`,
526
+ ? [origin]
527
+ : findCloudFrontDomainNames(
528
+ 'cloudFrontDistribution' in origin
529
+ ? origin.cloudFrontDistribution
530
+ : origin,
531
+ ).map((domain) => \`https://\${domain}\`),
527
532
  );
528
533
 
529
534
  this.allowedOrigins = allowedOrigins;
@@ -592,6 +597,7 @@ import {
592
597
  HttpApiIntegration,
593
598
  IntegrationBuilder,
594
599
  } from '../../core/api/utils.js';
600
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
595
601
  import { HttpApi } from '../../core/api/http-api.js';
596
602
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
597
603
  import { AppRouter, appRouter } from '@proj/test-api';
@@ -640,7 +646,7 @@ export class TestApi<
640
646
  return IntegrationBuilder.http({
641
647
  pattern: 'isolated',
642
648
  operations: routerToOperations(appRouter),
643
- defaultIntegrationOptions: <FunctionProps>{
649
+ defaultIntegrationOptions: {
644
650
  runtime: Runtime.NODEJS_LATEST,
645
651
  handler: 'index.handler',
646
652
  code: Code.fromAsset(
@@ -653,7 +659,7 @@ export class TestApi<
653
659
  ),
654
660
  timeout: Duration.seconds(30),
655
661
  tracing: Tracing.ACTIVE,
656
- },
662
+ } as FunctionProps,
657
663
  buildDefaultIntegration: (op, props: FunctionProps) => {
658
664
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
659
665
  handler.addEnvironment(
@@ -709,6 +715,8 @@ export class TestApi<
709
715
  * as the only permitted CORS origins
710
716
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
711
717
  * integrations since the associated header is controlled by API Gateway v2.
718
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
719
+ * included automatically alongside its default \`*.cloudfront.net\` domain.
712
720
  *
713
721
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
714
722
  */
@@ -719,12 +727,14 @@ export class TestApi<
719
727
  | { cloudFrontDistribution: Distribution }
720
728
  )[]
721
729
  ) {
722
- const allowedOrigins = origins.map((origin) =>
730
+ const allowedOrigins = origins.flatMap((origin) =>
723
731
  typeof origin === 'string'
724
- ? origin
725
- : 'cloudFrontDistribution' in origin
726
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
727
- : \`https://\${origin.distributionDomainName}\`,
732
+ ? [origin]
733
+ : findCloudFrontDomainNames(
734
+ 'cloudFrontDistribution' in origin
735
+ ? origin.cloudFrontDistribution
736
+ : origin,
737
+ ).map((domain) => \`https://\${domain}\`),
728
738
  );
729
739
 
730
740
  const cfnApi = this.api.node.defaultChild;
@@ -804,6 +814,7 @@ import {
804
814
  IntegrationBuilder,
805
815
  RestApiIntegration,
806
816
  } from '../../core/api/utils.js';
817
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
807
818
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
808
819
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
809
820
  import { AppRouter, appRouter } from '@proj/test-api';
@@ -853,7 +864,7 @@ export class TestApi<
853
864
  return IntegrationBuilder.rest({
854
865
  pattern: 'isolated',
855
866
  operations: routerToOperations(appRouter),
856
- defaultIntegrationOptions: <FunctionProps>{
867
+ defaultIntegrationOptions: {
857
868
  runtime: Runtime.NODEJS_LATEST,
858
869
  handler: 'index.handler',
859
870
  code: Code.fromAsset(
@@ -866,7 +877,7 @@ export class TestApi<
866
877
  ),
867
878
  timeout: Duration.seconds(30),
868
879
  tracing: Tracing.ACTIVE,
869
- },
880
+ } as FunctionProps,
870
881
  buildDefaultIntegration: (op, props: FunctionProps) => {
871
882
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
872
883
  handler.addEnvironment(
@@ -941,7 +952,9 @@ export class TestApi<
941
952
  *
942
953
  * Configures the provided CloudFront distribution domains or origin strings
943
954
  * as the only permitted CORS origins in API Gateway preflight responses and the
944
- * AWS Lambda integrations.
955
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
956
+ * CloudFront distribution are included automatically alongside its default
957
+ * \`*.cloudfront.net\` domain.
945
958
  *
946
959
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
947
960
  */
@@ -952,12 +965,14 @@ export class TestApi<
952
965
  | { cloudFrontDistribution: Distribution }
953
966
  )[]
954
967
  ) {
955
- const allowedOrigins = origins.map((origin) =>
968
+ const allowedOrigins = origins.flatMap((origin) =>
956
969
  typeof origin === 'string'
957
- ? origin
958
- : 'cloudFrontDistribution' in origin
959
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
960
- : \`https://\${origin.distributionDomainName}\`,
970
+ ? [origin]
971
+ : findCloudFrontDomainNames(
972
+ 'cloudFrontDistribution' in origin
973
+ ? origin.cloudFrontDistribution
974
+ : origin,
975
+ ).map((domain) => \`https://\${domain}\`),
961
976
  );
962
977
 
963
978
  this.allowedOrigins = allowedOrigins;
@@ -1024,6 +1039,7 @@ import {
1024
1039
  HttpApiIntegration,
1025
1040
  IntegrationBuilder,
1026
1041
  } from '../../core/api/utils.js';
1042
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
1027
1043
  import { HttpApi } from '../../core/api/http-api.js';
1028
1044
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
1029
1045
  import { AppRouter, appRouter } from '@proj/test-api';
@@ -1065,7 +1081,7 @@ export class TestApi<
1065
1081
  return IntegrationBuilder.http({
1066
1082
  pattern: 'isolated',
1067
1083
  operations: routerToOperations(appRouter),
1068
- defaultIntegrationOptions: <FunctionProps>{
1084
+ defaultIntegrationOptions: {
1069
1085
  runtime: Runtime.NODEJS_LATEST,
1070
1086
  handler: 'index.handler',
1071
1087
  code: Code.fromAsset(
@@ -1078,7 +1094,7 @@ export class TestApi<
1078
1094
  ),
1079
1095
  timeout: Duration.seconds(30),
1080
1096
  tracing: Tracing.ACTIVE,
1081
- },
1097
+ } as FunctionProps,
1082
1098
  buildDefaultIntegration: (op, props: FunctionProps) => {
1083
1099
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1084
1100
  handler.addEnvironment(
@@ -1153,6 +1169,8 @@ export class TestApi<
1153
1169
  * as the only permitted CORS origins
1154
1170
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
1155
1171
  * integrations since the associated header is controlled by API Gateway v2.
1172
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
1173
+ * included automatically alongside its default \`*.cloudfront.net\` domain.
1156
1174
  *
1157
1175
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
1158
1176
  */
@@ -1163,12 +1181,14 @@ export class TestApi<
1163
1181
  | { cloudFrontDistribution: Distribution }
1164
1182
  )[]
1165
1183
  ) {
1166
- const allowedOrigins = origins.map((origin) =>
1184
+ const allowedOrigins = origins.flatMap((origin) =>
1167
1185
  typeof origin === 'string'
1168
- ? origin
1169
- : 'cloudFrontDistribution' in origin
1170
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
1171
- : \`https://\${origin.distributionDomainName}\`,
1186
+ ? [origin]
1187
+ : findCloudFrontDomainNames(
1188
+ 'cloudFrontDistribution' in origin
1189
+ ? origin.cloudFrontDistribution
1190
+ : origin,
1191
+ ).map((domain) => \`https://\${domain}\`),
1172
1192
  );
1173
1193
 
1174
1194
  const cfnApi = this.api.node.defaultChild;
@@ -1391,6 +1411,7 @@ import {
1391
1411
  HttpApiIntegration,
1392
1412
  IntegrationBuilder,
1393
1413
  } from '../../core/api/utils.js';
1414
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
1394
1415
  import { HttpApi } from '../../core/api/http-api.js';
1395
1416
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
1396
1417
  import { AppRouter, appRouter } from '@proj/test-api';
@@ -1432,7 +1453,7 @@ export class TestApi<
1432
1453
  return IntegrationBuilder.http({
1433
1454
  pattern: 'isolated',
1434
1455
  operations: routerToOperations(appRouter),
1435
- defaultIntegrationOptions: <FunctionProps>{
1456
+ defaultIntegrationOptions: {
1436
1457
  runtime: Runtime.NODEJS_LATEST,
1437
1458
  handler: 'index.handler',
1438
1459
  code: Code.fromAsset(
@@ -1445,7 +1466,7 @@ export class TestApi<
1445
1466
  ),
1446
1467
  timeout: Duration.seconds(30),
1447
1468
  tracing: Tracing.ACTIVE,
1448
- },
1469
+ } as FunctionProps,
1449
1470
  buildDefaultIntegration: (op, props: FunctionProps) => {
1450
1471
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1451
1472
  handler.addEnvironment(
@@ -1495,6 +1516,8 @@ export class TestApi<
1495
1516
  * as the only permitted CORS origins
1496
1517
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
1497
1518
  * integrations since the associated header is controlled by API Gateway v2.
1519
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
1520
+ * included automatically alongside its default \`*.cloudfront.net\` domain.
1498
1521
  *
1499
1522
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
1500
1523
  */
@@ -1505,12 +1528,14 @@ export class TestApi<
1505
1528
  | { cloudFrontDistribution: Distribution }
1506
1529
  )[]
1507
1530
  ) {
1508
- const allowedOrigins = origins.map((origin) =>
1531
+ const allowedOrigins = origins.flatMap((origin) =>
1509
1532
  typeof origin === 'string'
1510
- ? origin
1511
- : 'cloudFrontDistribution' in origin
1512
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
1513
- : \`https://\${origin.distributionDomainName}\`,
1533
+ ? [origin]
1534
+ : findCloudFrontDomainNames(
1535
+ 'cloudFrontDistribution' in origin
1536
+ ? origin.cloudFrontDistribution
1537
+ : origin,
1538
+ ).map((domain) => \`https://\${domain}\`),
1514
1539
  );
1515
1540
 
1516
1541
  const cfnApi = this.api.node.defaultChild;
@@ -2421,6 +2446,7 @@ import {
2421
2446
  IntegrationBuilder,
2422
2447
  RestApiIntegration,
2423
2448
  } from '../../core/api/utils.js';
2449
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
2424
2450
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
2425
2451
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
2426
2452
  import { AppRouter, appRouter } from '@proj/test-api';
@@ -2470,7 +2496,7 @@ export class TestApi<
2470
2496
  return IntegrationBuilder.rest({
2471
2497
  pattern: 'isolated',
2472
2498
  operations: routerToOperations(appRouter),
2473
- defaultIntegrationOptions: <FunctionProps>{
2499
+ defaultIntegrationOptions: {
2474
2500
  runtime: Runtime.NODEJS_LATEST,
2475
2501
  handler: 'index.handler',
2476
2502
  code: Code.fromAsset(
@@ -2483,7 +2509,7 @@ export class TestApi<
2483
2509
  ),
2484
2510
  timeout: Duration.seconds(30),
2485
2511
  tracing: Tracing.ACTIVE,
2486
- },
2512
+ } as FunctionProps,
2487
2513
  buildDefaultIntegration: (op, props: FunctionProps) => {
2488
2514
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
2489
2515
  handler.addEnvironment(
@@ -2536,7 +2562,9 @@ export class TestApi<
2536
2562
  *
2537
2563
  * Configures the provided CloudFront distribution domains or origin strings
2538
2564
  * as the only permitted CORS origins in API Gateway preflight responses and the
2539
- * AWS Lambda integrations.
2565
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
2566
+ * CloudFront distribution are included automatically alongside its default
2567
+ * \`*.cloudfront.net\` domain.
2540
2568
  *
2541
2569
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
2542
2570
  */
@@ -2547,12 +2575,14 @@ export class TestApi<
2547
2575
  | { cloudFrontDistribution: Distribution }
2548
2576
  )[]
2549
2577
  ) {
2550
- const allowedOrigins = origins.map((origin) =>
2578
+ const allowedOrigins = origins.flatMap((origin) =>
2551
2579
  typeof origin === 'string'
2552
- ? origin
2553
- : 'cloudFrontDistribution' in origin
2554
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
2555
- : \`https://\${origin.distributionDomainName}\`,
2580
+ ? [origin]
2581
+ : findCloudFrontDomainNames(
2582
+ 'cloudFrontDistribution' in origin
2583
+ ? origin.cloudFrontDistribution
2584
+ : origin,
2585
+ ).map((domain) => \`https://\${domain}\`),
2556
2586
  );
2557
2587
 
2558
2588
  this.allowedOrigins = allowedOrigins;
@@ -747,6 +747,7 @@ exports[`ts#agent generator > should match snapshot for BedrockAgentCoreRuntime
747
747
  exports[`ts#agent generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > core-index.ts 1`] = `
748
748
  "export * from './app.js';
749
749
  export * from './checkov.js';
750
+ export * from './cloudfront.js';
750
751
  export * from './runtime-config.js';
751
752
  export * from './workspace.js';
752
753
  "
@@ -8,6 +8,7 @@ exports[`ts#mcp-server generator > should match snapshot for BedrockAgentCoreRun
8
8
  exports[`ts#mcp-server generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > core-index.ts 1`] = `
9
9
  "export * from './app.js';
10
10
  export * from './checkov.js';
11
+ export * from './cloudfront.js';
11
12
  export * from './runtime-config.js';
12
13
  export * from './workspace.js';
13
14
  "
@@ -13,6 +13,9 @@ import { formatFilesInSubtree } from '<%- formatImportPath %>';
13
13
  * - `nextSteps` and `agentContext`: https://nx.dev/docs/reference/devkit/MigrationReturnObject
14
14
  *
15
15
  * Guardrails:
16
+ * - Transform source with GritQL (`applyGritQL`, `matchGritQL`), not regexes or
17
+ * string replacements: it matches the AST, so it holds up against however the
18
+ * user's copy has been formatted. Use `updateJson` for JSON.
16
19
  * - Pattern-match before writing: skip files that have diverged from the shape
17
20
  * your generators produce, and report them via `agentContext` so the prompt
18
21
  * can pick them up, rather than clobbering the user's changes.
@@ -27,6 +30,9 @@ import { formatFilesInSubtree } from '<%- formatImportPath %>';
27
30
  * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject
28
31
  *
29
32
  * Guardrails:
33
+ * - Transform source with GritQL (`applyGritQL`, `matchGritQL`), not regexes or
34
+ * string replacements: it matches the AST, so it holds up against however the
35
+ * user's copy has been formatted. Use `updateJson` for JSON.
30
36
  * - Pattern-match before writing: skip files that have diverged from the shape
31
37
  * your generators produce and report them via `nextSteps`, or consider a
32
38
  * hybrid migration, rather than clobbering the user's changes.
@@ -4736,6 +4736,7 @@ exports[`ts#rdb generator > should generate the aurora shared construct 6`] = `
4736
4736
  "export * from './rdb/aurora.js';
4737
4737
  export * from './app.js';
4738
4738
  export * from './checkov.js';
4739
+ export * from './cloudfront.js';
4739
4740
  export * from './runtime-config.js';
4740
4741
  export * from './workspace.js';
4741
4742
  "
@@ -1391,10 +1391,31 @@ export const suppressRules = (
1391
1391
  "
1392
1392
  `;
1393
1393
 
1394
+ exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > packages/common/constructs/src/core/cloudfront.ts 1`] = `
1395
+ "import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
1396
+
1397
+ /**
1398
+ * Finds the domain names associated with a CloudFront distribution.
1399
+ *
1400
+ * Includes the distribution's default \`*.cloudfront.net\` domain name plus any custom
1401
+ * domain names (aliases) configured on it.
1402
+ */
1403
+ export const findCloudFrontDomainNames = (
1404
+ distribution: Distribution,
1405
+ ): string[] => {
1406
+ const cfnDistribution = distribution.node.defaultChild as CfnDistribution;
1407
+ const distributionConfig =
1408
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
1409
+ return [distribution.domainName, ...(distributionConfig.aliases ?? [])];
1410
+ };
1411
+ "
1412
+ `;
1413
+
1394
1414
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > packages/common/constructs/src/core/index.ts 1`] = `
1395
1415
  "export * from './static-website.js';
1396
1416
  export * from './app.js';
1397
1417
  export * from './checkov.js';
1418
+ export * from './cloudfront.js';
1398
1419
  export * from './runtime-config.js';
1399
1420
  export * from './workspace.js';
1400
1421
  "
@@ -3180,10 +3201,31 @@ export const suppressRules = (
3180
3201
  "
3181
3202
  `;
3182
3203
 
3204
+ exports[`react-website generator > Tanstack router integration > should generate website with router correctly > packages/common/constructs/src/core/cloudfront.ts 1`] = `
3205
+ "import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
3206
+
3207
+ /**
3208
+ * Finds the domain names associated with a CloudFront distribution.
3209
+ *
3210
+ * Includes the distribution's default \`*.cloudfront.net\` domain name plus any custom
3211
+ * domain names (aliases) configured on it.
3212
+ */
3213
+ export const findCloudFrontDomainNames = (
3214
+ distribution: Distribution,
3215
+ ): string[] => {
3216
+ const cfnDistribution = distribution.node.defaultChild as CfnDistribution;
3217
+ const distributionConfig =
3218
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
3219
+ return [distribution.domainName, ...(distributionConfig.aliases ?? [])];
3220
+ };
3221
+ "
3222
+ `;
3223
+
3183
3224
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > packages/common/constructs/src/core/index.ts 1`] = `
3184
3225
  "export * from './static-website.js';
3185
3226
  export * from './app.js';
3186
3227
  export * from './checkov.js';
3228
+ export * from './cloudfront.js';
3187
3229
  export * from './runtime-config.js';
3188
3230
  export * from './workspace.js';
3189
3231
  "
@@ -5039,6 +5081,7 @@ exports[`react-website generator > should generate shared constructs > common/co
5039
5081
  "export * from './static-website.js';
5040
5082
  export * from './app.js';
5041
5083
  export * from './checkov.js';
5084
+ export * from './cloudfront.js';
5042
5085
  export * from './runtime-config.js';
5043
5086
  export * from './workspace.js';
5044
5087
  "
@@ -80,6 +80,7 @@ exports[`cognito-auth generator > should generate files > identity-index 1`] = `
80
80
  "export * from './user-identity.js';
81
81
  export * from './app.js';
82
82
  export * from './checkov.js';
83
+ export * from './cloudfront.js';
83
84
  export * from './runtime-config.js';
84
85
  export * from './workspace.js';
85
86
  "
@@ -118,7 +119,8 @@ import {
118
119
  import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
119
120
  import { Construct } from 'constructs';
120
121
  import { RuntimeConfig } from './runtime-config.js';
121
- import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
122
+ import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
123
+ import { findCloudFrontDomainNames } from './cloudfront.js';
122
124
  import { suppressRules } from './checkov.js';
123
125
 
124
126
  const WEB_CLIENT_ID = 'WebClient';
@@ -334,7 +336,13 @@ export class UserIdentity extends Construct {
334
336
  const lazilyComputedCallbackUrls = Lazy.list({
335
337
  produce: () =>
336
338
  ['http://localhost:4200', 'http://localhost:4300'].concat(
337
- this.findCloudFrontDomainNames().map((domain) => \`https://\${domain}\`),
339
+ Stack.of(this)
340
+ .node.findAll()
341
+ .filter(
342
+ (child): child is Distribution => child instanceof Distribution,
343
+ )
344
+ .flatMap(findCloudFrontDomainNames)
345
+ .map((domain) => \`https://\${domain}\`),
338
346
  ),
339
347
  });
340
348
 
@@ -383,18 +391,6 @@ export class UserIdentity extends Construct {
383
391
  useCognitoProvidedValues: true,
384
392
  }).node.addDependency(userPoolClient, userPool, userPoolDomain);
385
393
  };
386
-
387
- // Includes each distribution's default domain name plus any custom domain names (aliases) configured on it.
388
- private findCloudFrontDomainNames = (): string[] =>
389
- Stack.of(this)
390
- .node.findAll()
391
- .filter((child): child is Distribution => child instanceof Distribution)
392
- .flatMap((d) => {
393
- const cfnDistribution = d.node.defaultChild as CfnDistribution;
394
- const distributionConfig =
395
- cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
396
- return [d.domainName, ...(distributionConfig.aliases ?? [])];
397
- });
398
394
  }
399
395
  "
400
396
  `;
@@ -422,6 +418,7 @@ exports[`cognito-auth generator > should update shared constructs index.ts > com
422
418
  "export * from './user-identity.js';
423
419
  export * from './app.js';
424
420
  export * from './checkov.js';
421
+ export * from './cloudfront.js';
425
422
  export * from './runtime-config.js';
426
423
  export * from './workspace.js';
427
424
  "
@@ -79,9 +79,30 @@ export const suppressRules = (
79
79
  "
80
80
  `;
81
81
 
82
+ exports[`shared-constructs utils > sharedConstructsGenerator > should generate shared constructs when they do not exist > packages/common/constructs/src/core/cloudfront.ts 1`] = `
83
+ "import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
84
+
85
+ /**
86
+ * Finds the domain names associated with a CloudFront distribution.
87
+ *
88
+ * Includes the distribution's default \`*.cloudfront.net\` domain name plus any custom
89
+ * domain names (aliases) configured on it.
90
+ */
91
+ export const findCloudFrontDomainNames = (
92
+ distribution: Distribution,
93
+ ): string[] => {
94
+ const cfnDistribution = distribution.node.defaultChild as CfnDistribution;
95
+ const distributionConfig =
96
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
97
+ return [distribution.domainName, ...(distributionConfig.aliases ?? [])];
98
+ };
99
+ "
100
+ `;
101
+
82
102
  exports[`shared-constructs utils > sharedConstructsGenerator > should generate shared constructs when they do not exist > packages/common/constructs/src/core/index.ts 1`] = `
83
103
  "export * from './app.js';
84
104
  export * from './checkov.js';
105
+ export * from './cloudfront.js';
85
106
  export * from './runtime-config.js';
86
107
  export * from './workspace.js';
87
108
  "
@@ -42,6 +42,7 @@ import {
42
42
  HttpApiIntegration,
43
43
  IntegrationBuilder,
44
44
  } from '../../core/api/utils<% if (esm) { %>.js<% } %>';
45
+ import { findCloudFrontDomainNames } from '../../core/cloudfront<% if (esm) { %>.js<% } %>';
45
46
  import { HttpApi } from '../../core/api/http-api<% if (esm) { %>.js<% } %>';
46
47
  <%_ if (backend.type === 'trpc') { _%>
47
48
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils<% if (esm) { %>.js<% } %>';
@@ -108,7 +109,7 @@ export class <%= apiNameClassName %><
108
109
  <%_ } else { _%>
109
110
  operations: OPERATION_DETAILS,
110
111
  <%_ } _%>
111
- defaultIntegrationOptions: <FunctionProps>{
112
+ defaultIntegrationOptions: {
112
113
  <%_ if (['trpc', 'smithy'].includes(backend.type)) { _%>
113
114
  runtime: Runtime.NODEJS_LATEST,
114
115
  handler: 'index.handler',
@@ -137,7 +138,7 @@ export class <%= apiNameClassName %><
137
138
  <%_ if (backend.type === 'fastapi') { _%>
138
139
  snapStart: SnapStartConf.ON_PUBLISHED_VERSIONS,
139
140
  <%_ } _%>
140
- },
141
+ } as FunctionProps,
141
142
  buildDefaultIntegration: (op, props: FunctionProps) => {
142
143
  <%_ const lambdaTarget = backend.type === 'fastapi' ? 'handler.currentVersion' : 'handler'; _%>
143
144
  <%_ const integrationOptions = backend.integrationPattern === 'shared' ? ', { scopePermissionToRoute: false }' : ''; _%>
@@ -245,18 +246,22 @@ export class <%= apiNameClassName %><
245
246
  * as the only permitted CORS origins
246
247
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
247
248
  * integrations since the associated header is controlled by API Gateway v2.
249
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
250
+ * included automatically alongside its default `*.cloudfront.net` domain.
248
251
  *
249
252
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
250
253
  */
251
254
  public restrictCorsTo(
252
255
  ...origins: (string | Distribution | { cloudFrontDistribution: Distribution })[]
253
256
  ) {
254
- const allowedOrigins = origins.map((origin) =>
257
+ const allowedOrigins = origins.flatMap((origin) =>
255
258
  typeof origin === 'string'
256
- ? origin
257
- : 'cloudFrontDistribution' in origin
258
- ? `https://${origin.cloudFrontDistribution.distributionDomainName}`
259
- : `https://${origin.distributionDomainName}`,
259
+ ? [origin]
260
+ : findCloudFrontDomainNames(
261
+ 'cloudFrontDistribution' in origin
262
+ ? origin.cloudFrontDistribution
263
+ : origin,
264
+ ).map((domain) => `https://${domain}`),
260
265
  );
261
266
 
262
267
  const cfnApi = this.api.node.defaultChild;
@@ -45,6 +45,7 @@ import {
45
45
  IntegrationBuilder,
46
46
  RestApiIntegration,
47
47
  } from '../../core/api/utils<% if (esm) { %>.js<% } %>';
48
+ import { findCloudFrontDomainNames } from '../../core/cloudfront<% if (esm) { %>.js<% } %>';
48
49
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api<% if (esm) { %>.js<% } %>';
49
50
  <%_ if (backend.type === 'trpc') { _%>
50
51
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils<% if (esm) { %>.js<% } %>';
@@ -118,7 +119,7 @@ export class <%= apiNameClassName %><
118
119
  <%_ } else { _%>
119
120
  operations: OPERATION_DETAILS,
120
121
  <%_ } _%>
121
- defaultIntegrationOptions: <FunctionProps>{
122
+ defaultIntegrationOptions: {
122
123
  <%_ if (['trpc', 'smithy'].includes(backend.type)) { _%>
123
124
  runtime: Runtime.NODEJS_LATEST,
124
125
  handler: 'index.handler',
@@ -147,7 +148,7 @@ export class <%= apiNameClassName %><
147
148
  <%_ if (backend.type === 'fastapi') { _%>
148
149
  snapStart: SnapStartConf.ON_PUBLISHED_VERSIONS,
149
150
  <%_ } _%>
150
- },
151
+ } as FunctionProps,
151
152
  buildDefaultIntegration: (op, props: FunctionProps) => {
152
153
  <%_ const lambdaTarget = backend.type === 'fastapi' ? 'handler.currentVersion' : 'handler'; _%>
153
154
  <%_
@@ -284,19 +285,23 @@ export class <%= apiNameClassName %><
284
285
  *
285
286
  * Configures the provided CloudFront distribution domains or origin strings
286
287
  * as the only permitted CORS origins in API Gateway preflight responses and the
287
- * AWS Lambda integrations.
288
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
289
+ * CloudFront distribution are included automatically alongside its default
290
+ * `*.cloudfront.net` domain.
288
291
  *
289
292
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
290
293
  */
291
294
  public restrictCorsTo(
292
295
  ...origins: (string | Distribution | { cloudFrontDistribution: Distribution })[]
293
296
  ) {
294
- const allowedOrigins = origins.map((origin) =>
297
+ const allowedOrigins = origins.flatMap((origin) =>
295
298
  typeof origin === 'string'
296
- ? origin
297
- : 'cloudFrontDistribution' in origin
298
- ? `https://${origin.cloudFrontDistribution.distributionDomainName}`
299
- : `https://${origin.distributionDomainName}`,
299
+ ? [origin]
300
+ : findCloudFrontDomainNames(
301
+ 'cloudFrontDistribution' in origin
302
+ ? origin.cloudFrontDistribution
303
+ : origin,
304
+ ).map((domain) => `https://${domain}`),
300
305
  );
301
306
 
302
307
  this.allowedOrigins = allowedOrigins;
@@ -0,0 +1,14 @@
1
+ import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
2
+
3
+ /**
4
+ * Finds the domain names associated with a CloudFront distribution.
5
+ *
6
+ * Includes the distribution's default `*.cloudfront.net` domain name plus any custom
7
+ * domain names (aliases) configured on it.
8
+ */
9
+ export const findCloudFrontDomainNames = (distribution: Distribution): string[] => {
10
+ const cfnDistribution = distribution.node.defaultChild as CfnDistribution;
11
+ const distributionConfig =
12
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
13
+ return [distribution.domainName, ...(distributionConfig.aliases ?? [])];
14
+ };