rygo6
rygo6

Reputation: 2019

Returning Appsync GraphQL type that also has field resolvers

I would like to return the ImageSet type from the AddImageSet mutation. But I seem to be unable to do this because each field on my ImageSet type has it's own resolver, which is overwriting the resolver mapping template.

Schema:

type ImageSet {
    SetKey: ID
    SetName: String
    SetCreatedAt: AWSTimestamp
    SetDescription: String
    SetTags: [Tag]
}

type Mutation {
    AddImageSet(setName: String!, setDescription: String): ImageSet
}

Here is the mutation:

{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "PartitionKey" : { "S" : "ImageSet" },
        "SortKey" : { "S" : "ImageSet-$util.autoId()" }
    },
    "attributeValues" : {
        "Name": { "S" : "${context.arguments.setName}" },
        "Description": { "S" : "${context.arguments.setDescription}" },
        "CreatedAt": { "N" : $util.time.nowEpochSeconds() },
    }
}

and the response mapping template

{
    "SetKey" : "$context.result.SortKey",
    "SetName" : "$context.result.Name",
    "SetCreatedAt" : $context.result.CreatedAt,
    "SetDescription" : "$context.result.Description"
}

When I run this, the object returned by AddImageSet mutation has every field set as null, because the field resolvers are overwriting the response mapping template of the AddImageSet mutation.

I have solved this by creating a duplicate 'ImageSetResult' type, just without resolvers attached to the field. Then if the AddImageSet Mutation returns that, everything is just fine. But these seems kind of redundant.

Is there a better way to do this?

Upvotes: 3

Views: 981

Answers (1)

mparis
mparis

Reputation: 3683

This is expected behavior in GraphQL. If you have a resolver on ImageSet.SetKey and your Mutation.AddImageSet mutation returns an object of type ImageSet, the resolver of every field listed in the selection set will be invoked. The values returned by Mutation.AddImageSet will be overwritten by whatever values are returned by the child resolvers.

To add more context, the value that you are returning from the Mutation.AddImageSet response mapping template will be the value of $ctx.source when you are in the ImageSet.SetKey/SetName/SetCreatedAt resolvers. From those resolvers you could then do something like this:

#if( $ctx.source.SetKey ) "$ctx.source.SetKey" #else .. whatever SetKey does .. #end

Is there a reason you need resolvers on SetKey/SetName/etc? If the object is already being returned by Mutation.AddImageSet or Query.AddImageSet etc then you do not need resolvers on that type.

Another note. Is there a reason you want the names ImageSet.SetName instead of just ImageSet.Name which is how you storing it in DynamoDB? This seems to be adding a lot of complexity where you can probably avoid it.

Upvotes: 4

Related Questions