Prisma’s 2.0.0-beta.2 is now included in RedwoodJS v0.5.0. One of the major Prisma updates is a new relation syntax with support for complex schema relations, which is covered in full with examples in the Prisma 2.0 Documentation.
As long as you are writing your own GraphQL SDL code, you can use all Prisma supported features in RedwoodJS today!
Using RWJS Generators with Prisma Beta.2
However, there are limitations to the Prisma relation support when using Redwood’s generators, specifically for 1) yarn rw g scaffold ...
and 2) yarn rw g sdl ...
and 3) yarn rw g service ...
.
Note: the Scaffold generator uses the SDL and Service generator. And the SDL generator uses the Service generator.
These generators will run correctly. However, when you try to use the associated CRUD UI (or your own UI, if applicable), you will encounter errors when trying to “save”.
Here’s what is going on.
Redwood supports relationships in SDL files the way you’d expect. For example, you can write queries like this:
posts {
id
title
body
user {
name
email
}
}
And the Redwood SDL generator, which calls to the Service generator, will make this work.
But when it comes to relationships between models in schema.prisma
, Prisma doesn’t allow you to save the foreign key field on any Scaffolds that you generate.
Example Schema Using @relation
With Prisma Beta.2, the schema.prisma
now supports these models (Note the @relation
on post.user
below):
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String @unique
body String
user User @relation(fields: [userId], references: [id])
userId Int
}
Using Redwood’s generators to build a CRUD scaffold for Post, you can successfully run yarn rw g scaffold post
. But when you run yarn rw dev
, and then try to create a new post and save from the UI, you’ll get an error.
Looking at the Service file the Redwood generator created, api/src/service/posts.js
, here’s what the mutation looks like to create a new post:
export const createPost = ({ input }) => {
return db.post.create({
data: input,
})
}
And the corresponding posts.sdl.js
:
type Post {
id: Int!
title: String!
body: String!
user: User!
userId: Int!
}
The issue is with Redwood’s use of userID
. We are unable to create a new record by using the foreign key of another table. In this case, where Post
has a userId
column, we cannot just set the userId
and save the record.
We have opened a GitHub issue with Prisma to request support for our Generator use case. You can learn more and follow along here.
A Workaround
'Cause we know you’re still going to use Generators…
If you would still like to use Redwood’s generators for this type of schema, our very own @rob has devised a workaround, aka a Handy-Dandy-Hack™. You’ll need to use the following to modify your create and update functions in your Redwood generated Services by running input
through this:
const foreignKeyReplacement = (input) => {
let output = input
const foreignKeys = Object.keys(input).filter((k) => k.match(/Id$/))
foreignKeys.forEach((key) => {
const modelName = key.replace(/Id$/, '')
const value = input[key]
delete output[key]
output = Object.assign(output, {
[modelName]: { connect: { id: value } },
})
})
return output
}
Applied to your own posts.js
, your code would look like this:
// api/src/services/posts/posts.js
import { db } from 'src/lib/db'
// super hacky workaround function by @rob 🚀
const foreignKeyReplacement = (input) => {
let output = input
const foreignKeys = Object.keys(input).filter((k) => k.match(/Id$/))
foreignKeys.forEach((key) => {
const modelName = key.replace(/Id$/, '')
const value = input[key]
delete output[key]
output = Object.assign(output, {
[modelName]: { connect: { id: value } },
})
})
return output
}
...
// create Post example using the workaround
export const createPost = ({ input }) => {
return db.post.create({
data: foreignKeyReplacement(input),
})
}
...
This is only a limited example for Post create. To fully implement this workaround, you will need to add this to all cases where you used the Generator on a model resulting in Service files with ‘create’ and ‘update’ functions.
Generators Now Support Forms Using Int
Type
Previously, if your schema contained an Int
field and you used the Scaffold generator, you would encounter a GraphQL error when submitting the corresponding form including the Int
input. The GraphQL API would be expecting type Int
, however, the input form would return a type string
(even though it was validating the input for Int
).
Now the Redwood generators correctly cast the type to Int
on form submit. For example:
const onSubmit = (input) => {
const castInput = Object.assign(input, { userId: parseInt(input.userId) })
createPost({ variables: { input: castInput } })
}
If you are manually creating forms, we recommend you cast to the required type in the
onSubmit
form handler.
Hope this helps! Any questions?