Full Stack GraphQL - Part 1 Building a Prisma Data Model
Tags: graphql, database, node, beginners
Published: 2020-01-03 03:22:29

This blog post is part of a multi-part entry with the goal of creating a Full Stack Application using GraphQL. We will be building a catalog of recipes and have authentication in the form of JSON Web Tokens. This first part will cover the modeling of the data that Prisma uses to build the API.

The finished project will look similar to [this one](https://next-starter-tailwind.gregleeper19.now.sh/)! Let's get started 😎

###Getting Started

To speed our development, we will begin by starting from a [boilerplate](https://github.com/andrewjmead/graphql-boilerplate) by Andrew Mead. This boilerplate is about 18 months old at this point, so some things have changed since he released it. 

```
mkdir recipe-blog-post
cd recipe-blog-post/
git clone https://github.com/andrewjmead/graphql-boilerplate recipes-api
code .
```

In the above code we use the terminal to create a folder for the project, change our working directory to that folder, clone the repo & rename it, and then open the project in VSCode.

###Creating an Account with Prisma

In order to use the awesome services that Prisma offers, let's [create an account](https://app.prisma.io/signup) with them and then install the global Prisma CLI.

###Install the Prisma CLI

```
npm i -g prisma
```

Then we can initiate a new Prisma service in the Prisma Cloud by using the following command.

###Initiate a Prisma Cloud Service from the Command Line

```
prisma init prisma
```
Then select the Demo Server hosted in Prisma Cloud and follow the prompts in the cli interface. For the programming language in the generated Prisma client, I'm choosing Javascript.

This gives us a folder in the root directory called `prisma`. Within this folder we have generated files and folders. We will concentrate on `datamodel.prisma` for this post. There isn't an extension for syntax highlighting in VSCode for files with the `.prisma` extension, so let's change this file extension to `.graphql`. The file will now have the name `datamodel.graphql`. We can install the GraphQL extension from Prisma in VSCode to get syntax highlighting.

The contents of `datamodel.graphql` should look like this:

``` javascript

type User {
  id: ID! @id
  name: String!
}
```
We will replace the contents of `datamodel.graphql` with this:

``` javascript
type User {
  id: ID! @id
  name: String!
  email: String! @unique
  password: String!
  updatedAt: DateTime! @updatedAt
  createdAt: DateTime! @createdAt
  recipes: [Recipe!] @relation(name: "UserRecipes", onDelete: SET_NULL)
}

type File {
  id: ID! @id
  createdAt: DateTime! @createdAt
  updatedAt: DateTime! @updatedAt
  filename: String!
  mimetype: String!
  encoding: String!
  url: String! @unique
}

type Recipe {
  id: ID! @id
  title: String!
  handle: String! @unique
  description: String
  author: User! @relation(name: "UserRecipes", onDelete: SET_NULL)
  image: File @relation(name: "RecipeImage", onDelete: CASCADE)
  ingredients: [String!]! @scalarList(strategy: RELATION)
  directions: String
  categories: [Category!]!
    @relation(name: "RecipeCategories", onDelete: SET_NULL)
  tags: [Tag!]! @relation(name: "RecipeTags", onDelete: SET_NULL)
}

type Tag {
  id: ID! @id
  name: String!
  recipes: [Recipe] @relation(name: "RecipeTags", onDelete: SET_NULL)
}

type Category {
  id: ID! @id
  name: String!
  recipes: [Recipe] @relation(name: "RecipeCategories", onDelete: SET_NULL)
}
```
###Breaking Down the Data Model

The `type` keyword gives us a table in the database representing that entity. There are also several directives such as, `@unique` and `@id` that give Prisma a little more information about that field or type. More info on directives can be found in Prisma's documentation.

The relational data is annotated with the @relation directive. We have used this directive several times in the above code. This creates a relational table showing the connection between two entities. The relational tables are named according to the `name` argument in the `@relation` directive.

####Close Look at the User Type

Let's dig into the User type to better understand the directives and relations.
``` javascript
type User {
  id: ID! @id
  name: String!
  email: String! @unique
  password: String!
  updatedAt: DateTime! @updatedAt
  createdAt: DateTime! @createdAt
  recipes: [Recipe!] @relation(name: "UserRecipes", onDelete: SET_NULL)
}
```
The `!` on each field type means that the field cannot be null when the `User` is created. 

The `id` field will automatically be created by Prisma when a new User is created and using the ID! type along with the `@id` directive tells Prisma this will be the case.

The `name` field accepts a `String!`, and similarly the `email` and `password` fields accept a `String!`. The `email` field does a `@unique` directive meaning that an email address cannot be used on more than one `User`.

The `updatedAt` and `createdAt` fields both accept a `DateTime!` type and these are automatically generated by Prisma using the appropriate directives.

Lastly, we have the `recipes` field, which is a realtion to the `Recipe` type. The plural name of the field `recipes` is intentional as a `User` can have more than one `Recipe`. This is signified in the type portion of the `recipes` field as we have a set of `[Recipe!]`. The `!` inside the square brackets does have significant meaning here. It sets the API up so that the creation of a `User` does not have to link to any recipes (the field can be `null`), that is why there is no `!` outside the square brackets. Having the `!` inside the brackets means that when a mutation occurs where a set of recipes is linked to a user, the type must be `Recipe`.

The `@relation(name: "UserRecipes", onDelete: SET_NULL)` directive sets up a table named `UserRecipes` that connects a `User` to a `Recipe` on each row. The `Recipe` entity uses the same directive to connect the `Recipe` to the `author`. The rest of the `datamodel` file follows the same patterns as the `User` type.

##Changing the Prisma.yml File
 
Now that the datamodel is ready to go, we need to make a few changes the `prisma.yml` file. The contents will look like this:

```
endpoint: https://eu1.prisma.sh/recipe-catalog/whatever-your-path-is/dev
datamodel: datamodel.graphql

generate:
  - generator: graphql-schema
    output: ./generated/prisma-client/prisma.graphql
hooks:
  post-deploy:
    - prisma generate

```

##Deployment

Once the above changes are saved, we can run the command:
```
prisma delpoy
```

This will have Prisma generate the GraphQL schema, including all the resolvers. It also gives us an active GraphQL Playground to explore using the auto-generated resolvers, along with docs.

![GraphQL Playground](https://thepracticaldev.s3.amazonaws.com/i/ypcmac23zo9o3sqzj0tt.png)

##Summary

While we didn't use the boilerplate mentioned above in this post, it did give us a folder structure to work off of in subsequent entries. If you have any questions or comments, please let me know! My twitter handle is [@gregleeper](https://www.twitter.com/gregleeper).