autumn_plugin_graphql/lib.rs
1//! Production-grade GraphQL for [Autumn](https://github.com/autumn-foundation/autumn).
2//!
3//! Mount any [async-graphql](https://docs.rs/async-graphql) schema on an
4//! Autumn app with one line, and get the operational surface a public or
5//! internal API needs:
6//!
7//! ```rust,ignore
8//! use autumn_plugin_graphql::GraphqlPlugin;
9//!
10//! #[autumn_web::main]
11//! async fn main() {
12//! autumn_web::app()
13//! .plugin(GraphqlPlugin::new(Schema::build(Query, Mutation, Subscription).finish()))
14//! .run()
15//! .await;
16//! }
17//! ```
18//!
19//! | Concern | What you get |
20//! |---|---|
21//! | Transports | `POST`/`GET` per GraphQL-over-HTTP (incl. `application/graphql-response+json` status semantics), opt-in batching, opt-in multipart uploads, WebSocket (`graphql-transport-ws` + legacy `graphql-ws`), SSE |
22//! | Hardening | size, lexical-nesting, depth, alias, root-field, field-count and directive limits before execution; mutations refused over `GET`; introspection and SDL off outside dev; CSRF preflight for multipart; execution timeouts; connection caps |
23//! | Persisted operations | Apollo APQ with a pluggable store, and trusted documents (safelisting) from an Apollo manifest |
24//! | Errors | stable `extensions.code` on every error; `AutumnError` mapping with 5xx redaction; masking of uncoded resolver errors |
25//! | Context | `AppState` + [`GraphqlRequestInfo`] in every resolver; hooks that run any axum extractor (current user, tenant, `DataLoaders`); WebSocket `connection_init` auth |
26//! | Operations | `[graphql]` config with profile layering and `AUTUMN_GRAPHQL__*` overrides; kill switch; Prometheus metrics; tracing spans; slow-operation log; graceful WebSocket/SSE shutdown |
27//! | Framework fit | declared routes for `autumn routes` / audit, a `PluginContract`, a guard seam for nested routers, conformance-tested |
28//!
29//! Every transport — HTTP, WebSocket and SSE — goes through the same
30//! [`pipeline`], so no path reaches the schema without the same checks.
31//!
32//! See the crate README for a guided tour, and `docs/` for architecture
33//! decision records.
34
35pub mod config;
36pub mod context;
37pub mod error;
38pub mod limits;
39mod metrics;
40pub mod persisted;
41pub mod pipeline;
42mod plugin;
43pub mod sdl;
44#[cfg(feature = "test-support")]
45pub mod testing;
46mod transport;
47
48pub use config::{GraphqlConfig, PersistedQueryMode, Toggle};
49pub use context::{ContextHook, GraphqlRequestInfo, Transport, WsInitHook};
50pub use error::{GraphqlResultExt, IntoGraphqlError, codes};
51pub use persisted::{InMemoryPersistedQueryStore, PersistedQueryStore, TrustedDocuments};
52pub use plugin::{DrainHandle, GraphqlPlugin, PLUGIN_NAME, SUPPORTED_AUTUMN_WEB};
53pub use transport::ws::{CLOSE_FORBIDDEN, CLOSE_GOING_AWAY, CLOSE_INIT_TIMEOUT};
54
55/// Re-exported so apps and this crate always agree on one async-graphql.
56pub use async_graphql;