GraphQL Mutations Overview
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
Seaography provides a robust system for generating GraphQL mutations directly from SeaORM entities. This framework automates the creation of standard Create, Update, and Delete (CUD) operations, allowing developers to perform database modifications through a fully-typed GraphQL API with minimal manual configuration. Mutations are integrated into the Builder system, which maps database schemas to dynamic GraphQL nodes while respecting relationship constraints and data validation.
Sources: README.md, src/lib.rs:207-224, src/mutation/entity_create_one_mutation.rs:36-40
Mutation Architecture and Lifecycle
The mutation system is built around specialized builders that generate GraphQL fields for specific database operations. These builders interact with the BuilderContext to determine naming conventions, input types, and execution logic. A critical component of the mutation lifecycle is the implementation of lifecycle hooks, which allow for authorization (guards), data filtering, and post-execution triggers.
Mutation Lifecycle Flow
The following diagram illustrates the execution flow of a standard mutation, including guard checks and transaction management.
The lifecycle ensures that every operation is wrapped in a transaction and passes through security layers before interacting with the database.
Sources: src/mutation/entity_update_mutation.rs:90-155, src/mutation/entity_create_one_mutation.rs:72-110
Core Mutation Types
Create One Mutation
The EntityCreateOneMutationBuilder creates a field that accepts a data object corresponding to a single entity. It automatically handles the conversion of GraphQL input objects into SeaORM ActiveModel structures, notably skipping auto-incrementing primary keys during the process.
| Component | Description |
|---|---|
| Builder Class | EntityCreateOneMutationBuilder |
| Mutation Name Suffix | CreateOne (default) or _create_one (snake case) |
| Input Argument | data (Non-nullable input object) |
| Return Type | The created entity object |
Sources: src/mutation/entity_create_one_mutation.rs:13-34, src/mutation/entity_create_one_mutation.rs:117-152
Update Mutation
The EntityUpdateMutationBuilder enables batch or individual updates based on a filter condition. Unlike create operations, the update mutation requires both a data field (containing the fields to change) and a filter field (defining which records to apply the update to).
| Component | Description |
|---|---|
| Builder Class | EntityUpdateMutationBuilder |
| Mutation Name Suffix | Update (default) or _update (snake case) |
| Input Arguments | data (changes), filter (selection criteria) |
| Return Type | A list of modified entities |
Sources: src/mutation/entity_update_mutation.rs:14-34, src/mutation/entity_update_mutation.rs:80-176
Batch and Delete Mutations
- Create Batch: Allows inserting an array of data for multiple entities simultaneously.
- Delete: Takes a condition filter object, removes the selected entities, and returns the count of deleted items.
Sources: CHANGELOG.md:188-195
Custom Mutations
Seaography supports the extension of the GraphQL schema with custom mutations using the #[CustomFields] macro. This allows developers to implement business logic that falls outside standard CUD operations, such as login procedures or complex multi-entity requests.
#[CustomFields]
impl Operations {
async fn login(ctx: &Context<'_>) -> async_graphql::Result<customer::Model> {
let db = ctx.data::<DatabaseConnection>().unwrap();
Ok(customer::Entity::find().one(db).await?.ok_or(...))
}
async fn rental_request(
_ctx: &Context<'_>,
rental_request: RentalRequest
) -> async_graphql::Result<String> {
// Custom logic here
Ok("Request Processed".into())
}
}
Sources: CHANGELOG.md:23-42, examples/sqlite/src/query_root.rs:60-65
Security and Hooks
Mutations are protected by a multi-layered guard system defined in LifecycleHooks.
- Entity Guards: Determine if an actor has permission to perform an
OperationType(Create, Update, Delete) on a specific entity. - Field Guards: Provide granular control, blocking updates to specific columns even if the user has entity-level access.
- Entity Filters: Automatically append database-level conditions (e.g.,
WHERE tenant_id = 1) to ensure users only mutate data they own.
impl LifecycleHooksInterface for MyHooks {
fn entity_filter(
&self, _ctx: &ResolverContext, entity: &str, _action: OperationType,
) -> Option<Condition> {
match entity {
"Store" => Some(Condition::all().add(store::Column::StoreId.eq(2))),
_ => None,
}
}
}
Sources: CHANGELOG.md:73-100, examples/sea-draw/src/schema.rs:114-142
Summary
GraphQL mutations in Seaography bridge the gap between SeaORM's active models and async-graphql's dynamic types. By providing automated builders for standard operations and macros for custom logic, the system ensures that database state changes are performed safely within transactions, validated by guards, and customized through lifecycle hooks. This architecture allows for rapid development of data-driven backends without sacrificing architectural control or security.