1
- import {
2
- FunctionOutput ,
3
- functionOutputKey ,
4
- } from '@aws-amplify/backend-output-schemas' ;
5
- import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage' ;
1
+ import { FunctionOutput } from '@aws-amplify/backend-output-schemas' ;
6
2
import {
7
3
AmplifyUserError ,
8
4
CallerDirectoryExtractor ,
@@ -20,19 +16,19 @@ import {
20
16
GenerateContainerEntryProps ,
21
17
LogLevel ,
22
18
LogRetention ,
19
+ ResourceAccessAcceptor ,
23
20
ResourceAccessAcceptorFactory ,
24
21
ResourceNameValidator ,
25
22
ResourceProvider ,
26
- SsmEnvironmentEntry ,
27
23
StackProvider ,
28
24
} from '@aws-amplify/plugin-types' ;
29
25
import { Duration , Size , Stack , Tags } from 'aws-cdk-lib' ;
30
26
import { Rule } from 'aws-cdk-lib/aws-events' ;
31
27
import * as targets from 'aws-cdk-lib/aws-events-targets' ;
32
- import { Policy } from 'aws-cdk-lib/aws-iam' ;
33
28
import {
34
29
Architecture ,
35
30
CfnFunction ,
31
+ IFunction ,
36
32
ILayerVersion ,
37
33
LayerVersion ,
38
34
Runtime ,
@@ -41,16 +37,19 @@ import { NodejsFunction, OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs';
41
37
import { Construct } from 'constructs' ;
42
38
import { readFileSync } from 'fs' ;
43
39
import { createRequire } from 'module' ;
44
- import { fileURLToPath } from 'node:url' ;
45
40
import { EOL } from 'os' ;
46
41
import * as path from 'path' ;
47
42
import { FunctionEnvironmentTranslator } from './function_env_translator.js' ;
48
43
import { FunctionEnvironmentTypeGenerator } from './function_env_type_generator.js' ;
49
44
import { FunctionLayerArnParser } from './layer_parser.js' ;
50
45
import { convertLoggingOptionsToCDK } from './logging_options_parser.js' ;
51
46
import { convertFunctionSchedulesToRuleSchedules } from './schedule_parser.js' ;
52
-
53
- const functionStackType = 'function-Lambda' ;
47
+ import {
48
+ ProvidedFunctionFactory ,
49
+ ProvidedFunctionProps ,
50
+ } from './provided_function_factory.js' ;
51
+ import { AmplifyFunctionBase } from './function_construct_base.js' ;
52
+ import { FunctionResourceAccessAcceptor } from './resource_access_acceptor.js' ;
54
53
55
54
export type AddEnvironmentFactory = {
56
55
addEnvironment : ( key : string , value : string | BackendSecret ) => void ;
@@ -74,17 +73,38 @@ export type FunctionLogLevel = Extract<
74
73
> ;
75
74
export type FunctionLogRetention = LogRetention ;
76
75
77
- /**
78
- * Entry point for defining a function in the Amplify ecosystem
79
- */
80
- export const defineFunction = (
81
- props : FunctionProps = { }
76
+ export function defineFunction (
77
+ props ?: FunctionProps
82
78
) : ConstructFactory <
83
79
ResourceProvider < FunctionResources > &
84
80
ResourceAccessAcceptorFactory &
85
81
AddEnvironmentFactory &
86
82
StackProvider
87
- > => new FunctionFactory ( props , new Error ( ) . stack ) ;
83
+ > ;
84
+ export function defineFunction (
85
+ provider : ( scope : Construct ) => IFunction ,
86
+ providerProps ?: ProvidedFunctionProps
87
+ ) : ConstructFactory <
88
+ ResourceProvider < FunctionResources > &
89
+ ResourceAccessAcceptorFactory &
90
+ StackProvider
91
+ > ;
92
+ /**
93
+ * Entry point for defining a function in the Amplify ecosystem
94
+ */
95
+ // This is the "implementation overload", it's not visible in public api.
96
+ // We have to use function notation instead of arrow notation.
97
+ // Arrow notation does not support overloads.
98
+ // eslint-disable-next-line no-restricted-syntax
99
+ export function defineFunction (
100
+ propsOrProvider : FunctionProps | ( ( scope : Construct ) => IFunction ) = { } ,
101
+ providerProps ?: ProvidedFunctionProps
102
+ ) : unknown {
103
+ if ( propsOrProvider && typeof propsOrProvider === 'function' ) {
104
+ return new ProvidedFunctionFactory ( propsOrProvider , providerProps ) ;
105
+ }
106
+ return new FunctionFactory ( propsOrProvider , new Error ( ) . stack ) ;
107
+ }
88
108
89
109
export type FunctionProps = {
90
110
/**
@@ -507,14 +527,10 @@ class FunctionGenerator implements ConstructContainerEntryGenerator {
507
527
}
508
528
509
529
class AmplifyFunction
510
- extends Construct
511
- implements
512
- ResourceProvider < FunctionResources > ,
513
- ResourceAccessAcceptorFactory ,
514
- AddEnvironmentFactory
530
+ extends AmplifyFunctionBase
531
+ implements AddEnvironmentFactory
515
532
{
516
533
readonly resources : FunctionResources ;
517
- readonly stack : Stack ;
518
534
private readonly functionEnvironmentTranslator : FunctionEnvironmentTranslator ;
519
535
constructor (
520
536
scope : Construct ,
@@ -523,9 +539,7 @@ class AmplifyFunction
523
539
backendSecretResolver : BackendSecretResolver ,
524
540
outputStorageStrategy : BackendOutputStorageStrategy < FunctionOutput >
525
541
) {
526
- super ( scope , id ) ;
527
-
528
- this . stack = Stack . of ( scope ) ;
542
+ super ( scope , id , outputStorageStrategy ) ;
529
543
530
544
const runtime = nodeVersionMap [ props . runtime ] ;
531
545
@@ -647,52 +661,18 @@ class AmplifyFunction
647
661
} ,
648
662
} ;
649
663
650
- this . storeOutput ( outputStorageStrategy ) ;
651
-
652
- new AttributionMetadataStorage ( ) . storeAttributionMetadata (
653
- Stack . of ( this ) ,
654
- functionStackType ,
655
- fileURLToPath ( new URL ( '../package.json' , import . meta. url ) )
656
- ) ;
664
+ this . storeOutput ( ) ;
657
665
}
658
666
659
667
addEnvironment = ( key : string , value : string | BackendSecret ) => {
660
668
this . functionEnvironmentTranslator . addEnvironmentEntry ( key , value ) ;
661
669
} ;
662
670
663
- getResourceAccessAcceptor = ( ) => ( {
664
- identifier : `${ this . node . id } LambdaResourceAccessAcceptor` ,
665
- acceptResourceAccess : (
666
- policy : Policy ,
667
- ssmEnvironmentEntries : SsmEnvironmentEntry [ ]
668
- ) => {
669
- const role = this . resources . lambda . role ;
670
- if ( ! role ) {
671
- // This should never happen since we are using the Function L2 construct
672
- throw new Error (
673
- 'No execution role found to attach lambda permissions to'
674
- ) ;
675
- }
676
- policy . attachToRole ( role ) ;
677
- ssmEnvironmentEntries . forEach ( ( { name, path } ) => {
678
- this . functionEnvironmentTranslator . addSsmEnvironmentEntry ( name , path ) ;
679
- } ) ;
680
- } ,
681
- } ) ;
682
-
683
- /**
684
- * Store storage outputs using provided strategy
685
- */
686
- private storeOutput = (
687
- outputStorageStrategy : BackendOutputStorageStrategy < FunctionOutput >
688
- ) : void => {
689
- outputStorageStrategy . appendToBackendOutputList ( functionOutputKey , {
690
- version : '1' ,
691
- payload : {
692
- definedFunctions : this . resources . lambda . functionName ,
693
- } ,
694
- } ) ;
695
- } ;
671
+ getResourceAccessAcceptor = ( ) : ResourceAccessAcceptor =>
672
+ new FunctionResourceAccessAcceptor (
673
+ this ,
674
+ this . functionEnvironmentTranslator
675
+ ) ;
696
676
}
697
677
698
678
const isWholeNumberBetweenInclusive = (
0 commit comments