Dynamic Schema Builder
Relevant source files
The following files were used as context for generating this wiki page:
The Dynamic Schema Builder is the core engine of Seaography, responsible for translating SeaORM entities and database schemas into a fully functional async-graphql dynamic schema. Unlike static code generation approaches, this builder constructs the GraphQL schema at runtime, which significantly reduces compilation times and allows for more flexible customizations.
The builder provides a fluent API to register entities, enumerations, custom queries, and mutations. It automatically handles the complexities of relational queries (1-to-1, 1-to-N, M-to-N), filtering with various operators, and multiple pagination strategies (offset-based and cursor-based).
Sources: src/lib.rs:18-25, README.md:16-22
Architecture and Core Components
The primary structure for schema construction is the Builder struct, which maintains the internal state of GraphQL objects, inputs, and scalars before finalizing them into a SchemaBuilder.
The Builder Struct
The Builder manages several collections of GraphQL components:
| Component | Type | Description |
|---|---|---|
query | Object | The root GraphQL Query object. |
mutation | Object | The root GraphQL Mutation object. |
subscription | Subscription | The root GraphQL Subscription object. |
outputs | Vec<Object> | Collection of all generated output object types. |
inputs | Vec<InputObject> | Collection of all input objects (filters, sorting, data). |
context | &'static BuilderContext | Configuration settings for naming, types, and hooks. |
connection | DatabaseConnection | The SeaORM database connection used by resolvers. |
Sources: src/builder.rs:31-77
Component Relationship
The following diagram illustrates how the Builder aggregates various SeaORM elements to produce the final GraphQL Schema.
The Builder acts as an orchestrator that takes SeaORM metadata and transforms it into async-graphql dynamic types based on the provided BuilderContext.
Sources: src/builder.rs:80-120, generator/src/writer.rs:80-104
Entity Registration Logic
Registering a SeaORM entity via register_entity triggers a multi-step process that creates not just the object itself, but all supporting structures required for advanced GraphQL features.
Automated Object Generation
When an entity is registered, the builder creates:
- Entity Object: The main output type representing the database record.
- Edge & Connection Objects: Types required for Relay-compliant cursor pagination.
- Input Objects: Specifically
Filter,Having(for related entity filtering), andOrderinputs.
Sources: src/builder.rs:114-149
Data Loaders
To solve the N+1 query problem, the builder provides methods to register DataLoaders for relations.
register_entity_dataloader_one_to_one: Loads single related records.register_entity_dataloader_one_to_many: Loads collections of related records.
Sources: src/builder.rs:207-238
Customization and Extensibility
The builder is designed to be extended beyond automated SeaORM mapping through several registration methods and macros.
Custom Operations
Developers can manually add fields to the root Query or Mutation objects using:
register_custom_query<T>: Adds fields defined in a struct implementingCustomFields.register_custom_mutation<T>: Adds mutation fields.register_subscription_field: Manually appends subscription fields.
Sources: src/builder.rs:327-343, examples/sqlite/src/query_root.rs:58-62
Lifecycle Hooks and Guards
The builder integrates with LifecycleHooks to implement authorization and business logic. This allows for:
- Entity Guards: Restricting access to an entire entity based on the operation type (Create, Read, Update, Delete).
- Field Guards: Restricting access to specific columns.
- Entity Filters: Automatically injecting SQL conditions (e.g.,
WHERE tenant_id = X) into queries.
Sources: examples/sea-draw/src/schema.rs:110-150, CHANGELOG.md:58-80
Schema Construction Flow
The typical workflow for creating a schema involves initializing a context, setting up a builder, and finishing the process.
The sequence shows how the builder transitions from a collection of SeaORM definitions to a finalized GraphQL Schema.
Sources: generator/src/writer.rs:88-103, src/builder.rs:360-460
Configuration Options
The BuilderContext (and specific limit methods on the Builder) control the behavior of the generated schema.
| Feature | Method / Configuration | Description |
|---|---|---|
| Depth Limit | set_depth_limit(Option<usize>) | Prevents deeply nested malicious queries. |
| Complexity Limit | set_complexity_limit(Option<usize>) | Limits the total computational cost of a query. |
| Naming | EntityObjectConfig | Custom functions to define how table/column names map to GraphQL. |
| Pagination | PaginationInputConfig | Sets default and maximum limits for page sizes. |
Sources: src/builder.rs:350-358, examples/sea-draw/src/schema.rs:77-96
Summary
The Dynamic Schema Builder serves as the translation layer between SeaORM's relational mapping and GraphQL's graph-based interface. By utilizing the dynamic capabilities of async-graphql, it provides a highly efficient way to expose database schemas while maintaining strict type safety and offering deep hooks for customization, security, and performance optimization through DataLoaders.
Sources: src/lib.rs:20-35, src/builder.rs:31-40