AWSTemplateFormatVersion: 2010-09-09 Description: AppSync setup Parameters: FunctionStack: Description: The stack name that deploys the Lambda functions to invoke. Type: String Resources: DataSourceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: appsync.amazonaws.com Policies: - PolicyName: LambdaInvoker PolicyDocument: Version: 2012-10-17 Statement: - Action: lambda:InvokeFunction Effect: Allow Resource: - Fn::Join: - '' - - 'arn:aws:lambda:' - !Ref AWS::Region - ':' - !Ref AWS::AccountId - ':function:' - Fn::ImportValue: !Sub '${FunctionStack}-functions-Product' - Fn::Join: - '' - - 'arn:aws:lambda:' - !Ref AWS::Region - ':' - !Ref AWS::AccountId - ':function:' - Fn::ImportValue: !Sub '${FunctionStack}-functions-Product' - ':*' RoleName: !Sub '${AWS::StackName}-lambda-role' GqlApi: Type: AWS::AppSync::GraphQLApi Properties: AuthenticationType: AWS_IAM Name: !Ref AWS::StackName GqlSchema: Type: AWS::AppSync::GraphQLSchema Properties: ApiId: !GetAtt GqlApi.ApiId Definition: | type Mutation { } type Query { getProduct(productId: String, cognitoIdentityId__: String): Product } input BreadcrumbInput { link: String name: String position: Int } type Breadcrumb { link: String name: String position: Int } input ColorInput { fill: String id: String name: String position: Int } type Color { fill: String id: String name: String position: Int } input DetailInput { iconHandle: String tech: [TechInput] title: String } type Detail { iconHandle: String tech: [Tech] title: String } input ImageInput { alt: String id: Int position: Int src: String } type Image { alt: String id: Int position: Int src: String } input PriceInput { isDiscounted: Boolean msrp: String percentOff: String price: String } type Price { isDiscounted: Boolean msrp: String percentOff: String price: String } input ProductInput { breadcrumbs: [BreadcrumbInput] colors: [ColorInput] createdAt: String description: String descriptionHtml: String details: [DetailInput] gender: String handle: String id: Int images: [AWSJSON] itemCount: Int productType: String sizes: [SizeInput] title: String updatedAt: String variants: [VariantInput] } type Product { breadcrumbs: [Breadcrumb] colors: [Color] createdAt: String description: String descriptionHtml: String details: [Detail] gender: String handle: String id: Int images: [AWSJSON] itemCount: Int productType: String sizes: [Size] title: String updatedAt: String variants: [Variant] } input ShippingInput { grams: Int requiresShipping: Boolean weight: Int weightUnit: String } type Shipping { grams: Int requiresShipping: Boolean weight: Int weightUnit: String } input SizeInput { name: String values: [SizeValuesInput] } type Size { name: String values: [SizeValues] } input SizeValuesInput { guidance: String id: String name: String } type SizeValues { guidance: String id: String name: String } input TechInput { content: String handle: String title: String } type Tech { content: String handle: String title: String } input VariantInput { createdAt: String id: Int isAvailable: Boolean price: PriceInput productId: Int shipping: ShippingInput sizes: [SizeInput] sku: String title: String updatedAt: String } type Variant { createdAt: String id: Int isAvailable: Boolean price: Price productId: Int shipping: Shipping sizes: [Size] sku: String title: String updatedAt: String } schema { query: Query mutation: Mutation } DependsOn: - GqlApi ProductDataSource: Type: AWS::AppSync::DataSource Properties: ApiId: !GetAtt GqlApi.ApiId LambdaConfig: LambdaFunctionArn: Fn::Join: - '' - - 'arn:aws:lambda:' - !Ref AWS::Region - ':' - !Ref AWS::AccountId - ':function:' - Fn::ImportValue: !Sub '${FunctionStack}-functions-Product' Name: product_lambda ServiceRoleArn: !GetAtt DataSourceRole.Arn Type: AWS_LAMBDA DependsOn: - DataSourceRole - GqlApi GetProductResolver: Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt GqlApi.ApiId FieldName: getProduct TypeName: Query DataSourceName: !GetAtt ProductDataSource.Name RequestMappingTemplate: | #set( $cognitoIdentityId = $context.identity.cognitoIdentityId ) #if($context.identity.userArn.matches('arn:aws:iam::\d+:user/.*')) #if($context.args.cognitoIdentityId__) #set( $cognitoIdentityId = $context.args.cognitoIdentityId__ ) #elseif( $context.source.cognitoIdentityId__ ) #set( $cognitoIdentityId = $context.source.cognitoIdentityId__ ) #end #end #set( $unamepwd = "$util.urlEncode($cognitoIdentityId):" ) { "version" : "2017-02-28", "operation": "Invoke", "payload": { "source": "AppSync", "httpMethod": "get", "headers": { "Authorization": "Basic $util.base64Encode($unamepwd)", }, "pathParameters": { "productId": "$util.escapeJavaScript($context.args.productId)" }, "queryStringParameters": { } } } ResponseMappingTemplate: | #if($context.result.statusCode >= 200 && $context.result.statusCode <= 299) #set( $result = $util.parseJson($context.result.body) ) #if($context.args.cognitoIdentityId__) #set( $result.cognitoIdentityId__ = $context.args.cognitoIdentityId__ ) #elseif($context.source.cognitoIdentityId__) #set( $result.cognitoIdentityId__ = $context.source.cognitoIdentityId__ ) #end $util.toJson($result) #else $utils.error($util.parseJson($context.result.body).message, $context.result.statusCode.toString(), $util.parseJson($context.result.body)) #end DependsOn: - GqlApi - GqlSchema - ProductDataSource Outputs: ApiEndpoint: Description: The endpoint for the AppSync API. Value: !GetAtt GqlApi.GraphQLUrl