#✅ - How to auto-generate attributes in GraphQL mutations resolvers
15 messages · Page 1 of 1 (latest)
As a secondary issue, I am having trouble when mocking some queries for this API. I want to query with PK "owner" and SK "timestamp" but in my mock functions, they are returning empty lists while my other query (PK "type" SK "timestep") works.
Here is my schema:
type Post
@model (
mutations: {create: "createPost", delete: "deletePost", update: null}
timestamps: null
subscriptions: { level: public}
)
@auth(rules: [
{allow: owner, ownerField:"owner", provider: userPools, operations:[read, create, delete]}
{allow: private, provider: userPools, operations:[read]}
])
{
type: String! @index(name: "listPostsSortedByTimestamp", sortKeyFields: ["timestamp"])
id: ID! @primaryKey
content: String!
owner: String @index(name: "listPostsBySpecificOwner", sortKeyFields: ["timestamp"])
timestamp: Int!
}
I am attempting to follow this workshop:
https://amplify-sns.workshop.aws/en/30_mock/25_post_back_end_key.html
Hi @analog snow . Let's say you have the following schema:
type Todo
@model(
timestamps: { createdAt: "createdOn", updatedAt: "updatedOn" } ## <<-- for the timestamps
)
{
todoId: ID! @primaryKey ## <<-- for the autogenerated ID
content: String
}
The timestamps: {...} annotates your Model to tell Amplify which fields represent your timestamps. Amplify will then set this value on create and update operations for you.
You can find more about this here: https://docs.amplify.aws/cli/graphql/data-modeling/#customize-creation-and-update-timestamps
The todoId field will be assigned an autogenerated UUID since it is annotated with @primaryKey by default.
To achieve this, Amplify creates the following resolvers:
`MyApi/build/resolvers/Post.createPost.init.1.req.vtl`
`MyApi/build/resolvers/Post.updatePost.init.1.req.vtl`
The createPost.init.1.req.vtl would look like this:
## [Start] Initialization default values. **
$util.qr($ctx.stash.put("defaultValues", $util.defaultIfNull($ctx.stash.defaultValues, {})))
#set( $createdAt = $util.time.nowISO8601() )
$util.qr($ctx.stash.defaultValues.put("id", $util.autoId()))
$util.qr($ctx.stash.defaultValues.put("createdAt", $createdAt))
$util.qr($ctx.stash.defaultValues.put("updatedAt", $createdAt))
$util.toJson({
"version": "2018-05-29",
"payload": {}
})
## [End] Initialization default values. **
If you want to override these values you can set them yourself in a similar way. You would create an resolver for the init slot. For example,
Let's say your model is called Post, you would create a file resolvers/Mutation.createPost.init.X.req.vtl. If you want to replace the existing code, you would use the the same index (i.e. '1'). However, if you want to maintain the default behavior and add additional logic then you would replace X with 2 or any other index that wasn't already in use.
You can find out more about the slots here:
https://docs.amplify.aws/cli/graphql/custom-business-logic/#extend-amplify-generated-resolvers
NOTE
Preference is given to the input values over default values. So if these values are important to you then you can ensure that your value holds. You can:
- Clobber the input value with the generated value. For example, set the value for
$args.input.createdAtso that it replaces any user input. - Modify your schema so that you remove the values that you don't want the user to set as shown below. This will prevent the user from sending any values for the removed fields. Just don't forget to modify this to keep it in sync with your model as it evolves.
input TodoInput {
id: ID! ## <<-- remove this
name: String!
description: String
createdOn: AWSDateTime! ## <<-- remove this
updatedOn: AWSDateTime! ## <<-- remove this
}
Wow @jagged compass. Thank you for providing such a deep explanation and clearing a lot of this up, this was immensely helpful.
Here is my updated schema:
type Post
@model (
mutations: {create: "createPost", delete: "deletePost", update: null}
timestamps: { createdAt: "createdOn", updatedAt: "updatedOn" }
subscriptions: { level: public }
)
@auth(rules: [
{allow: owner, ownerField:"owner", provider: userPools, operations:[read, create, delete]}
{allow: private, provider: userPools, operations:[read]}
])
{
type: String! @index(name: "listPostsSortedByTimestamp", sortKeyFields: ["createdOn"])
id: ID! @primaryKey
content: String!
owner: String @index(name: "listPostsBySpecificOwner", sortKeyFields: ["createdOn"])
createdOn: AWSDateTime!
updatedOn: AWSDateTime!
}
I am now having issues with the indexes I have set up. I am returning no data for both after performing some createPost operations.
Happy to know this helped! 👍
To debug this I would suggest going to the the DynamoDB web console and checking the objects that are actually stored to see that they contain the data you expect. Verify that values exist for each of the fields in the indexes.
I am currently mocking the information through amplify CLI. I haven't been able to see the data in the console that i have been messing around with
FYI, for those who have relationships which are sorted on the built-in field 'createdAt'. ( to do this one has to add a createdAt field to the referenced model ) Some recent change to DataStore has made it so that one must pass a non-null dummy value for the 'createdAt' field when creating a new record. Prior to a week or two ago, the createdAt field could be left out of the DataStore.save(new MyModel, ...) call as one would expect and DataStore would update the record with the built-in fields.
✅ - How to auto-generate attributes in GraphQL mutations resolvers