Connecting a relationship using a hook in Keystone.js 6
I’m writing this for the weary internet traveler because I spent 3 hours debugging this and finally had some coffee ☕️ and figured it out after running into a ton of errors.
This is my desired outcome: every time a user signs up for my app, I want to associate the “Reader” role with that user. I had the option of doing this from the frontend but I would’ve had to run two mutations which isn’t ideal and I’m sure I was going to encounter a race condition in some cases.
The role list in my app can either be an “Admin”, “Reader”, or “Robot”. Pretty self-explanatory but I wanted to make sure all new users signing up are of the Reader role so they can’t mess with other users etc. Keystone does not come with a lot of built in control for this and I’m following Wes Bos’ example of Roles for Users.
Here’s the code:
// this is the Role schema
Role: list({
fields: {
name: text({ validation: { isRequired: true } }),
assignedTo: relationship({
ref: "User.role", // this is how the user is related to this list
many: true,
}),
},
}),
// this is the User schema, truncated to only show the Role relation
role: relationship({
ref: "Role.assignedTo",
hooks: {
resolveInput: async ({ resolvedData, operation, context }) => {
if (operation === "create") {
const reader = await context.query.Role.findMany({
where: { name: { equals: "Reader" } },
});
resolvedData.role = { connect: { id: reader[0].id } };
}
return resolvedData["role"];
},
},
}),
The part I was struggling with was a vague Prisma error like the following, the UI only said “Prisma error”
Unknown arg `role` in data.role for type UserUncheckedCreateInput. Did you mean `roleId`? Available args:
type UserUncheckedCreateInput {
id?: String
name?: String
username?: String
email?: String
password: String
roleId?: String | Null
readings?: ReadingUncheckedCreateNestedManyWithoutUserInput
}
I guess this error is not very helpful to someone running into this for the first time so my best understanding of it is that it’s due to the resolvedData
being returned incorrect. I was returning resolvedData
but instead needed to return resolvedData["role"]
where role is the field name.
Some terminology
Term | Description |
list | Keystone’s way of indicating tables, more documentation: https://keystonejs.com/docs/apis/config#lists |
field, or field name | A property on a list, aka a column in a table. |
Comments ()