Build and Deploy a GraphQL API to the Edge with MySQL and PlanetScale — Part 6
productDelete mutation
Now let's create the delete mutation resolver. We will first update the Grafbase Configuration to include the mutation productDelete
.
This mutation uses the ProductByInput
input type we created above for the updateProduct
mutation. This mutation will also return a new type — ProdudctDeletePayload
has a deleted
field that returns a boolean to represent the success of the deletion request.
const productDeletePayload = g.type('ProductDeletePayload', {
deleted: g.boolean()
})
g.mutation('productDelete', {
args: {
by: g.inputRef(productByInput)
},
resolver: 'products/delete',
returns: g.ref(productDeletePayload).optional()
})
Next, create the file grafbase/resolvers/products/delete.ts
and add the following:
import { connect } from '@planetscale/database'
import { GraphQLError } from 'graphql'
import { config, options } from '../../lib'
const conn = connect(config)
export default async function ProductsDelete(_, { by }) {
let statement: string = ''
let params: (string | number | boolean | {})[] = []
}
Here we import the necessary PlanetScale connection config, establish the connection and export a resolver function for ProductsDelete
that contains the following variables:
statement
— the SQL statement that will be executedparams
— the SQL values (id
orslug
) that will be used
Inside the function ProductsDelete
add the following:
Object.entries(by).forEach(([field, value]) => {
if (
value !== undefined &&
value !== null &&
(typeof value === 'string' || typeof value === 'number')
) {
statement = `DELETE FROM Products WHERE ${field} = ?`
params = [value]
}
})
if (!statement) {
throw new GraphQLError('ID or Slug must be provided')
}
This mostly follows the same patterns as above. If you were to use an ORM like Prisma or Drizzle the code wouldn't look so verbose.
Now we're ready to use the statement
and params
to execute against the database:
try {
const results = await conn.execute(statement, params, options)
if (results.rowsAffected === 1) {
return { deleted: true }
}
return { deleted: false }
} catch (error) {
return { deleted: false }
}
With that added, you should now have a delete.ts
that looks something like this:
import { connect } from '@planetscale/database'
import { GraphQLError } from 'graphql'
import { config, options } from '../../lib'
const conn = connect(config)
export default async function ProductsDelete(_, { by }) {
let statement: string = ''
let params: (string | number | boolean | {})[] = []
Object.entries(by).forEach(([field, value]) => {
if (
value !== undefined &&
value !== null &&
(typeof value === 'string' || typeof value === 'number')
) {
statement = `DELETE FROM Products WHERE ${field} = ?`
params = [value]
}
})
if (!statement) {
throw new GraphQLError('ID or Slug must be provided')
}
try {
const results = await conn.execute(statement, params, options)
if (results.rowsAffected === 1) {
return { deleted: true }
}
return { deleted: false }
} catch (error) {
return { deleted: false }
}
}
Now open Pathfinder and execute the following mutation:
mutation {
productDelete(by: { id: "7" }) {
deleted
}
}
Remember to use a valid id
or slug
.