Documentation Index Fetch the complete documentation index at: https://mintlify.com/Antony-Figueroa/my-evershop-app/llms.txt
Use this file to discover all available pages before exploring further.
Introduction
GraphQL mutations allow you to modify data in your EverShop application. Unlike queries which are read-only, mutations perform write operations such as creating, updating, or deleting data.
Mutation Structure
Mutations in EverShop follow the standard GraphQL mutation syntax:
mutation MutationName {
mutationField ( argument : value ) {
field1
field2
}
}
Defining Mutations
Mutations are defined in your GraphQL schema files alongside queries:
Schema Definition
Resolver Implementation
type Foo {
id : ID !
name : String !
description : String
}
type Mutation {
createFoo ( name : String ! , description : String ): Foo
updateFoo ( id : ID ! , name : String , description : String ): Foo
deleteFoo ( id : ID ! ): Boolean
}
Mutation Examples
Create Mutation
Create a new resource in the system.
The name of the new Foo object
Optional description for the Foo object
Returns the newly created Foo object Auto-generated unique identifier
Name of the created object
Mutation
Response
With Variables
Variables
mutation CreateNewFoo {
createFoo ( name : "New Foo" , description : "A newly created object" ) {
id
name
description
}
}
Update Mutation
Update an existing resource.
The ID of the Foo object to update
New name for the object (optional)
New description for the object (optional)
Returns the updated Foo object
Mutation
Response
Partial Update
mutation UpdateFoo {
updateFoo ( id : "1" , name : "Updated Foo" ) {
id
name
description
}
}
Delete Mutation
Remove a resource from the system.
The ID of the Foo object to delete
Returns true if the deletion was successful
Mutation
Response
Error Response
mutation DeleteFoo {
deleteFoo ( id : "3" )
}
For complex mutations, use input types to group related fields:
Schema with Input Type
Usage
Variables
input CreateFooInput {
name : String !
description : String
category : String
tags : [ String ! ]
}
type Mutation {
createFoo ( input : CreateFooInput ! ): Foo
}
Mutation Context
Mutations have access to the same context object as queries:
export default {
Mutation: {
createFoo : ( root , { name , description }, context ) => {
// Access authenticated user
const userId = context . user ?. id ;
// Access database connection
const db = context . db ;
// Access request object
const headers = context . request . headers ;
// Implementation
return newFoo ;
}
}
} ;
Authorization
Implement authorization checks in your mutation resolvers:
export default {
Mutation: {
createFoo : ( root , { name , description }, context ) => {
// Check if user is authenticated
if ( ! context . user ) {
throw new Error ( 'Authentication required' );
}
// Check if user has permission
if ( ! context . user . hasPermission ( 'create_foo' )) {
throw new Error ( 'Insufficient permissions' );
}
// Proceed with mutation
return createNewFoo ( name , description );
}
}
} ;
Validation
Validate input data before processing:
export default {
Mutation: {
createFoo : ( root , { name , description }, context ) => {
// Validate required fields
if ( ! name || name . trim (). length === 0 ) {
throw new Error ( 'Name is required and cannot be empty' );
}
// Validate length
if ( name . length > 100 ) {
throw new Error ( 'Name must be 100 characters or less' );
}
// Validate format
if ( ! / ^ [ a-zA-Z0-9\s ] + $ / . test ( name )) {
throw new Error ( 'Name can only contain letters, numbers, and spaces' );
}
// Create the resource
return createNewFoo ( name , description );
}
}
} ;
Database Integration
Integrate mutations with database operations:
export default {
Mutation: {
createFoo : async ( root , { name , description }, context ) => {
const db = context . db ;
try {
// Insert into database
const result = await db . query (
'INSERT INTO foos (name, description) VALUES ($1, $2) RETURNING *' ,
[ name , description ]
);
return result . rows [ 0 ];
} catch ( error ) {
throw new Error ( `Failed to create Foo: ${ error . message } ` );
}
},
updateFoo : async ( root , { id , name , description }, context ) => {
const db = context . db ;
const updates = [];
const values = [];
let paramIndex = 1 ;
if ( name !== undefined ) {
updates . push ( `name = $ ${ paramIndex ++ } ` );
values . push ( name );
}
if ( description !== undefined ) {
updates . push ( `description = $ ${ paramIndex ++ } ` );
values . push ( description );
}
values . push ( id );
const query = `
UPDATE foos
SET ${ updates . join ( ', ' ) }
WHERE id = $ ${ paramIndex }
RETURNING *
` ;
const result = await db . query ( query , values );
if ( result . rows . length === 0 ) {
throw new Error ( `Foo with id ${ id } not found` );
}
return result . rows [ 0 ];
}
}
} ;
Best Practices
Use Descriptive Names Name your mutations clearly: createProduct, updateUser, deleteOrder
Return Created Objects Return the full object after creation/update for immediate use
Validate Input Always validate input data before processing mutations
Handle Errors Provide clear, actionable error messages
Use Transactions Wrap related database operations in transactions
Check Authorization Verify user permissions before allowing mutations
Error Handling
Mutations should provide clear error messages:
export default {
Mutation: {
createFoo : ( root , { name , description }, context ) => {
try {
// Validation
if ( ! name ) {
throw new Error ( 'Name is required' );
}
// Business logic validation
if ( isDuplicateName ( name )) {
throw new Error ( `A Foo with name " ${ name } " already exists` );
}
// Create the resource
return createNewFoo ( name , description );
} catch ( error ) {
// Log error for debugging
console . error ( 'Error creating Foo:' , error );
// Re-throw with user-friendly message
throw error ;
}
}
}
} ;
Testing Mutations
Test your mutations thoroughly:
// Example test
describe ( 'createFoo mutation' , () => {
it ( 'should create a new Foo' , async () => {
const result = await graphql ({
schema ,
source: `
mutation {
createFoo(name: "Test Foo", description: "Test description") {
id
name
description
}
}
` ,
contextValue: { user: mockUser }
});
expect ( result . data . createFoo ). toBeDefined ();
expect ( result . data . createFoo . name ). toBe ( 'Test Foo' );
});
it ( 'should reject creation without authentication' , async () => {
const result = await graphql ({
schema ,
source: `
mutation {
createFoo(name: "Test Foo") {
id
}
}
` ,
contextValue: {}
});
expect ( result . errors ). toBeDefined ();
expect ( result . errors [ 0 ]. message ). toContain ( 'Authentication required' );
});
});
Next Steps
GraphQL Queries Learn about querying data with GraphQL
GraphQL Overview Review GraphQL architecture and concepts