| Crates.io | reinhardt-graphql |
| lib.rs | reinhardt-graphql |
| version | 0.1.0-alpha.1 |
| created_at | 2026-01-23 09:18:52.74651+00 |
| updated_at | 2026-01-23 09:18:52.74651+00 |
| description | GraphQL API support for Reinhardt (facade crate) |
| homepage | |
| repository | https://github.com/kent8192/reinhardt-rs |
| max_upload_size | |
| id | 2063899 |
| size | 202,344 |
GraphQL integration (facade crate)
GraphQL API support with schema generation from models, query and mutation resolvers, and integration with the authentication and permission system. Provides a flexible alternative to REST APIs.
This is a facade crate that re-exports functionality from the following modules:
reinhardt-graphql/ (facade crate - public API)
├── crates/
│ ├── core/ (core GraphQL implementation)
│ └── macros/ (procedural macros)
Users should depend on `reinhardt-graphql` (this facade crate) for all GraphQL functionality.
GraphQLType and GraphQLField traits for type-safe GraphQL type definitionsGraphQLError enum with Schema, Resolver, and NotFound variantsResolver trait with generic output types for flexible resolver implementationArc<RwLock<HashMap>> for user data
new(): Create new storage instanceadd_user(): Add or update user in storageget_user(): Retrieve user by IDlist_users(): List all stored usersCreateUserInput for user creation mutationscreate_schema() function to build GraphQL schema with data contextuser(id: ID): Retrieve single user by IDusers(): List all usershello(name: Option<String>): Simple greeting query for testingcreateUser(input: CreateUserInput): Create new user with auto-generated UUIDupdateUserStatus(id: ID, active: bool): Update user active statusUserEvent enum supporting Created, Updated, and Deleted eventsEventBroadcaster with tokio broadcast channel (capacity: 100)
new(): Create new broadcaster instancebroadcast(): Send events to all subscriberssubscribe(): Subscribe to event streamSubscriptionRoot with filtered subscription streams
userCreated(): Stream of user creation eventsuserUpdated(): Stream of user update eventsuserDeleted(): Stream of user deletion events (returns ID only)graphql-grpc feature)GraphQLGrpcService implementing gRPC protocol for GraphQL
execute_query(): Execute GraphQL queries via unary RPCexecute_mutation(): Execute GraphQL mutations via unary RPCexecute_subscription(): Execute GraphQL subscriptions via server streaming RPCreinhardt-grpc crate
GraphQLRequest: query, variables, operation_nameGraphQLResponse: data, errors, extensionsSubscriptionEvent: id, event_type, payload, timestampdi feature)#[graphql_handler] macro: Attribute macro for resolvers with automatic dependency injectionGraphQLContextExt trait: Extension trait for extracting DI context from GraphQL contextSchemaBuilderExt trait: Convenience methods for adding DI context to schema#[inject(cache = false)]Add reinhardt to your Cargo.toml:
[dependencies]
reinhardt = { version = "0.1.0-alpha.1", features = ["graphql"] }
# Or use a preset:
# reinhardt = { version = "0.1.0-alpha.1", features = ["standard"] } # Recommended
# reinhardt = { version = "0.1.0-alpha.1", features = ["full"] } # All features
Then import GraphQL features:
use reinhardt::graphql::{Schema, Query, Mutation};
use reinhardt::graphql::types::{UserStorage, UserEvent};
Note: GraphQL features are included in the standard and full feature presets.
# With dependency injection
reinhardt = { version = "0.1.0-alpha.1", features = ["graphql", "di"] }
# With gRPC transport
reinhardt = { version = "0.1.0-alpha.1", features = ["graphql", "grpc"] }
use async_graphql::{EmptySubscription, Schema};
use reinhardt::graphql::schema::{Mutation, Query, UserStorage};
#[tokio::main]
async fn main() {
let storage = UserStorage::new();
let schema = Schema::build(Query, Mutation, EmptySubscription)
.data(storage)
.finish();
let query = r#"{ hello(name: "World") }"#;
let result = schema.execute(query).await;
println!("{}", result.data);
}
Enable the di feature to use dependency injection in GraphQL resolvers:
use async_graphql::{Context, Object, Result, ID, Schema, EmptyMutation, EmptySubscription};
use reinhardt::graphql::{graphql_handler, SchemaBuilderExt};
use reinhardt_di::InjectionContext;
use std::sync::Arc;
// Define your resolvers
pub struct Query;
#[Object]
impl Query {
async fn user(&self, ctx: &Context<'_>, id: ID) -> Result<User> {
user_impl(ctx, id).await
}
async fn users(&self, ctx: &Context<'_>, limit: Option<i32>) -> Result<Vec<User>> {
users_impl(ctx, limit).await
}
}
// Use #[graphql_handler] for DI
#[graphql_handler]
async fn user_impl(
ctx: &Context<'_>,
id: ID,
#[inject] db: DatabaseConnection, // Auto-injected
#[inject] cache: RedisCache, // Auto-injected
) -> Result<User> {
// Check cache first
if let Some(user) = cache.get(&id).await {
return Ok(user);
}
// Fetch from database
let user = db.fetch_user(&id).await?;
// Update cache
cache.set(&id, &user).await;
Ok(user)
}
#[graphql_handler]
async fn users_impl(
ctx: &Context<'_>,
limit: Option<i32>,
#[inject] db: DatabaseConnection,
) -> Result<Vec<User>> {
let limit = limit.unwrap_or(100);
let users = db.fetch_users(limit).await?;
Ok(users)
}
// Build schema with DI context
#[tokio::main]
async fn main() {
let injection_ctx = Arc::new(InjectionContext::new());
// Register dependencies
// injection_ctx.register(DatabaseConnection::new(...));
// injection_ctx.register(RedisCache::new(...));
let schema = Schema::build(Query, EmptyMutation, EmptySubscription)
.with_di_context(injection_ctx) // Helper method from SchemaBuilderExt
.finish();
// Execute query
let query = r#"{ user(id: "123") { id name email } }"#;
let result = schema.execute(query).await;
println!("{}", result.data);
}
Control dependency caching per parameter:
#[graphql_handler]
async fn handler(
ctx: &Context<'_>,
id: ID,
#[inject] cached_db: DatabaseConnection, // Cached (default)
#[inject(cache = false)] fresh_db: DatabaseConnection, // Not cached
) -> Result<User> {
// ...
}
use async_graphql::{EmptySubscription, Schema};
use reinhardt::graphql::grpc_service::GraphQLGrpcService;
use reinhardt::graphql::schema::{Mutation, Query, UserStorage};
use reinhardt::grpc::proto::graphql::graph_ql_service_server::GraphQlServiceServer;
use tonic::transport::Server;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let storage = UserStorage::new();
let schema = Schema::build(Query, Mutation, EmptySubscription)
.data(storage)
.finish();
let service = GraphQLGrpcService::new(schema);
let grpc_service = GraphQlServiceServer::new(service);
Server::builder()
.add_service(grpc_service)
.serve("127.0.0.1:50051".parse()?)
.await?;
Ok(())
}
use reinhardt::grpc::proto::graphql::{
graph_ql_service_client::GraphQlServiceClient,
GraphQlRequest,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = GraphQlServiceClient::connect("http://127.0.0.1:50051").await?;
let request = tonic::Request::new(GraphQlRequest {
query: r#"{ hello(name: "gRPC") }"#.to_string(),
variables: None,
operation_name: None,
});
let response = client.execute_query(request).await?;
println!("{:?}", response.into_inner());
Ok(())
}
# Start gRPC server
cargo run --package reinhardt-graphql --features graphql-grpc --example grpc_server
# In another terminal, run client
cargo run --package reinhardt-graphql --features graphql-grpc --example grpc_client
# All tests
cargo test --package reinhardt-graphql --features graphql-grpc
# Integration tests
cargo test --package reinhardt-graphql --features graphql-grpc --test grpc_integration_tests
# Subscription streaming tests
cargo test --package reinhardt-graphql --features graphql-grpc --test grpc_subscription_tests
# E2E tests with real network
cargo test --package reinhardt-graphql --features graphql-grpc --test grpc_e2e_tests
# Performance benchmarks
cargo bench --package reinhardt-graphql --features graphql-grpc
See PERFORMANCE.md for detailed benchmarks.
Summary: