in source/cdk-infrastructure/lib/front-end/appsync-api/appsync-api-construct.ts [26:183]
constructor(scope: Construct, id: string, props: AppSyncApiProps) {
super(scope, id);
const sourceCodeBucket = Bucket.fromBucketName(this, 'sourceCodeBucket', props.sourceCodeBucketName);
this.configTable = new Table(this, 'ConfigTable', {
partitionKey: { name: 'id', type: AttributeType.STRING },
sortKey: { name: 'type', type: AttributeType.STRING },
billingMode: BillingMode.PAY_PER_REQUEST,
stream: StreamViewType.NEW_AND_OLD_IMAGES,
removalPolicy: RemovalPolicy.DESTROY,
encryption: TableEncryption.AWS_MANAGED,
pointInTimeRecovery: true
});
this.uiReferenceTable = new Table(this, 'UIReferenceTable', {
partitionKey: { name: 'id', type: AttributeType.STRING },
sortKey: { name: 'type', type: AttributeType.STRING },
billingMode: BillingMode.PAY_PER_REQUEST,
stream: StreamViewType.NEW_AND_OLD_IMAGES,
removalPolicy: RemovalPolicy.DESTROY,
encryption: TableEncryption.AWS_MANAGED,
pointInTimeRecovery: true
});
this.realTimeDataTable = new Table(this, 'RealTimeDataTable', {
partitionKey: { name: 'id', type: AttributeType.STRING },
sortKey: { name: 'messageTimestamp', type: AttributeType.NUMBER },
timeToLiveAttribute: 'realTimeTableTTLExpirationTimestamp',
billingMode: BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.DESTROY,
encryption: TableEncryption.AWS_MANAGED,
pointInTimeRecovery: true
});
const graphqlApiLogRole = new Role(this, 'GraphqlApiLogRole', {
assumedBy: new ServicePrincipal('appsync.amazonaws.com'),
path: '/'
});
graphqlApiLogRole.addToPrincipalPolicy(new PolicyStatement({
effect: Effect.ALLOW,
actions: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
resources: [`arn:${Aws.PARTITION}:logs:${Aws.REGION}:${Aws.ACCOUNT_ID}:log-group:*`]
}));
this.graphqlApi = new GraphqlApi(this, 'GraphqlApi', {
name: `${Aws.STACK_NAME}-api`,
schema: Schema.fromAsset(`${__dirname}/schema.graphql`),
authorizationConfig: {
defaultAuthorization: {
authorizationType: AuthorizationType.IAM
}
},
logConfig: { fieldLogLevel: FieldLogLevel.NONE, excludeVerboseContent: false, role: graphqlApiLogRole }
});
const realTimeDataSourceLambda = new LambdaFunction(this, 'RealTimeDataSourceLambda', {
runtime: Runtime.NODEJS_14_X,
handler: 'data-sources/machine-detail.handler',
timeout: Duration.minutes(2),
description: 'AppSync data source for getting machine details over a longer period of time',
code: Code.fromBucket(sourceCodeBucket, [props.sourceCodeKeyPrefix, 'data-sources.zip'].join('/')),
environment: {
REAL_TIME_DATA_TABLE_NAME: this.realTimeDataTable.tableName,
SEND_ANONYMOUS_DATA: props.sendAnonymousData,
ANONYMOUS_DATA_UUID: props.anonymousDataUUID,
SOLUTION_ID: props.solutionId,
SOLUTION_VERSION: props.solutionVersion
}
});
// Suppress CFN Nag warnings
(realTimeDataSourceLambda.node.findChild('Resource') as CfnFunction)
.cfnOptions.metadata = {
cfn_nag: {
rules_to_suppress: [
{
id: 'W58',
reason: 'CloudWatch permissions are granted by the LambdaBasicExecutionRole'
},
{
id: 'W89',
reason: 'VPC for Lambda is not needed. This serverless architecture does not deploy a VPC.'
},
{
id: 'W92',
reason: 'ReservedConcurrentExecutions is not needed for this Lambda function.'
}
]
}
};
const configDataSource = this.graphqlApi.addDynamoDbDataSource('ConfigDataSource', this.configTable);
const uiReferenceDataSource = this.graphqlApi.addDynamoDbDataSource('UIReferenceDataSource', this.uiReferenceTable);
const realTimeDataSource = this.graphqlApi.addLambdaDataSource('RealTimeDataSource', realTimeDataSourceLambda);
this.realTimeDataTable.grantReadData(realTimeDataSourceLambda);
configDataSource.createResolver({
typeName: 'Query',
fieldName: 'getConfigItems',
requestMappingTemplate: MappingTemplate.dynamoDbScanTable(),
responseMappingTemplate: MappingTemplate.dynamoDbResultList()
});
configDataSource.createResolver({
typeName: 'Query',
fieldName: 'getConfigItem',
requestMappingTemplate: MappingTemplate.fromFile(`${__dirname}/get-item-req.vtl`),
responseMappingTemplate: MappingTemplate.fromFile(`${__dirname}/get-item-res.vtl`)
});
configDataSource.createResolver({
typeName: 'Mutation',
fieldName: 'updateMachineConfig',
requestMappingTemplate: MappingTemplate.fromFile(`${__dirname}/update-machine-config-req.vtl`),
responseMappingTemplate: MappingTemplate.dynamoDbResultItem()
});
uiReferenceDataSource.createResolver({
typeName: 'Query',
fieldName: 'getUIReferenceItems',
requestMappingTemplate: MappingTemplate.dynamoDbScanTable(),
responseMappingTemplate: MappingTemplate.dynamoDbResultList()
});
uiReferenceDataSource.createResolver({
typeName: 'Query',
fieldName: 'getUIReferenceItem',
requestMappingTemplate: MappingTemplate.fromFile(`${__dirname}/get-item-req.vtl`),
responseMappingTemplate: MappingTemplate.fromFile(`${__dirname}/get-item-res.vtl`)
});
uiReferenceDataSource.createResolver({
typeName: 'Mutation',
fieldName: 'updateUIReferenceItem',
requestMappingTemplate: MappingTemplate.fromFile(`${__dirname}/update-item-req.vtl`),
responseMappingTemplate: MappingTemplate.dynamoDbResultItem()
});
uiReferenceDataSource.createResolver({
typeName: 'Mutation',
fieldName: 'updateMachineName',
requestMappingTemplate: MappingTemplate.fromFile(`${__dirname}/update-machine-name-req.vtl`),
responseMappingTemplate: MappingTemplate.dynamoDbResultItem()
});
uiReferenceDataSource.createResolver({
typeName: 'Mutation',
fieldName: 'updateMachineGrouping',
requestMappingTemplate: MappingTemplate.fromFile(`${__dirname}/update-machine-grouping-req.vtl`),
responseMappingTemplate: MappingTemplate.dynamoDbResultItem()
});
realTimeDataSource.createResolver({
typeName: 'Query',
fieldName: 'getRealTimeMachineData'
});
}