1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! GraphQL transport for acton-service (requires the `graphql` feature).
//!
//! This module integrates [`async-graphql`](https://docs.rs/async-graphql) as a
//! third sibling transport next to HTTP (Axum) and gRPC (Tonic). Schemas are
//! mounted by [`ServiceBuilder::with_versioned_graphql`] underneath the same
//! versioned Axum router used for REST endpoints, so they inherit the full
//! middleware stack — authentication, tracing, rate limiting, CORS, and
//! everything else.
//!
//! # Versioning
//!
//! GraphQL endpoints are versioned per-path. A schema registered for
//! [`ApiVersion::V1`] is mounted at `/{base}/v1/graphql`, V2 at
//! `/{base}/v2/graphql`, and so on. This matches the framework's existing
//! path-based versioning ([`VersionedApiBuilder`](crate::versioning::VersionedApiBuilder)).
//!
//! # Authentication
//!
//! When PASETO or JWT middleware is enabled, [`Claims`](crate::middleware::Claims)
//! placed into request extensions are automatically injected into the GraphQL
//! request's data. Resolvers retrieve them through the
//! [`GraphQLContextExt::claims`] extension trait.
//!
//! # Cedar authorization
//!
//! Under the `graphql-cedar` feature, resolvers can call
//! [`CedarResolverCheck::authorize`] to evaluate Cedar policies using the same
//! [`CedarAuthz`](crate::middleware::cedar::CedarAuthz) instance that protects
//! HTTP and gRPC.
//!
//! # Example
//!
//! ```rust,ignore
//! use acton_service::prelude::*;
//! use acton_service::graphql::{VersionedGraphQLBuilder, GraphQLContextExt};
//! use async_graphql::{Object, Schema, EmptyMutation, EmptySubscription, Context};
//!
//! struct Query;
//!
//! #[Object]
//! impl Query {
//! async fn me(&self, ctx: &Context<'_>) -> String {
//! ctx.claims()
//! .map(|c| c.sub.clone())
//! .unwrap_or_else(|| "anonymous".into())
//! }
//! }
//!
//! let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
//!
//! let graphql = VersionedGraphQLBuilder::new()
//! .with_base_path("/api")
//! .add_version(ApiVersion::V1, schema)
//! .build();
//!
//! ServiceBuilder::new()
//! .with_routes(VersionedApiBuilder::new().build_routes())
//! .with_versioned_graphql(graphql)
//! .build()
//! .serve()
//! .await?;
//! ```
pub use ;
pub use GraphQLContextExt;
pub use ;
/// Re-export the underlying `async_graphql` crate so consumers don't need to
/// add a direct dependency. Build schemas as
/// `acton_service::graphql::async_graphql::Schema::build(...)`.
pub use async_graphql;