- Introduction
- Overview of GraphQL Entities and Resolvers
- Creating Data Provider Entities
- Defining GraphQL Entities for Different Data Providers
- Creating GraphQL Entities
- Linking GraphQL Entities to Data Provider Entities
- Customizing GraphQL Entities and Resolvers
- Field Resolver
- Conclusion
Introduction
GraphQL entities and resolvers play a vital role in the Graphweaver framework.
They are responsible for defining the data schema and handling data operations in GraphQL APIs.
By understanding how to create and customize these entities and resolvers, you can unleash the full potential of GraphQL in your applications.
Overview of GraphQL Entities and Resolvers
In GraphQL, entities represent the objects or data types in your system. They define the fields and relationships that can be queried and mutated.
Resolvers, on the other hand, are responsible for resolving the queries and mutations against the underlying data sources.
GraphWeaver simplifies the creation and integration of entities and resolvers by providing a set of tools and abstractions. It allows you to define entities for different data providers, such as databases (MySQL, PostgreSQL) and external services (REST, Xero). You can connect these entities to the GraphQL layer and map data sources to GraphQL attributes.
Creating Data Provider Entities
To start with, you need to create entities in the respective data providers. For example, if you're working with a MySQL database, you would create a database entity to represent a table. This entity defines the attributes and structure of the data in the database.
There is more on this in the data entities section.
For this example we will look to create a GraphQL entity and resolver for a Task
data entity. This data entity is a table held in MySQL database, it looks like this:
import { BigIntType, Entity, PrimaryKey, Property } from '@mikro-orm/core';
import { BaseEntity, ExternalIdField } from '@exogee/graphweaver-mikroorm';
@Entity()
export class Task extends BaseEntity {
@PrimaryKey({ type: BigIntType })
id!: string;
@Property({ type: String })
description!: string;
@ExternalIdField({ from: 'user' })
@Property({ type: BigIntType })
userId!: string;
}
Now we have defined the data entity we can attach it to a GraphQL entity.
Defining GraphQL Entities for Different Data Providers
In Graphweaver, you can define GraphQL entities to expose the data from the data providers. The process involves creating GraphQL entities that correspond to the data provider entities.
Letβs look at connecting the Task
data entity from above.
Creating GraphQL Entities
To expose the data provider entity, you need to create a GraphQL entity in your project. This entity represents the data structure that will be exposed through the GraphQL API.
Start by creating a new directory in ./src/schema
for the entity. Inside this directory, create three files:
entity.ts
: This file defines the attributes that will be exposed in the GraphQL API.resolver.ts
: This file connects the GraphQL entity to the data provider entity by creating a resolver.index.ts
: This file exports the entity and resolver files.
For example, let's create a Task
GraphQL entity:
import { GraphQLEntity, RelationshipField } from '@exogee/graphweaver';
import { Field, ID, ObjectType } from 'type-graphql';
import { Task as OrmTask } from '../../entities';
import { User } from '../user';
@ObjectType('Task')
export class Task extends GraphQLEntity<OrmTask> {
public dataEntity!: OrmTask;
@Field(() => ID)
id!: string;
@Field(() => String)
description!: string;
@RelationshipField<Task>(() => User, { id: 'userId' })
user!: User;
}
In the above code, we define the Task
GraphQL entity by extending the GraphQLEntity
class and specifying the corresponding data provider entity (OrmTask
this is the Tasks data entity we created earlier).
The attributes are decorated with @Field
to expose them in the GraphQL schema. For more on decorators and their usage see the decorators section.
Now we have a Data Provider Entity and a GraphQL Entity. The next task is to create a resolver that will be used by the Queries and Mutations.
Linking GraphQL Entities to Data Provider Entities
To connect the GraphQL entity to the data provider entity, we need to create a resolver. The resolver acts as the bridge between the GraphQL schema and the data provider.
In the resolver.ts
file, you can create a resolver class for the GraphQL entity:
import { createBaseResolver } from '@exogee/graphweaver';
import { MikroBackendProvider } from '@exogee/graphweaver-mikroorm';
import { Resolver } from 'type-graphql';
import { Task as OrmTask } from '../../entities';
import { Task } from './entity';
@Resolver((of) => Task)
export class TaskResolver extends createBaseResolver<Task, OrmTask>(
Task,
new MikroBackendProvider(OrmTask, 'my')
) {}
Here, we create a TaskResolver
class that extends createBaseResolver
. The resolver takes two parameters: the GraphQL entity (Task
) and the data provider used to fetch data (MikroBackendProvider
). This establishes the connection between the GraphQL entity and the data provider entity.
After connecting all the parts, export the resolver in ./index.ts
to expose the Driver GraphQL entity through the API. The resolver will provide functions for common operations like Get One, List, Create, Update, and Delete.
Customizing GraphQL Entities and Resolvers
There may be cases where you need to extend an entity with custom queries or mutations.
Graphweaver allows you to create custom queries and mutations in addition to the ones provided by the BaseResolver.
To create custom queries/mutations, add the desired functionality within the resolver class. You can define custom resolver methods and decorate them accordingly.
Here's an example of creating a custom mutation createTaskWithValidation
in the TaskResolver
:
import { createBaseResolver } from '@exogee/graphweaver';
import { MikroBackendProvider } from '@exogee/graphweaver-mikroorm';
import { Resolver } from 'type-graphql';
import { Task as OrmTask } from '../../entities';
import { Task } from './entity';
@Resolver((of) => Task)
export class TaskResolver extends createBaseResolver<Task, OrmTask>(
Task,
new MikroBackendProvider(OrmTask, 'mysql-connection-1')
) {
@Mutation((returns) => Task)
@Authorized()
async createTaskWithValidation(
// Custom mutation parameters
) {
// Custom mutation logic
}
}
In the above code, we define the createTaskWithValidation
mutation within the TaskResolver
.
This custom mutation performs specific backend logic, such as validating the input with custom business logic before creating a task.
The @Mutation
decorator exposes the custom mutation in the GraphQL schema.
By adding custom queries and mutations, you can tailor the functionality of your GraphQL API to meet your specific requirements.
Field Resolver
Sometimes you will have a requirement to combine two attributes or to compute a new property.
To do this you can use a Field Resolver.
Here is an example of returning two combined values for the Task
entity and creating a new property called slug
:
import {
GraphQLEntity,
RelationshipField,
Field,
ID,
ObjectType,
Root
} from '@exogee/graphweaver';
import { Task as OrmTask } from '../../entities';
import { User } from '../user';
@ObjectType('Task')
export class Task extends GraphQLEntity<OrmTask> {
public dataEntity!: OrmTask;
@Field(() => ID)
id!: string;
@Field(() => String)
description!: string;
@Field(type => String, { nullable: true })
slug(@Root() task: Task) {
return `${task.id}:${task.description}`;
}
@RelationshipField<Task>(() => User, { id: 'userId' })
user!: User;
}
As you can see from the above the field resolver is a function, in here you can do any logic required to return the computed value.
Conclusion
In this article, we explored the creation and customization of GraphQL entities and resolvers in Graphweaver.
We learned how to create data provider entities, define GraphQL entities for different data providers, connect them to the data sources, and create resolvers.
Additionally, we explored the process of adding custom queries and mutations to extend the functionality of the API.
By leveraging the power of GraphQL entities and resolvers, you can build robust and scalable GraphQL APIs that seamlessly integrate with various data providers. Graphweaver simplifies this process by providing a unified framework and tools to handle the complexities of data operations.
Start implementing GraphQL entities and resolvers in your Graphweaver projects and unlock the full potential of GraphQL in your applications.