constructor()

in templates/CDKTemplate.js [52:277]


    constructor(scope, id, props) {
        super(scope, id, props);  
        
        // Lambda function IAM/VPC
        let echoLambda = null;

        // Lambda: IAM Role
        const lambda_role = new iam.Role(this, NAME + 'LambdaExecutionRole', {
            assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com') 
        });

        lambda_role.addManagedPolicy( iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'));

       let env = {
           NEPTUNE_HOST: NEPTUNE_HOST,
           NEPTUNE_PORT: NEPTUNE_PORT,
           NEPTUNE_IAM_AUTH_ENABLED: NEPTUNE_IAM_AUTH.toString(),
           LOGGING_ENABLED: 'false',
           NEPTUNE_DB_NAME: NEPTUNE_DB_NAME,
           NEPTUNE_REGION: REGION,
           NEPTUNE_DOMAIN: this.parseNeptuneDomainFromHost(NEPTUNE_HOST),
           NEPTUNE_TYPE: NEPTUNE_TYPE,
       };
       if (NEPTUNE_IAM_AUTH) {
            // is IAM auth
            echoLambda = new lambda.Function(this, LAMBDA_FUNCTION_NAME, {
                functionName: LAMBDA_FUNCTION_NAME,
                description: 'Neptune GraphQL Resolver for AppSync',
                code: lambda.Code.fromAsset(LAMBDA_ZIP_FILE), 
                handler: 'index.handler',
                runtime: lambda.Runtime.NODEJS_18_X,
                timeout: Duration.seconds(15), 
                memorySize: 128, 
                environment: env,
                initialPolicy: [new iam.PolicyStatement({
                    sid: NAME + "NeptuneQueryPolicy",
                    effect: iam.Effect.ALLOW,
                    actions: [
                        NEPTUNE_TYPE + ':connect',
                        NEPTUNE_TYPE + ':DeleteDataViaQuery',
                        NEPTUNE_TYPE + ':ReadDataViaQuery',
                        NEPTUNE_TYPE + ':WriteDataViaQuery'
                    ],
                    resources: [NEPTUNE_IAM_POLICY_RESOURCE]
                })],
                roleArn: lambda_role.roleArn
            });
                        
        } else {
            // is VPC auth
            const neptune_vpc = ec2.Vpc.fromLookup(this, 'Neptune_VPC', {
                vpcId: NEPTUNE_DBSubnetGroup
            });
            
            lambda_role.addManagedPolicy( iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'));

           let subnets = NEPTUNE_DBSubnetIds.split(',').map((subnetId) => ec2.Subnet.fromSubnetId(this, 'neptuneSubnet-' + subnetId, subnetId));

            echoLambda = new lambda.Function(this, LAMBDA_FUNCTION_NAME, {
                functionName: LAMBDA_FUNCTION_NAME,
                description: 'Neptune GraphQL Resolver for AppSync',
                code: lambda.Code.fromAsset(LAMBDA_ZIP_FILE),
                handler: 'index.handler',
                runtime: lambda.Runtime.NODEJS_18_X,
                timeout: Duration.seconds(15),
                memorySize: 128,
                environment: env,
                vpc: neptune_vpc,
                vpcSubnets: {
                    subnets: subnets
                },
                securityGroups: [
                    ec2.SecurityGroup.fromSecurityGroupId(this, 'neptuneSecurityGroup', NEPTUNE_VpcSecurityGroupId)
                ],
                allowPublicSubnet: 'true',
                roleArn: lambda_role.roleArn
            });
        }
        
        echoLambda.node.addDependency(lambda_role);
        LAMBDA_ARN = echoLambda.functionArn;        

        // Appsync: GraphQL API
        const itemsGraphQLApi = new CfnGraphQLApi(this, NAME + 'API', {
            name: NAME + 'API',
            authenticationType: 'API_KEY'
        });
      
        // AppSync: Key
        new CfnApiKey(this, NAME + '-' + 'APIKEY', {
            apiId: itemsGraphQLApi.attrApiId
        });
      
        // AppSync: Schema
        const apiSchema = new CfnGraphQLSchema(this, NAME + 'Schema', {
            apiId: itemsGraphQLApi.attrApiId,
            definition: APPSYNC_SCHEMA
        });

        // AppSync: IAM Lambda invocation role
        const lambdaInvokationRole = new iam.Role(this, NAME + 'LambdaInvocationRole', {
            assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com')
        });
              
        lambdaInvokationRole.addToPolicy(
            new iam.PolicyStatement({
                effect: iam.Effect.ALLOW,                
                actions: ["lambda:invokeFunction"],            
                resources: [
                    LAMBDA_ARN,
                    LAMBDA_ARN + ":*"
                ]       
            })
        );
                
        // AppSync: DataSource
        const dataSource = new CfnDataSource(this, NAME + 'DataSource', {
            apiId: itemsGraphQLApi.attrApiId,
            name: NAME + 'DataSource',
            type: 'AWS_LAMBDA',
            lambdaConfig: {
                lambdaFunctionArn: LAMBDA_ARN,
            },
            serviceRoleArn: lambdaInvokationRole.roleArn
        });

        dataSource.node.addDependency(itemsGraphQLApi);
        dataSource.node.addDependency(lambdaInvokationRole);
        dataSource.node.addDependency(echoLambda);

               
        // AppSync: Function        
        const functionappSync = new CfnFunctionConfiguration(this, NAME + 'Function', {
            apiId: itemsGraphQLApi.attrApiId,
            dataSourceName: NAME + 'DataSource',
            name: NAME + 'Function',
            runtime: {
                name: "APPSYNC_JS",
                runtimeVersion: "1.0.0",
            },
            code:
`import { util } from '@aws-appsync/utils';
export function request(ctx) {
    const {source, args} = ctx
    return {
        operation: 'Invoke',
        payload: {
            field: ctx.info.fieldName, 
            arguments: args,
            selectionSetGraphQL: ctx.info.selectionSetGraphQL,
            source 
        },
    };
}
    
export function response(ctx) {
    return ctx.result;
}`
        });        

        functionappSync.node.addDependency(dataSource);
        
        // AppSync: attach resolvers to queries
        APPSYNC_ATTACH_QUERY.forEach(n => {
            const resolver = new CfnResolver(this, n + "Resolver", {
                apiId: itemsGraphQLApi.attrApiId,
                typeName: 'Query',
                fieldName: n,     
                kind: "PIPELINE",
                pipelineConfig: { 
                    functions: [ 
                        functionappSync.attrFunctionId
                    ]},        
                runtime: { 
                    name: "APPSYNC_JS",
                    runtimeVersion: "1.0.0", 
                },
                code:
`import {util} from '@aws-appsync/utils';

export function request(ctx) {
    return {};
}

export function response(ctx) {
    return ctx.prev.result;
}`
            });

            resolver.node.addDependency(functionappSync);
            resolver.node.addDependency(apiSchema);
        });

        // AppSync: attach resolvers to mutations
        APPSYNC_ATTACH_MUTATION.forEach(n => {
            const resolver = new CfnResolver(this, n + "Resolver", {
                apiId: itemsGraphQLApi.attrApiId, 
                typeName: 'Mutation', 
                fieldName: n,      
                kind: "PIPELINE",
                pipelineConfig: { 
                    functions: [ 
                        functionappSync.attrFunctionId
                    ]},        
                runtime: {
                    name: "APPSYNC_JS",
                    runtimeVersion: "1.0.0", 
                },
                code:
`import {util} from '@aws-appsync/utils';

export function request(ctx) {
    return {};
}

export function response(ctx) {
    return ctx.prev.result;
}`
            });

            resolver.node.addDependency(functionappSync);
            resolver.node.addDependency(apiSchema);
        });


    }