@aws/nx-plugin 0.80.1 → 0.81.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/LICENSE-THIRD-PARTY +28 -299
- package/package.json +1 -1
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +368 -86
- package/src/py/fast-api/generator.js +3 -0
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/schema.d.ts +1 -0
- package/src/py/fast-api/schema.json +22 -0
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +12 -8
- package/src/smithy/ts/api/generator.js +3 -0
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/smithy/ts/api/schema.d.ts +4 -0
- package/src/smithy/ts/api/schema.json +22 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +392 -102
- package/src/trpc/backend/generator.js +20 -1
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.ts +1 -0
- package/src/trpc/backend/schema.json +22 -0
- package/src/utils/api-constructs/api-constructs.d.ts +1 -0
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +18 -10
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +28 -16
- package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +25 -5
- package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +32 -8
- package/src/utils/api-constructs/files/cdk/core/api/utils/utils.ts.template +151 -32
|
@@ -246,7 +246,11 @@ def test_main():
|
|
|
246
246
|
exports[`fastapi project generator > should set up shared constructs for http > http-api.ts 1`] = `
|
|
247
247
|
"import { Construct } from 'constructs';
|
|
248
248
|
import { RuntimeConfig } from '../runtime-config.js';
|
|
249
|
-
import {
|
|
249
|
+
import {
|
|
250
|
+
ApiIntegrations,
|
|
251
|
+
HttpApiIntegration,
|
|
252
|
+
OperationDetails,
|
|
253
|
+
} from './utils.js';
|
|
250
254
|
import { CfnOutput } from 'aws-cdk-lib';
|
|
251
255
|
import {
|
|
252
256
|
HttpApi as _HttpApi,
|
|
@@ -265,7 +269,7 @@ import { suppressRules } from '../checkov.js';
|
|
|
265
269
|
* @template TOperation - String literal type representing operation names
|
|
266
270
|
*/
|
|
267
271
|
export interface HttpApiProps<
|
|
268
|
-
TIntegrations extends
|
|
272
|
+
TIntegrations extends ApiIntegrations<TOperation, HttpApiIntegration>,
|
|
269
273
|
TOperation extends string,
|
|
270
274
|
> extends _HttpApiProps {
|
|
271
275
|
/**
|
|
@@ -295,7 +299,7 @@ export interface HttpApiProps<
|
|
|
295
299
|
*/
|
|
296
300
|
export class HttpApi<
|
|
297
301
|
TOperation extends string,
|
|
298
|
-
TIntegrations extends
|
|
302
|
+
TIntegrations extends ApiIntegrations<TOperation, HttpApiIntegration>,
|
|
299
303
|
> extends Construct {
|
|
300
304
|
/** The underlying CDK HttpApi instance */
|
|
301
305
|
public readonly api: _HttpApi;
|
|
@@ -345,16 +349,32 @@ export class HttpApi<
|
|
|
345
349
|
},
|
|
346
350
|
});
|
|
347
351
|
|
|
352
|
+
// Resolve the integration for a given operation.
|
|
353
|
+
// If the operation has a dedicated integration, use it; otherwise fall back to $router.
|
|
354
|
+
const resolveIntegration = (op: TOperation): HttpApiIntegration => {
|
|
355
|
+
const record = integrations as Record<string, HttpApiIntegration>;
|
|
356
|
+
if (op in record) {
|
|
357
|
+
return record[op];
|
|
358
|
+
}
|
|
359
|
+
if ('$router' in record) {
|
|
360
|
+
return record['$router'];
|
|
361
|
+
}
|
|
362
|
+
throw new Error(
|
|
363
|
+
\`No integration found for operation '\${op}' and no $router integration available\`,
|
|
364
|
+
);
|
|
365
|
+
};
|
|
366
|
+
|
|
348
367
|
// Create API resources and methods for each operation
|
|
349
368
|
(Object.entries(operations) as [TOperation, OperationDetails][]).map(
|
|
350
369
|
([op, details]) => {
|
|
370
|
+
const integration = resolveIntegration(op);
|
|
351
371
|
this.api.addRoutes({
|
|
352
372
|
path: details.path.startsWith('/')
|
|
353
373
|
? details.path
|
|
354
374
|
: \`/\${details.path}\`,
|
|
355
375
|
methods: [details.method as HttpMethod],
|
|
356
|
-
integration:
|
|
357
|
-
...
|
|
376
|
+
integration: integration.integration,
|
|
377
|
+
...integration.options,
|
|
358
378
|
});
|
|
359
379
|
},
|
|
360
380
|
);
|
|
@@ -399,6 +419,7 @@ import { HttpIamAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
|
|
|
399
419
|
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
400
420
|
import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam';
|
|
401
421
|
import {
|
|
422
|
+
ApiIntegrations,
|
|
402
423
|
HttpApiIntegration,
|
|
403
424
|
IntegrationBuilder,
|
|
404
425
|
} from '../../core/api/utils.js';
|
|
@@ -414,7 +435,7 @@ import {
|
|
|
414
435
|
* @template TIntegrations - Map of operation names to their integrations
|
|
415
436
|
*/
|
|
416
437
|
export interface TestApiProps<
|
|
417
|
-
TIntegrations extends
|
|
438
|
+
TIntegrations extends ApiIntegrations<Operations, HttpApiIntegration>,
|
|
418
439
|
> {
|
|
419
440
|
/**
|
|
420
441
|
* Map of operation names to their API Gateway integrations
|
|
@@ -428,7 +449,7 @@ export interface TestApiProps<
|
|
|
428
449
|
* @template TIntegrations - Map of operation names to their integrations
|
|
429
450
|
*/
|
|
430
451
|
export class TestApi<
|
|
431
|
-
TIntegrations extends
|
|
452
|
+
TIntegrations extends ApiIntegrations<Operations, HttpApiIntegration>,
|
|
432
453
|
> extends HttpApi<Operations, TIntegrations> {
|
|
433
454
|
/**
|
|
434
455
|
* Creates default integrations for all operations, which implement each operation as
|
|
@@ -439,8 +460,9 @@ export class TestApi<
|
|
|
439
460
|
*/
|
|
440
461
|
public static defaultIntegrations = (scope: Construct) => {
|
|
441
462
|
return IntegrationBuilder.http({
|
|
463
|
+
pattern: 'isolated',
|
|
442
464
|
operations: OPERATION_DETAILS,
|
|
443
|
-
defaultIntegrationOptions: {
|
|
465
|
+
defaultIntegrationOptions: <FunctionProps>{
|
|
444
466
|
runtime: Runtime.PYTHON_3_12,
|
|
445
467
|
handler: 'run.sh',
|
|
446
468
|
code: Code.fromAsset(
|
|
@@ -460,7 +482,7 @@ export class TestApi<
|
|
|
460
482
|
AWS_LWA_INVOKE_MODE: 'buffered',
|
|
461
483
|
AWS_LAMBDA_EXEC_WRAPPER: '/opt/bootstrap',
|
|
462
484
|
},
|
|
463
|
-
}
|
|
485
|
+
},
|
|
464
486
|
buildDefaultIntegration: (op, props: FunctionProps) => {
|
|
465
487
|
const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
|
|
466
488
|
const stack = Stack.of(scope);
|
|
@@ -616,20 +638,46 @@ export interface HttpApiIntegration {
|
|
|
616
638
|
}
|
|
617
639
|
|
|
618
640
|
/**
|
|
619
|
-
*
|
|
641
|
+
* Common options shared by all IntegrationBuilder configurations
|
|
620
642
|
*/
|
|
621
|
-
|
|
643
|
+
interface IntegrationBuilderPropsBase<
|
|
622
644
|
TOperation extends string,
|
|
623
|
-
TBaseIntegration,
|
|
624
645
|
TDefaultIntegrationProps extends object,
|
|
625
|
-
TDefaultIntegration extends TBaseIntegration,
|
|
626
646
|
> {
|
|
627
647
|
/** Map of operation names to their API path and HTTP method details */
|
|
628
648
|
operations: Record<TOperation, OperationDetails>;
|
|
629
649
|
|
|
630
650
|
/** Default configuration options for integrations */
|
|
631
651
|
defaultIntegrationOptions: TDefaultIntegrationProps;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Options for constructing an IntegrationBuilder with a shared integration pattern.
|
|
656
|
+
* A single default integration is built once (for '$router') and reused for all operations.
|
|
657
|
+
*/
|
|
658
|
+
interface SharedIntegrationBuilderProps<
|
|
659
|
+
TOperation extends string,
|
|
660
|
+
TDefaultIntegrationProps extends object,
|
|
661
|
+
TDefaultIntegration,
|
|
662
|
+
> extends IntegrationBuilderPropsBase<TOperation, TDefaultIntegrationProps> {
|
|
663
|
+
pattern: 'shared';
|
|
664
|
+
/** Function to create a default integration for the shared router */
|
|
665
|
+
buildDefaultIntegration: (
|
|
666
|
+
op: '$router',
|
|
667
|
+
props: TDefaultIntegrationProps,
|
|
668
|
+
) => TDefaultIntegration;
|
|
669
|
+
}
|
|
632
670
|
|
|
671
|
+
/**
|
|
672
|
+
* Options for constructing an IntegrationBuilder with an isolated integration pattern.
|
|
673
|
+
* A separate default integration is built per operation.
|
|
674
|
+
*/
|
|
675
|
+
interface IsolatedIntegrationBuilderProps<
|
|
676
|
+
TOperation extends string,
|
|
677
|
+
TDefaultIntegrationProps extends object,
|
|
678
|
+
TDefaultIntegration,
|
|
679
|
+
> extends IntegrationBuilderPropsBase<TOperation, TDefaultIntegrationProps> {
|
|
680
|
+
pattern: 'isolated';
|
|
633
681
|
/** Function to create a default integration for an operation */
|
|
634
682
|
buildDefaultIntegration: (
|
|
635
683
|
op: TOperation,
|
|
@@ -637,6 +685,71 @@ export interface IntegrationBuilderProps<
|
|
|
637
685
|
) => TDefaultIntegration;
|
|
638
686
|
}
|
|
639
687
|
|
|
688
|
+
/**
|
|
689
|
+
* Options for constructing an IntegrationBuilder
|
|
690
|
+
*/
|
|
691
|
+
export type IntegrationBuilderProps<
|
|
692
|
+
TOperation extends string,
|
|
693
|
+
TBaseIntegration,
|
|
694
|
+
TDefaultIntegrationProps extends object,
|
|
695
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
696
|
+
> =
|
|
697
|
+
| SharedIntegrationBuilderProps<
|
|
698
|
+
TOperation,
|
|
699
|
+
TDefaultIntegrationProps,
|
|
700
|
+
TDefaultIntegration
|
|
701
|
+
>
|
|
702
|
+
| IsolatedIntegrationBuilderProps<
|
|
703
|
+
TOperation,
|
|
704
|
+
TDefaultIntegrationProps,
|
|
705
|
+
TDefaultIntegration
|
|
706
|
+
>;
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Extracts the IntegrationBuilderProps variant matching the given pattern.
|
|
710
|
+
*/
|
|
711
|
+
type IntegrationBuilderPropsForPattern<
|
|
712
|
+
TOperation extends string,
|
|
713
|
+
TBaseIntegration,
|
|
714
|
+
TDefaultIntegrationProps extends object,
|
|
715
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
716
|
+
TPattern extends 'shared' | 'isolated',
|
|
717
|
+
> = Extract<
|
|
718
|
+
IntegrationBuilderProps<
|
|
719
|
+
TOperation,
|
|
720
|
+
TBaseIntegration,
|
|
721
|
+
TDefaultIntegrationProps,
|
|
722
|
+
TDefaultIntegration
|
|
723
|
+
>,
|
|
724
|
+
{ pattern: TPattern }
|
|
725
|
+
>;
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Resolves the default integration keys based on the pattern.
|
|
729
|
+
* - 'shared': only '$router' is a default key
|
|
730
|
+
* - 'isolated': all TOperation keys are default keys
|
|
731
|
+
*/
|
|
732
|
+
type DefaultIntegrationKeys<
|
|
733
|
+
TPattern extends 'shared' | 'isolated',
|
|
734
|
+
TOperation extends string,
|
|
735
|
+
> = TPattern extends 'shared' ? '$router' : TOperation;
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Shared integration record: $router is required, individual operations are optional.
|
|
739
|
+
*/
|
|
740
|
+
type SharedIntegrations<TOperation extends string, TBaseIntegration> = {
|
|
741
|
+
$router: TBaseIntegration;
|
|
742
|
+
} & Partial<Record<TOperation, TBaseIntegration>>;
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Valid integration record types for an API.
|
|
746
|
+
* Either all operations are provided (isolated), or $router is provided
|
|
747
|
+
* with optional per-operation overrides (shared).
|
|
748
|
+
*/
|
|
749
|
+
export type ApiIntegrations<TOperation extends string, TBaseIntegration> =
|
|
750
|
+
| SharedIntegrations<TOperation, TBaseIntegration>
|
|
751
|
+
| (Record<TOperation, TBaseIntegration> & { $router?: never });
|
|
752
|
+
|
|
640
753
|
/**
|
|
641
754
|
* A builder class for creating API integrations with flexible configuration options.
|
|
642
755
|
*
|
|
@@ -645,16 +758,18 @@ export interface IntegrationBuilderProps<
|
|
|
645
758
|
*
|
|
646
759
|
* @template TOperation - String literal type representing operation names
|
|
647
760
|
* @template TBaseIntegration - Base type for all integrations
|
|
648
|
-
* @template TIntegrations - Record mapping
|
|
761
|
+
* @template TIntegrations - Record mapping integration keys to their integrations
|
|
649
762
|
* @template TDefaultIntegrationProps - Type for default integration properties
|
|
650
763
|
* @template TDefaultIntegration - Type for default integration implementation
|
|
764
|
+
* @template TPattern - The integration pattern ('shared' or 'isolated')
|
|
651
765
|
*/
|
|
652
766
|
export class IntegrationBuilder<
|
|
653
767
|
TOperation extends string,
|
|
654
768
|
TBaseIntegration,
|
|
655
|
-
TIntegrations extends Record<
|
|
769
|
+
TIntegrations extends Record<string, TBaseIntegration>,
|
|
656
770
|
TDefaultIntegrationProps extends object,
|
|
657
771
|
TDefaultIntegration extends TBaseIntegration,
|
|
772
|
+
TPattern extends 'shared' | 'isolated',
|
|
658
773
|
> {
|
|
659
774
|
/** Options for the integration builder */
|
|
660
775
|
private options: IntegrationBuilderProps<
|
|
@@ -672,23 +787,25 @@ export class IntegrationBuilder<
|
|
|
672
787
|
*/
|
|
673
788
|
public static http = <
|
|
674
789
|
TOperation extends string,
|
|
675
|
-
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
676
790
|
TDefaultIntegrationProps extends object,
|
|
677
791
|
TDefaultIntegration extends HttpApiIntegration,
|
|
792
|
+
TPattern extends 'shared' | 'isolated',
|
|
678
793
|
>(
|
|
679
|
-
options:
|
|
794
|
+
options: IntegrationBuilderPropsForPattern<
|
|
680
795
|
TOperation,
|
|
681
796
|
HttpApiIntegration,
|
|
682
797
|
TDefaultIntegrationProps,
|
|
683
|
-
TDefaultIntegration
|
|
798
|
+
TDefaultIntegration,
|
|
799
|
+
TPattern
|
|
684
800
|
>,
|
|
685
801
|
) => {
|
|
686
802
|
return new IntegrationBuilder<
|
|
687
803
|
TOperation,
|
|
688
804
|
HttpApiIntegration,
|
|
689
|
-
|
|
805
|
+
Record<DefaultIntegrationKeys<TPattern, TOperation>, TDefaultIntegration>,
|
|
690
806
|
TDefaultIntegrationProps,
|
|
691
|
-
TDefaultIntegration
|
|
807
|
+
TDefaultIntegration,
|
|
808
|
+
TPattern
|
|
692
809
|
>(options);
|
|
693
810
|
};
|
|
694
811
|
|
|
@@ -697,23 +814,25 @@ export class IntegrationBuilder<
|
|
|
697
814
|
*/
|
|
698
815
|
public static rest = <
|
|
699
816
|
TOperation extends string,
|
|
700
|
-
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
701
817
|
TDefaultIntegrationProps extends object,
|
|
702
818
|
TDefaultIntegration extends RestApiIntegration,
|
|
819
|
+
TPattern extends 'shared' | 'isolated',
|
|
703
820
|
>(
|
|
704
|
-
options:
|
|
821
|
+
options: IntegrationBuilderPropsForPattern<
|
|
705
822
|
TOperation,
|
|
706
823
|
RestApiIntegration,
|
|
707
824
|
TDefaultIntegrationProps,
|
|
708
|
-
TDefaultIntegration
|
|
825
|
+
TDefaultIntegration,
|
|
826
|
+
TPattern
|
|
709
827
|
>,
|
|
710
828
|
) => {
|
|
711
829
|
return new IntegrationBuilder<
|
|
712
830
|
TOperation,
|
|
713
831
|
RestApiIntegration,
|
|
714
|
-
|
|
832
|
+
Record<DefaultIntegrationKeys<TPattern, TOperation>, TDefaultIntegration>,
|
|
715
833
|
TDefaultIntegrationProps,
|
|
716
|
-
TDefaultIntegration
|
|
834
|
+
TDefaultIntegration,
|
|
835
|
+
TPattern
|
|
717
836
|
>(options);
|
|
718
837
|
};
|
|
719
838
|
|
|
@@ -738,13 +857,20 @@ export class IntegrationBuilder<
|
|
|
738
857
|
TOverrideIntegrations extends Partial<Record<TOperation, TBaseIntegration>>,
|
|
739
858
|
>(overrides: TOverrideIntegrations) {
|
|
740
859
|
this.integrations = { ...this.integrations, ...overrides };
|
|
741
|
-
// Re-type to include the overridden integration types
|
|
860
|
+
// Re-type to include the overridden integration types.
|
|
861
|
+
// If all operations are overridden in a 'shared' pattern, drop '$router' from the type.
|
|
862
|
+
type MergedIntegrations = [TOperation] extends [keyof TOverrideIntegrations]
|
|
863
|
+
? Omit<TIntegrations, keyof TOverrideIntegrations | '$router'> &
|
|
864
|
+
TOverrideIntegrations
|
|
865
|
+
: Omit<TIntegrations, keyof TOverrideIntegrations> &
|
|
866
|
+
TOverrideIntegrations;
|
|
742
867
|
return this as unknown as IntegrationBuilder<
|
|
743
868
|
TOperation,
|
|
744
869
|
TBaseIntegration,
|
|
745
|
-
|
|
870
|
+
MergedIntegrations,
|
|
746
871
|
TDefaultIntegrationProps,
|
|
747
|
-
TDefaultIntegration
|
|
872
|
+
TDefaultIntegration,
|
|
873
|
+
TPattern
|
|
748
874
|
>;
|
|
749
875
|
}
|
|
750
876
|
|
|
@@ -770,24 +896,39 @@ export class IntegrationBuilder<
|
|
|
770
896
|
* 1. Including all custom overrides provided via withOverrides()
|
|
771
897
|
* 2. Creating default integrations for any operations without custom overrides
|
|
772
898
|
*
|
|
773
|
-
*
|
|
899
|
+
* For the 'shared' pattern, a single router integration is built and assigned to '$router'.
|
|
900
|
+
* For the 'isolated' pattern, each operation without an override gets its own integration.
|
|
901
|
+
*
|
|
902
|
+
* @returns A complete map of integration keys to their integrations
|
|
774
903
|
*/
|
|
775
904
|
public build(): TIntegrations {
|
|
905
|
+
const options = this.options;
|
|
776
906
|
return {
|
|
777
|
-
...this.integrations,
|
|
778
907
|
...Object.fromEntries(
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
])
|
|
908
|
+
options.pattern === 'shared'
|
|
909
|
+
? [
|
|
910
|
+
[
|
|
911
|
+
'$router',
|
|
912
|
+
options.buildDefaultIntegration(
|
|
913
|
+
'$router',
|
|
914
|
+
options.defaultIntegrationOptions,
|
|
915
|
+
),
|
|
916
|
+
],
|
|
917
|
+
]
|
|
918
|
+
: (Object.keys(options.operations) as TOperation[])
|
|
919
|
+
.filter(
|
|
920
|
+
(op) =>
|
|
921
|
+
!this.integrations[op as keyof typeof this.integrations],
|
|
922
|
+
)
|
|
923
|
+
.map((op) => [
|
|
924
|
+
op,
|
|
925
|
+
options.buildDefaultIntegration(
|
|
926
|
+
op,
|
|
927
|
+
options.defaultIntegrationOptions,
|
|
928
|
+
),
|
|
929
|
+
]),
|
|
790
930
|
),
|
|
931
|
+
...this.integrations,
|
|
791
932
|
} as unknown as TIntegrations;
|
|
792
933
|
}
|
|
793
934
|
}
|
|
@@ -803,17 +944,21 @@ import {
|
|
|
803
944
|
Stage,
|
|
804
945
|
} from 'aws-cdk-lib/aws-apigateway';
|
|
805
946
|
import { RuntimeConfig } from '../runtime-config.js';
|
|
806
|
-
import {
|
|
947
|
+
import {
|
|
948
|
+
ApiIntegrations,
|
|
949
|
+
OperationDetails,
|
|
950
|
+
RestApiIntegration,
|
|
951
|
+
} from './utils.js';
|
|
807
952
|
import { suppressRules } from '../checkov.js';
|
|
808
953
|
|
|
809
954
|
/**
|
|
810
955
|
* Properties for creating a RestApi construct.
|
|
811
956
|
*
|
|
812
|
-
* @template TIntegrations - Record mapping
|
|
957
|
+
* @template TIntegrations - Record mapping integration keys to their integrations
|
|
813
958
|
* @template TOperation - String literal type representing operation names
|
|
814
959
|
*/
|
|
815
960
|
export interface RestApiProps<
|
|
816
|
-
TIntegrations extends
|
|
961
|
+
TIntegrations extends ApiIntegrations<TOperation, RestApiIntegration>,
|
|
817
962
|
TOperation extends string,
|
|
818
963
|
> extends _RestApiProps {
|
|
819
964
|
/**
|
|
@@ -825,7 +970,7 @@ export interface RestApiProps<
|
|
|
825
970
|
*/
|
|
826
971
|
readonly operations: Record<TOperation, OperationDetails>;
|
|
827
972
|
/**
|
|
828
|
-
* Map of
|
|
973
|
+
* Map of integration keys to their API Gateway integrations
|
|
829
974
|
*/
|
|
830
975
|
readonly integrations: TIntegrations;
|
|
831
976
|
}
|
|
@@ -839,16 +984,16 @@ export interface RestApiProps<
|
|
|
839
984
|
* - Integration with runtime configuration for client discovery
|
|
840
985
|
*
|
|
841
986
|
* @template TOperation - String literal type representing operation names
|
|
842
|
-
* @template TIntegrations - Record mapping
|
|
987
|
+
* @template TIntegrations - Record mapping integration keys to their integrations
|
|
843
988
|
*/
|
|
844
989
|
export class RestApi<
|
|
845
990
|
TOperation extends string,
|
|
846
|
-
TIntegrations extends
|
|
991
|
+
TIntegrations extends ApiIntegrations<TOperation, RestApiIntegration>,
|
|
847
992
|
> extends Construct {
|
|
848
993
|
/** The underlying CDK RestApi instance */
|
|
849
994
|
public readonly api: _RestApi;
|
|
850
995
|
|
|
851
|
-
/** Map of
|
|
996
|
+
/** Map of integration keys to their API Gateway integrations */
|
|
852
997
|
public readonly integrations: TIntegrations;
|
|
853
998
|
|
|
854
999
|
constructor(
|
|
@@ -880,9 +1025,25 @@ export class RestApi<
|
|
|
880
1025
|
(c) => c instanceof Stage,
|
|
881
1026
|
);
|
|
882
1027
|
|
|
1028
|
+
// Resolve the integration for a given operation.
|
|
1029
|
+
// If the operation has a dedicated integration, use it; otherwise fall back to $router.
|
|
1030
|
+
const resolveIntegration = (op: TOperation): RestApiIntegration => {
|
|
1031
|
+
const record = integrations as Record<string, RestApiIntegration>;
|
|
1032
|
+
if (op in record) {
|
|
1033
|
+
return record[op];
|
|
1034
|
+
}
|
|
1035
|
+
if ('$router' in record) {
|
|
1036
|
+
return record['$router'];
|
|
1037
|
+
}
|
|
1038
|
+
throw new Error(
|
|
1039
|
+
\`No integration found for operation '\${op}' and no $router integration available\`,
|
|
1040
|
+
);
|
|
1041
|
+
};
|
|
1042
|
+
|
|
883
1043
|
// Create API resources and methods for each operation
|
|
884
1044
|
(Object.entries(operations) as [TOperation, OperationDetails][]).map(
|
|
885
1045
|
([op, details]) => {
|
|
1046
|
+
const integration = resolveIntegration(op);
|
|
886
1047
|
const resource = this.getOrCreateResource(
|
|
887
1048
|
this.api.root,
|
|
888
1049
|
(details.path.startsWith('/')
|
|
@@ -892,8 +1053,8 @@ export class RestApi<
|
|
|
892
1053
|
);
|
|
893
1054
|
resource.addMethod(
|
|
894
1055
|
details.method,
|
|
895
|
-
|
|
896
|
-
|
|
1056
|
+
integration.integration,
|
|
1057
|
+
integration.options,
|
|
897
1058
|
);
|
|
898
1059
|
},
|
|
899
1060
|
);
|
|
@@ -956,6 +1117,7 @@ import {
|
|
|
956
1117
|
Grant,
|
|
957
1118
|
} from 'aws-cdk-lib/aws-iam';
|
|
958
1119
|
import {
|
|
1120
|
+
ApiIntegrations,
|
|
959
1121
|
IntegrationBuilder,
|
|
960
1122
|
RestApiIntegration,
|
|
961
1123
|
} from '../../core/api/utils.js';
|
|
@@ -971,7 +1133,7 @@ import {
|
|
|
971
1133
|
* @template TIntegrations - Map of operation names to their integrations
|
|
972
1134
|
*/
|
|
973
1135
|
export interface TestApiProps<
|
|
974
|
-
TIntegrations extends
|
|
1136
|
+
TIntegrations extends ApiIntegrations<Operations, RestApiIntegration>,
|
|
975
1137
|
> {
|
|
976
1138
|
/**
|
|
977
1139
|
* Map of operation names to their API Gateway integrations
|
|
@@ -985,7 +1147,7 @@ export interface TestApiProps<
|
|
|
985
1147
|
* @template TIntegrations - Map of operation names to their integrations
|
|
986
1148
|
*/
|
|
987
1149
|
export class TestApi<
|
|
988
|
-
TIntegrations extends
|
|
1150
|
+
TIntegrations extends ApiIntegrations<Operations, RestApiIntegration>,
|
|
989
1151
|
> extends RestApi<Operations, TIntegrations> {
|
|
990
1152
|
/**
|
|
991
1153
|
* Creates default integrations for all operations, which implement each operation as
|
|
@@ -996,8 +1158,9 @@ export class TestApi<
|
|
|
996
1158
|
*/
|
|
997
1159
|
public static defaultIntegrations = (scope: Construct) => {
|
|
998
1160
|
return IntegrationBuilder.rest({
|
|
1161
|
+
pattern: 'isolated',
|
|
999
1162
|
operations: OPERATION_DETAILS,
|
|
1000
|
-
defaultIntegrationOptions: {
|
|
1163
|
+
defaultIntegrationOptions: <FunctionProps>{
|
|
1001
1164
|
runtime: Runtime.PYTHON_3_12,
|
|
1002
1165
|
handler: 'run.sh',
|
|
1003
1166
|
code: Code.fromAsset(
|
|
@@ -1017,7 +1180,7 @@ export class TestApi<
|
|
|
1017
1180
|
AWS_LWA_INVOKE_MODE: 'response_stream',
|
|
1018
1181
|
AWS_LAMBDA_EXEC_WRAPPER: '/opt/bootstrap',
|
|
1019
1182
|
},
|
|
1020
|
-
}
|
|
1183
|
+
},
|
|
1021
1184
|
buildDefaultIntegration: (op, props: FunctionProps) => {
|
|
1022
1185
|
const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
|
|
1023
1186
|
const stack = Stack.of(scope);
|
|
@@ -1179,20 +1342,46 @@ export interface HttpApiIntegration {
|
|
|
1179
1342
|
}
|
|
1180
1343
|
|
|
1181
1344
|
/**
|
|
1182
|
-
*
|
|
1345
|
+
* Common options shared by all IntegrationBuilder configurations
|
|
1183
1346
|
*/
|
|
1184
|
-
|
|
1347
|
+
interface IntegrationBuilderPropsBase<
|
|
1185
1348
|
TOperation extends string,
|
|
1186
|
-
TBaseIntegration,
|
|
1187
1349
|
TDefaultIntegrationProps extends object,
|
|
1188
|
-
TDefaultIntegration extends TBaseIntegration,
|
|
1189
1350
|
> {
|
|
1190
1351
|
/** Map of operation names to their API path and HTTP method details */
|
|
1191
1352
|
operations: Record<TOperation, OperationDetails>;
|
|
1192
1353
|
|
|
1193
1354
|
/** Default configuration options for integrations */
|
|
1194
1355
|
defaultIntegrationOptions: TDefaultIntegrationProps;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* Options for constructing an IntegrationBuilder with a shared integration pattern.
|
|
1360
|
+
* A single default integration is built once (for '$router') and reused for all operations.
|
|
1361
|
+
*/
|
|
1362
|
+
interface SharedIntegrationBuilderProps<
|
|
1363
|
+
TOperation extends string,
|
|
1364
|
+
TDefaultIntegrationProps extends object,
|
|
1365
|
+
TDefaultIntegration,
|
|
1366
|
+
> extends IntegrationBuilderPropsBase<TOperation, TDefaultIntegrationProps> {
|
|
1367
|
+
pattern: 'shared';
|
|
1368
|
+
/** Function to create a default integration for the shared router */
|
|
1369
|
+
buildDefaultIntegration: (
|
|
1370
|
+
op: '$router',
|
|
1371
|
+
props: TDefaultIntegrationProps,
|
|
1372
|
+
) => TDefaultIntegration;
|
|
1373
|
+
}
|
|
1195
1374
|
|
|
1375
|
+
/**
|
|
1376
|
+
* Options for constructing an IntegrationBuilder with an isolated integration pattern.
|
|
1377
|
+
* A separate default integration is built per operation.
|
|
1378
|
+
*/
|
|
1379
|
+
interface IsolatedIntegrationBuilderProps<
|
|
1380
|
+
TOperation extends string,
|
|
1381
|
+
TDefaultIntegrationProps extends object,
|
|
1382
|
+
TDefaultIntegration,
|
|
1383
|
+
> extends IntegrationBuilderPropsBase<TOperation, TDefaultIntegrationProps> {
|
|
1384
|
+
pattern: 'isolated';
|
|
1196
1385
|
/** Function to create a default integration for an operation */
|
|
1197
1386
|
buildDefaultIntegration: (
|
|
1198
1387
|
op: TOperation,
|
|
@@ -1200,6 +1389,71 @@ export interface IntegrationBuilderProps<
|
|
|
1200
1389
|
) => TDefaultIntegration;
|
|
1201
1390
|
}
|
|
1202
1391
|
|
|
1392
|
+
/**
|
|
1393
|
+
* Options for constructing an IntegrationBuilder
|
|
1394
|
+
*/
|
|
1395
|
+
export type IntegrationBuilderProps<
|
|
1396
|
+
TOperation extends string,
|
|
1397
|
+
TBaseIntegration,
|
|
1398
|
+
TDefaultIntegrationProps extends object,
|
|
1399
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
1400
|
+
> =
|
|
1401
|
+
| SharedIntegrationBuilderProps<
|
|
1402
|
+
TOperation,
|
|
1403
|
+
TDefaultIntegrationProps,
|
|
1404
|
+
TDefaultIntegration
|
|
1405
|
+
>
|
|
1406
|
+
| IsolatedIntegrationBuilderProps<
|
|
1407
|
+
TOperation,
|
|
1408
|
+
TDefaultIntegrationProps,
|
|
1409
|
+
TDefaultIntegration
|
|
1410
|
+
>;
|
|
1411
|
+
|
|
1412
|
+
/**
|
|
1413
|
+
* Extracts the IntegrationBuilderProps variant matching the given pattern.
|
|
1414
|
+
*/
|
|
1415
|
+
type IntegrationBuilderPropsForPattern<
|
|
1416
|
+
TOperation extends string,
|
|
1417
|
+
TBaseIntegration,
|
|
1418
|
+
TDefaultIntegrationProps extends object,
|
|
1419
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
1420
|
+
TPattern extends 'shared' | 'isolated',
|
|
1421
|
+
> = Extract<
|
|
1422
|
+
IntegrationBuilderProps<
|
|
1423
|
+
TOperation,
|
|
1424
|
+
TBaseIntegration,
|
|
1425
|
+
TDefaultIntegrationProps,
|
|
1426
|
+
TDefaultIntegration
|
|
1427
|
+
>,
|
|
1428
|
+
{ pattern: TPattern }
|
|
1429
|
+
>;
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* Resolves the default integration keys based on the pattern.
|
|
1433
|
+
* - 'shared': only '$router' is a default key
|
|
1434
|
+
* - 'isolated': all TOperation keys are default keys
|
|
1435
|
+
*/
|
|
1436
|
+
type DefaultIntegrationKeys<
|
|
1437
|
+
TPattern extends 'shared' | 'isolated',
|
|
1438
|
+
TOperation extends string,
|
|
1439
|
+
> = TPattern extends 'shared' ? '$router' : TOperation;
|
|
1440
|
+
|
|
1441
|
+
/**
|
|
1442
|
+
* Shared integration record: $router is required, individual operations are optional.
|
|
1443
|
+
*/
|
|
1444
|
+
type SharedIntegrations<TOperation extends string, TBaseIntegration> = {
|
|
1445
|
+
$router: TBaseIntegration;
|
|
1446
|
+
} & Partial<Record<TOperation, TBaseIntegration>>;
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Valid integration record types for an API.
|
|
1450
|
+
* Either all operations are provided (isolated), or $router is provided
|
|
1451
|
+
* with optional per-operation overrides (shared).
|
|
1452
|
+
*/
|
|
1453
|
+
export type ApiIntegrations<TOperation extends string, TBaseIntegration> =
|
|
1454
|
+
| SharedIntegrations<TOperation, TBaseIntegration>
|
|
1455
|
+
| (Record<TOperation, TBaseIntegration> & { $router?: never });
|
|
1456
|
+
|
|
1203
1457
|
/**
|
|
1204
1458
|
* A builder class for creating API integrations with flexible configuration options.
|
|
1205
1459
|
*
|
|
@@ -1208,16 +1462,18 @@ export interface IntegrationBuilderProps<
|
|
|
1208
1462
|
*
|
|
1209
1463
|
* @template TOperation - String literal type representing operation names
|
|
1210
1464
|
* @template TBaseIntegration - Base type for all integrations
|
|
1211
|
-
* @template TIntegrations - Record mapping
|
|
1465
|
+
* @template TIntegrations - Record mapping integration keys to their integrations
|
|
1212
1466
|
* @template TDefaultIntegrationProps - Type for default integration properties
|
|
1213
1467
|
* @template TDefaultIntegration - Type for default integration implementation
|
|
1468
|
+
* @template TPattern - The integration pattern ('shared' or 'isolated')
|
|
1214
1469
|
*/
|
|
1215
1470
|
export class IntegrationBuilder<
|
|
1216
1471
|
TOperation extends string,
|
|
1217
1472
|
TBaseIntegration,
|
|
1218
|
-
TIntegrations extends Record<
|
|
1473
|
+
TIntegrations extends Record<string, TBaseIntegration>,
|
|
1219
1474
|
TDefaultIntegrationProps extends object,
|
|
1220
1475
|
TDefaultIntegration extends TBaseIntegration,
|
|
1476
|
+
TPattern extends 'shared' | 'isolated',
|
|
1221
1477
|
> {
|
|
1222
1478
|
/** Options for the integration builder */
|
|
1223
1479
|
private options: IntegrationBuilderProps<
|
|
@@ -1235,23 +1491,25 @@ export class IntegrationBuilder<
|
|
|
1235
1491
|
*/
|
|
1236
1492
|
public static http = <
|
|
1237
1493
|
TOperation extends string,
|
|
1238
|
-
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
1239
1494
|
TDefaultIntegrationProps extends object,
|
|
1240
1495
|
TDefaultIntegration extends HttpApiIntegration,
|
|
1496
|
+
TPattern extends 'shared' | 'isolated',
|
|
1241
1497
|
>(
|
|
1242
|
-
options:
|
|
1498
|
+
options: IntegrationBuilderPropsForPattern<
|
|
1243
1499
|
TOperation,
|
|
1244
1500
|
HttpApiIntegration,
|
|
1245
1501
|
TDefaultIntegrationProps,
|
|
1246
|
-
TDefaultIntegration
|
|
1502
|
+
TDefaultIntegration,
|
|
1503
|
+
TPattern
|
|
1247
1504
|
>,
|
|
1248
1505
|
) => {
|
|
1249
1506
|
return new IntegrationBuilder<
|
|
1250
1507
|
TOperation,
|
|
1251
1508
|
HttpApiIntegration,
|
|
1252
|
-
|
|
1509
|
+
Record<DefaultIntegrationKeys<TPattern, TOperation>, TDefaultIntegration>,
|
|
1253
1510
|
TDefaultIntegrationProps,
|
|
1254
|
-
TDefaultIntegration
|
|
1511
|
+
TDefaultIntegration,
|
|
1512
|
+
TPattern
|
|
1255
1513
|
>(options);
|
|
1256
1514
|
};
|
|
1257
1515
|
|
|
@@ -1260,23 +1518,25 @@ export class IntegrationBuilder<
|
|
|
1260
1518
|
*/
|
|
1261
1519
|
public static rest = <
|
|
1262
1520
|
TOperation extends string,
|
|
1263
|
-
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
1264
1521
|
TDefaultIntegrationProps extends object,
|
|
1265
1522
|
TDefaultIntegration extends RestApiIntegration,
|
|
1523
|
+
TPattern extends 'shared' | 'isolated',
|
|
1266
1524
|
>(
|
|
1267
|
-
options:
|
|
1525
|
+
options: IntegrationBuilderPropsForPattern<
|
|
1268
1526
|
TOperation,
|
|
1269
1527
|
RestApiIntegration,
|
|
1270
1528
|
TDefaultIntegrationProps,
|
|
1271
|
-
TDefaultIntegration
|
|
1529
|
+
TDefaultIntegration,
|
|
1530
|
+
TPattern
|
|
1272
1531
|
>,
|
|
1273
1532
|
) => {
|
|
1274
1533
|
return new IntegrationBuilder<
|
|
1275
1534
|
TOperation,
|
|
1276
1535
|
RestApiIntegration,
|
|
1277
|
-
|
|
1536
|
+
Record<DefaultIntegrationKeys<TPattern, TOperation>, TDefaultIntegration>,
|
|
1278
1537
|
TDefaultIntegrationProps,
|
|
1279
|
-
TDefaultIntegration
|
|
1538
|
+
TDefaultIntegration,
|
|
1539
|
+
TPattern
|
|
1280
1540
|
>(options);
|
|
1281
1541
|
};
|
|
1282
1542
|
|
|
@@ -1301,13 +1561,20 @@ export class IntegrationBuilder<
|
|
|
1301
1561
|
TOverrideIntegrations extends Partial<Record<TOperation, TBaseIntegration>>,
|
|
1302
1562
|
>(overrides: TOverrideIntegrations) {
|
|
1303
1563
|
this.integrations = { ...this.integrations, ...overrides };
|
|
1304
|
-
// Re-type to include the overridden integration types
|
|
1564
|
+
// Re-type to include the overridden integration types.
|
|
1565
|
+
// If all operations are overridden in a 'shared' pattern, drop '$router' from the type.
|
|
1566
|
+
type MergedIntegrations = [TOperation] extends [keyof TOverrideIntegrations]
|
|
1567
|
+
? Omit<TIntegrations, keyof TOverrideIntegrations | '$router'> &
|
|
1568
|
+
TOverrideIntegrations
|
|
1569
|
+
: Omit<TIntegrations, keyof TOverrideIntegrations> &
|
|
1570
|
+
TOverrideIntegrations;
|
|
1305
1571
|
return this as unknown as IntegrationBuilder<
|
|
1306
1572
|
TOperation,
|
|
1307
1573
|
TBaseIntegration,
|
|
1308
|
-
|
|
1574
|
+
MergedIntegrations,
|
|
1309
1575
|
TDefaultIntegrationProps,
|
|
1310
|
-
TDefaultIntegration
|
|
1576
|
+
TDefaultIntegration,
|
|
1577
|
+
TPattern
|
|
1311
1578
|
>;
|
|
1312
1579
|
}
|
|
1313
1580
|
|
|
@@ -1333,24 +1600,39 @@ export class IntegrationBuilder<
|
|
|
1333
1600
|
* 1. Including all custom overrides provided via withOverrides()
|
|
1334
1601
|
* 2. Creating default integrations for any operations without custom overrides
|
|
1335
1602
|
*
|
|
1336
|
-
*
|
|
1603
|
+
* For the 'shared' pattern, a single router integration is built and assigned to '$router'.
|
|
1604
|
+
* For the 'isolated' pattern, each operation without an override gets its own integration.
|
|
1605
|
+
*
|
|
1606
|
+
* @returns A complete map of integration keys to their integrations
|
|
1337
1607
|
*/
|
|
1338
1608
|
public build(): TIntegrations {
|
|
1609
|
+
const options = this.options;
|
|
1339
1610
|
return {
|
|
1340
|
-
...this.integrations,
|
|
1341
1611
|
...Object.fromEntries(
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
])
|
|
1612
|
+
options.pattern === 'shared'
|
|
1613
|
+
? [
|
|
1614
|
+
[
|
|
1615
|
+
'$router',
|
|
1616
|
+
options.buildDefaultIntegration(
|
|
1617
|
+
'$router',
|
|
1618
|
+
options.defaultIntegrationOptions,
|
|
1619
|
+
),
|
|
1620
|
+
],
|
|
1621
|
+
]
|
|
1622
|
+
: (Object.keys(options.operations) as TOperation[])
|
|
1623
|
+
.filter(
|
|
1624
|
+
(op) =>
|
|
1625
|
+
!this.integrations[op as keyof typeof this.integrations],
|
|
1626
|
+
)
|
|
1627
|
+
.map((op) => [
|
|
1628
|
+
op,
|
|
1629
|
+
options.buildDefaultIntegration(
|
|
1630
|
+
op,
|
|
1631
|
+
options.defaultIntegrationOptions,
|
|
1632
|
+
),
|
|
1633
|
+
]),
|
|
1353
1634
|
),
|
|
1635
|
+
...this.integrations,
|
|
1354
1636
|
} as unknown as TIntegrations;
|
|
1355
1637
|
}
|
|
1356
1638
|
}
|