- Overview
- Architecture and Functionality
- Architecture of Graphweaver
- Functionality of Graphweaver
- Graphweaver API
- Query Operations
- Get One
- List
- Filters
- Pagination and Order
- Root-Level Aggregation
- Relationship Aggregation
- Mutation Operations
- Create
- CreateMany
- Update
- UpdateMany
- Delete
- DeleteMany
- CreateOrUpdateMany
- Customising Graphweaver
- Conclusion
Overview
Graphweaver facilitates the automatic generation of GraphQL schemas and types at runtime.
With Graphweaver, developers can easily and quickly create GraphQL APIs for their data models without the need to manually define schemas and types for each model.
The generated schema includes queries for fetching single entities or lists of entities, along with support for filtering, ordering, and pagination.
Additionally, Graphweaver provides mutations for create, update, and delete operations, as well as bulk operations such as CreateMany and UpdateMany.
Graphweaver is designed to be compatible with various data providers. Such as, PostgreSQL, MySQL, REST, Microsoft Dynamics 365 and Xero APIs.
Let’s start by looking at the architecture of the system.
Architecture and Functionality
Before diving into the details, let's provide an overview of the architecture and functionality of Graphweaver.
Architecture of Graphweaver
Graphweaver follows a modular architecture, comprising several components:
- a GraphQL server
- a schema generator
- data providers such as PostgreSQL and Microsoft Dynamics 365
The GraphQL server handles requests and responses, while the schema generator generates the GraphQL schema based on the data model.
The data providers interact with the respective data sources and supply data to the schema generator.
Functionality of Graphweaver
The primary functionality of Graphweaver Core is to automatically generate schemas for GraphQL APIs.
The generated schema includes queries for fetching single entities or lists of entities, along with filtering, ordering, and pagination capabilities.
Graphweaver also provides mutations for create, update, and delete operations, as well as bulk operations like CreateMany and UpdateMany.
While Graphweaver is designed to work with the built in Data Providers, it can be extended to interface with other data providers if needed.
When a request is made to the GraphQL server, it passes the request to the appropriate resolver function within Graphweaver.
The resolver function interacts with the data provider to retrieve the required data, which is then formatted according to the schema and returned to the client.
Graphweaver supports custom queries and mutations, allowing developers to add additional functionality to their GraphQL APIs beyond the standard operations like create, update, and delete.
Overall, the architecture and functionality of Graphweaver make it a powerful tool for easily creating GraphQL APIs that connect to various data sources.
Graphweaver API
Graphweaver automatically generates a set of Queries and Mutations for each entity. Let's explore them in more detail.
Query Operations
Query operations are used to retrieve data from the server and include Get One and List queries.
Get One
The Get One queries allow fetching a single entity using its ID. For example:
query {
user(id: "1") {
id
firstName
email
}
}
In this example, the user
query retrieves a single driver entity with the ID "1". The user
query is automatically generated by Graphweaver, eliminating the need for manual definition.
List
The List queries are used to fetch a list of entities based on specific criteria. For instance, to list all users with the state "NSW", the following request can be made:
query {
users(filter: { state: "NSW" }) {
id
firstName
state
}
}
Filters
List queries support automatic generation of filters based on entity properties.
Each entity has a corresponding filter input type with the entity name followed by the suffix "ListFilter". For example, if the entity is named "user", the corresponding filter input type would be "UserListFilter".
The filter input type includes fields for each filterable property of the entity.
Operators such as "gt" (greater than), "gte" (greater than or equal to), "lt" (less than), "lte" (less than or equal to), "ne" (not equal to), "in" (in a specified list), "nin" (not in a specified list), "notnull" (not null), "null" (null), "like" (pattern matching), and "ilike" (case-insensitive pattern matching) are automatically added as fields to the ListFilter.
The name of each field is formed by combining the operator name with the property name, separated by an underscore. For example, the field for the "in" operator applied to the "id" property would be named "id_in".
Here's an example of a GraphQL query using the "UserListFilter" input type to list all users with IDs in the array ["1", "99", "1023"]:
query {
users(filter: { id_in: ["1", "99", "1023"] }) {
id
firstName
}
}
In this query, "id_in" is the field name on the "UserListFilter" input type corresponding to the "in" operator applied to the "id" property of the "User" entity type.
Next, let's explore pagination and ordering.
Pagination and Order
Graphweaver provides pagination capabilities by automatically generating a PaginationInput
type that can be used as an input in GraphQL queries.
The PaginationInput
includes fields for specifying the limit, offset, and orderBy.
- The limit field defines the maximum number of items to return.
- The offset field determines the number of items to skip before returning results.
- The orderBy field specifies the sorting order for the results. Graphweaver also generates an
OrderByInput
type that allows specifying the field to order by and the sort order.
Pagination is applied to the list query method. The client can provide the filter and pagination arguments to limit and sort the returned results.
For example, let's retrieve the first 3 users, sorted by their ID in descending order, using pagination:
query {
users(pagination: { limit: 3, offset: 0 }, orderBy: { id: DESC }) {
id
firstName
age
}
}
In this query, we set the limit to 3, the offset to 0 (no skipping), and specify the orderBy field as "id" in descending order.
The response will contain the first 3 users, sorted by ID, along with their respective ID, firstName, and age fields.
The response might look like this:
{
"data": {
"users": [
{
"id": "10",
"firstName": "John",
"age": 25
},
{
"id": "9",
"firstName": "Jane",
"age": 30
},
{
"id": "8",
"firstName": "Bob",
"age": 28
}
]
}
}
Root-Level Aggregation
If your backend provider supports it, Graphweaver will generate aggregation query endpoints as well. For example if you implemented the User entity as mentioned above, in addition to user
and users
, you’ll also get users_aggregate
which you can use to count
the number of users matching a filter:
# This will count all users that you have permission to access
query {
users_aggregate {
count
}
}
# This will count all users that you have permission to access matching
# the supplied filter
query {
users_aggregate(filter: { age_gte: 25 }) {
count
}
}
It’s common to want to fetch a page of results and count all results that match a filter. You can use the same filter variable in two queries to make this happen like so:
query($filter: UsersListFilter) {
users(filter: $filter, pagination: { limit: 3, offset: 0 }, orderBy: { id: DESC }) {
id
name
}
users_aggregate(filter: $filter) {
count
}
}
You’ll then get a result that looks something like this:
{
"data": {
"users": [
{
"id": "10",
"firstName": "John",
"age": 25
},
{
"id": "9",
"firstName": "Jane",
"age": 30
},
{
"id": "8",
"firstName": "Bob",
"age": 28
}
],
"users_aggregate": {
"count": 10
}
}
}
Relationship Aggregation
You can also aggregate at the relationship level with additional filtering or without.
Without additional filtering:
query {
artist(id: "1"){
name
albums {
title
}
albums_aggregate {
count
}
}
}
Result:
{
"data": {
"artist": {
"name": "AC/DC",
"albums": [
{
"title": "For Those About To Rock We Salute You"
},
{
"title": "Let There Be Rock"
}
],
"albums_aggregate": {
"count": 2
}
}
}
}
With Additional Filtering:
query {
artist(id: "1"){
name
albums(filter: { id: "4" }) {
id
title
}
albums_aggregate(filter: { id: "4" }) {
count
}
}
}
Result:
{
"data": {
"artist": {
"name": "AC/DC",
"albums": [
{
"id": "4",
"title": "Let There Be Rock"
}
],
"albums_aggregate": {
"count": 1
}
}
}
}
Mutation Operations
Mutation operations are used to modify data in the data provider.
Graphweaver generates several mutations, including Create, Update, and Delete operations, along with bulk operations like CreateMany, UpdateMany, DeleteMany, and CreateOrUpdateMany.
Let's explore some examples and learn how to use them.
Create
The create mutation is used to create a single entity.
Here's an example of using the Graphweaver create mutation to create a user:
mutation {
createUser(data: { firstName: "John", lastName: "Doe" }) {
id
}
}
In this mutation, we use the createUser
operation to create a new user.
We pass the user’s firstName and lastName as an object in the data argument. The response will contain the ID of the created user.
CreateMany
The CreateMany mutation allows you to create multiple entities at once by passing an array of objects. Here's an example:
mutation {
createUsers(input: {
data: [
{ firstName: "Alice", lastName: "Smith" },
{ firstName: "Bob", lastName: "Johnson" },
{ firstName: "Charlie", lastName: "Garcia" }
]
}) {
id
}
}
In this example, we're using the CreateMany mutation to create multiple users. We provide an array of objects, where each object represents the data for a single user.
Update
The update mutation is used to modify an existing entity.
To update a user's last name from "Smith" to "Jones," we can use the updateUser mutation:
mutation {
updateUser(data: { id: 1, lastName: "Jones" }) {
id
firstName
lastName
}
}
In this mutation, we specify the user’s ID and the updated lastName value. The query returns the updated user's ID, firstName, and lastName.
UpdateMany
Similar to CreateMany, the UpdateMany mutation allows you to update multiple entities at once.
Here's an example:
mutation {
updateUsers(input: {
data: [
{ id: "1", firstName: "Alice", lastName: "Smith" },
{ id: "2", firstName: "Bob", lastName: "Johnson" },
{ id: "3", firstName: "Charlie", lastName: "Garcia" }
]
}) {
id
}
}
In this example, we use the UpdateMany mutation to update multiple users. We provide an array of objects, where each object represents the updated data for a user.
Delete
The delete mutation is used to remove an entity from the data provider.
For example, to delete the user with ID 1, we can use the following mutation:
mutation {
deleteUser(id: "1")
}
The response for this request will be a boolean value indicating the success or failure of the deletion.
DeleteMany
The DeleteMany mutation allows you to delete multiple entities at once.
Here's an example:
mutation {
deleteManyUsers(ids: ["1", "2"])
}
In this example, we use the DeleteMany mutation to delete multiple users. We pass an array of user IDs to be deleted.
CreateOrUpdateMany
The CreateOrUpdateMany mutation enables creating or updating multiple entities in a single GraphQL mutation.
It accepts an array of objects, where each object represents the data for a single entity.
Here's an example of using the CreateOrUpdateMany mutation for the User entity:
mutation {
createOrUpdateManyUsers(input: {
data: [
{ id: "1", firstName: "Alice", lastName: "Smith" },
{ firstName: "Charlie", lastName: "Garcia" }
]
}) {
id
}
}
In this example, the mutation will update the user with ID 1 and set their firstName and lastName, and it will also create a new user record for Charlie Garcia with the provided data.
The response will include the ID of each created or updated users.
Customising Graphweaver
You can also add your own custom Queries and Mutations to Graphweaver.
Conclusion
Graphweaver is a powerful tool for generating GraphQL schemas and types at runtime.
It simplifies the process of creating GraphQL APIs by automatically generating queries, mutations, and other essential components based on your data models.
With support for many data providers, Graphweaver provides flexibility and ease of integration with various data sources.
By extending the functionality with custom queries and mutations, you can tailor your GraphQL API to suit your specific application needs.
Whether you need to fetch data, create entities, update records, or perform bulk operations, Graphweaver offers a comprehensive set of features to streamline your GraphQL development process.