Extend your Platformatic API with Prisma Client
Tags: node, prisma, platformatic
Published: 2022-12-16 11:22:17

---
title: Extend your Platformatic API with Prisma Client
published: true
description: Learn how you can extend your auto-generated REST and GraphQL API by Platformatic using Prisma Client
tags: nodejs, prisma, platformatic
series: Prisma and Platformatic
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbnzk7t8hr2su606tclz.png
---

In this part, you will learn how to extend the auto-generated GraphQL and REST API by Platformatic using [Prisma Client](https://www.prisma.io/docs/concepts/components/prisma-client).

You will create a GraphQL mutation and a REST API endpoint to increment the views on a post record.

If you're interested in learning how to use Prisma to model your database schema and auto-generate database migrations when working with Platformatic, refer to [part 2](https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib) of this series.

> **Note**: It is recommended you type out the changes over copying and pasting the code.

## Prerequisites

### Your dev toolbox

To follow along, ensure you have the following installed:
- Node.js v18 or later
- npm v7 or later
- [Prisma VSCode Extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) (_optional_)
- [Thunder Client VSCode Extension](https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client) (_optional_)
- Docker (_optional_)

> Note: If you don't have Docker installed, you can set up a free hosted database on [Railway](https://railway.app/) or install [PostgreSQL](https://www.postgresql.org/download/).

### Assumed knowledge

This guide will require you have basic familiarity in the following technologies:
- JavaScript
- GraphQL APIs
- REST APIs

## Set up your Platformatic API

The starting point of this tutorial is [part 2](https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib) of this series. If you're following along from the previous part, you can jump to [Extend the functionality of your API with a plugin](#extend-the-functionality-of-your-api-with-plugins) section of this guide.

In this tutorial, you'll use the following starter [repository](https://github.com/ruheni/prisma-platformatic/tree/automated-migrations). It contains the setup files for a new Platformatic project.

To get started, clone the repository and checkout to the [`automated-migrations`](https://github.com/ruheni/prisma-platformatic/tree/extend-plugin) branch.

Clone the repository:

```bash
git clone -b extend-plugin https://github.com/ruheni/prisma-platformatic.git
```

Now, perform the following actions to get started:

1. Navigate to the cloned directory:

    ```
    cd prisma-platformatic
    ```

2. Install dependencies:

    ```bash
    npm install
    ```

3. Create a `.env` file based-off of the `.env.example` file:

    ```
    cp .env.example .env
    ```

4. Start the PostgreSQL database with docker:

    ```
    docker-compose up -d
    ```


    > **Note**: If you already have an existing database server running locally, update the value of the `DATABASE_URL` in the `.env` file with your database's user and password values:
    >
    >```
    > DATABASE_URL="postgres://<USER>:<PASSWORD>@localhost:5432/blog"
    >```
    >
    > Connect to your database instance using `psql` or your preferred SQL client. Copy and run the following SQL to create a database:
    > ```sql
    >CREATE DATABASE blog;
    >```

1. Generate an `up` and `down` migration:
    ```
    npx db-diff
    ```

1. Apply the `up` migration to your database:
    ```
    npx platformatic db migrations apply
    ```

1. Populate the database with sample data:
    ```
    npx platformatic db seed seed.js
    ```
   > **Note**: If you're following along from the previous part, you can skip this step.
1. Generate Prisma Client:
    ```
    npx prisma generate
    ```

### Project structure and files

The project has the following structure:
The important files in the directory are:

- `.env`: Contains the database connection string for your PostgreSQL database.
- `docker-compose.yml`: Defines the Docker image and configuration for your PostgreSQL database.
- `package.json`: Defines your application dependencies. [`platformatic`](http://npmjs.com/package/platformatic) is currently the only dependency in the project.
- `platformatic.db.json`: Defines [Platformatic's configuration](https://oss.platformatic.dev/docs/reference/service/configuration) such as the server's hostname and port, migration directory, and your database's connection string.
- `seed.js`: Contains a script for populating the database with seed data.
- `schema.prisma`: Defines the structure of your database schema.

The `schema.prisma` file contains two models: `User` and `Post`, with a one-to-many relation.

## Extend the functionality of your API with plugins

### Define the `plugin` property in your `platformatic.db.json` file

The first step is defining the plugin configuration in your `platformatic.db.json` file. Paste the following snippet to in your configuration file right after the `migrations` property:

```json
  "plugin": {
    "path": "./plugin.js"
  }
```

{% details Expand to view the entire file %} 

```json
{
  "server": {
    "logger":{
      "level": "info"
    },
    "hostname": "127.0.0.1",
    "port": "3042"
  },
  "core": {
    "connectionString": "{DATABASE_URL}"
  },
  "migrations": {
    "dir": "./migrations"
  },
  "plugin": {
    "path": "plugin.js"
  }
}

```
{% enddetails %}

The snippet defines the path to your plugin. The plugin will be registered when your server starts, exposing the custom logic you've defined.

### Create a plugin

At the root of your directory, create a new file called `plugin.js`. Paste  the following snippet to your plugin file:

```js
// ./plugin.js
module.exports = async (app) => {
  app.log.info('plugin loaded')
}
```

The file exports an async function with an `app` parameter that's a [`FastifyInstance`](https://www.fastify.io/docs/latest/Reference/Server/#instance).

When you you start up Platformatic with `npx platformatic db start`, Platformatic will register the plugin. "plugin loaded" will also be logged to your console.

With everything set up, let's take a look at how you can extend your API using Prisma Client.

## Extend the GraphQL API

You'll extend the GraphQL API by defining a mutation called `incrementPostViewCount`. The mutation will have one argument, `id` that is an `ID` type. The mutation response type will be a `Post` object type.

To implement the GraphQL mutation, make the following changes to your `plugin.js` file:

```js
// ./plugin.js

// 1. 
const { PrismaClient } = require("@prisma/client")

// 2
const prisma = new PrismaClient()

module.exports = async (app) => {
  app.log.info('plugin loaded')

  //3.
  app.graphql.extendSchema(`
    extend type Mutation {
      incrementPostViewCount(id: ID): Post
    }
  `)
  
  //4.
  app.graphql.defineResolvers({
    Mutation: {
      incrementPostViewCount: async (_, { id }) => {
        // 5. 
        const post = await prisma.post.update({
          where: {
            id: Number(id)
          },
          data: {
            viewCount: {
              increment: 1
            }
          }
        })

        // 6.
        if (!post) throw new Error(`Post with id:${id} was not found`)
        // 7.
        return post
      }
    }
  })
}
```

The above snippet does the following:
1. Imports Prisma Client.
1. Creates a new instance of Prisma Client.
1. Defines the `incrementPostViewCount` mutation type definition. It also defines the corresponding argument and the return type.
1. Defines the resolver for your mutation.
1. Makes a query to the database on the `Post` model to increment a post's view count.
1. Adds error handling in the event a record with the matching id was not found.
1. Returns the updated post on success.


As you're defining the `incrementPostMutation` resolver, you will notice Prisma Client provides auto-completion. On hovering on the `incrementPostViewCount` resolver and `post` variable, VS Code infers the types for you.

You can head over to [`http://localhost:3042/graphiql`](http://localhost:3042/graphiql) to try out the mutation you just created.

```graphql
mutation INCREMENT_POST_VIEWS {
  incrementPostViewCount(id: 1){
    id 
    title
    viewCount
  }
}
```

{% details Expand to view the response %} 

```json
{
  "data": {
    "incrementPostViewCount": {
      "id": "1",
      "title": "Prisma 💚 Platformatic",
      "viewCount": 1
    }
  }
}
```
{% enddetails %}

## Extend the REST API

Next, you'll extend the REST API by defining an endpoint that will accept `PUT` requests to increment the views of a post.

To implement the REST endpoint, update `./plugin.js` file with the following snippet:

```js
// ./plugin.js
const { PrismaClient } = require("@prisma/client")

const prisma = new PrismaClient()

module.exports = async (app) => {
  app.log.info('plugin loaded')

  // ...GraphQL API

  // 1. 
  app.put('/post/:id/views', async (req, reply) => {
    // 2. 
    const { id } = req.params
    // 3. 
    const post = await prisma.post.update({
      where: {
        id: Number(id)
      },
      data: {
        viewCount: {
          increment: 1
        }
      }
    })

    // 4.
    if (!post) reply.code(404).send({ error: `Post with id:${id} was not found` })
     // 5.
    return reply.send(post)
  })
}
```

The above code does the following:
1. Defines the route for incrementing a post's views.
1. Retrieves the `id` from the request parameters.
1. Makes a query to the database on the `Post` model to increment the post's view count.
1. Adds error handling in the event a record with the matching id was not found.
1. Returns the updated post on success.

{% details Expand to see the diff %}

```diff
const { PrismaClient } = require("@prisma/client")

const prisma = new PrismaClient()

module.exports = async (app) => {
  app.log.info('plugin loaded')

  app.graphql.extendSchema(`
    extend type Mutation {
      incrementPostViewCount(id: ID): Post
    }
  `)
  
  //4.
  app.graphql.defineResolvers({
    Mutation: {
      incrementPostViewCount: async (_, { id }) => {
        // 5. 
        const post = await prisma.post.update({
          where: {
            id: Number(id)
          },
          data: {
            viewCount: {
              increment: 1
            }
          }
        })

        // 6.
        if (!post) throw new Error(`Post with id:${id} was not found`)
        // 7.
        return post
      }
    }
  })

+  // 1. 
+  app.put('/post/:id/views', async (req, reply) => {
+    // 2.
+    const { id } = req.params
+    // 3.
+    const post = await prisma.post.update({
+      where: {
+        id: Number(id)
+      },
+      data: {
+        viewCount: {
+          increment: 1
+        }
+      }
+    })
+    // 4. 
+    if (!post) reply.code(404).send({ error: `Post with id:${id} was not found` })
+    // 5. 
+    return reply.send(post)
+  })
}
```

{% enddetails %}
You can head over to [`http://localhost:3042/documentation`](http://localhost:3042/documentation) to view the Swagger docs. You should see the endpoint you just created.


![Platformatic  auto-generated Swagger documentation](https://user-images.githubusercontent.com/33921841/204011764-c569e9a4-96f2-47dd-bdeb-9c29bd52d964.png)

To try out the endpoint you just created, you can make a request to your endpoint using `curl`: 
```
curl -X PUT \
  'localhost:3042/post/2/views' \
  --header 'Accept: */*' \
  --header 'Content-Type: application/json' 
```

You can also use Thunder Client on VS Code to run the request. To make a request:

1. Open up Thunder Client on VS Code.
2. Create a new request by clicking **New Request** button on the side bar.
3. Select the `PUT` method.
4. Enter it to the following URL: `http://localhost:3042/post/1/views`.
5. Click **Send**.

You should see the following output on your editor:

![Thunder Client `PUT` request](https://user-images.githubusercontent.com/33921841/204013519-a088f09e-586b-4f25-b8cd-68d194133cbd.png)

## Recap and next steps

Congratulations! 🎉
Using Prisma Client, you've successfully extended the GraphQL and REST APIs generated with Platformatic API.

In case you missed it, check out [part 2](https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib) to learn how you can use Prisma to:
- Model your database schema
- Auto-generate fully customizable SQL migrations

You can find the source code for this project on [GitHub](https://github.com/ruheni/platformatic-prisma). If you run into any challenges, feel free to create a GitHub issue or contribute to the repository. You can also reach out to me directly on [Twitter](https://twitter.com/ruheni_alex)