Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion book/src/serve/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ In the [Juniper] ecosystem, both implementations are provided by the [`juniper_g
[`subscriptions-transport-ws` npm package]: https://npmjs.com/package/subscriptions-transport-ws
[`warp`]: https://docs.rs/warp
[Apollo]: https://www.apollographql.com
[GraphiQL]: https://github.com/graphql/graphiql
§
[GraphQL]: https://graphql.org
[GraphQL Playground]: https://github.com/prisma/graphql-playground
[HTTP]: https://en.wikipedia.org/wiki/HTTP
Expand Down
7 changes: 7 additions & 0 deletions juniper/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ All user visible changes to `juniper` crate will be documented in this file. Thi
- Added `description` field to `ast::Operation`, `ast::Fragment` and `ast::VariableDefinition`. ([#1349], [graphql/graphql-spec#1170])
- Renamed `ast::VariableDefinitions` to `ast::VariablesDefinition`: ([#1353], [graphql/graphql-spec#916])
- Renamed `ast::Operation::variable_definitions` field to `variables_definition`.
- Added `extenstions` field to `http::GraphQLRequest`. ([#1356], [graphql/graphql-spec#976])
- Added `Ext` type parameter to `http::GraphQLRequest` and `http::GraphQLBatchRequest` defaulting to `Variables`. ([#1356], [graphql/graphql-spec#976])
- Changed `ScalarToken::String` to contain raw quoted and escaped `StringLiteral` (was unquoted but escaped string before). ([#1349])
- Added `LexerError::UnterminatedBlockString` variant. ([#1349])
- `http::GraphQLRequest`:
- Removed `new()` constructor in favor of constructing it directly. ([#1356])
- Removed deprecated `operation_name()` method in favor of direct `operation_name` field. ([#1356])

### Added

Expand Down Expand Up @@ -72,12 +77,14 @@ All user visible changes to `juniper` crate will be documented in this file. Thi
[#1353]: /../../pull/1353
[#1354]: /../../pull/1354
[#1355]: /../../pull/1355
[#1356]: /../../pull/1356
[graphql/graphql-spec#525]: https://github.com/graphql/graphql-spec/pull/525
[graphql/graphql-spec#687]: https://github.com/graphql/graphql-spec/issues/687
[graphql/graphql-spec#805]: https://github.com/graphql/graphql-spec/pull/805
[graphql/graphql-spec#825]: https://github.com/graphql/graphql-spec/pull/825
[graphql/graphql-spec#849]: https://github.com/graphql/graphql-spec/pull/849
[graphql/graphql-spec#916]: https://github.com/graphql/graphql-spec/pull/916
[graphql/graphql-spec#976]: https://github.com/graphql/graphql-spec/pull/976
[graphql/graphql-spec#1040]: https://github.com/graphql/graphql-spec/pull/1040
[graphql/graphql-spec#1142]: https://github.com/graphql/graphql-spec/pull/1142
[graphql/graphql-spec#1170]: https://github.com/graphql/graphql-spec/pull/1170
Expand Down
98 changes: 92 additions & 6 deletions juniper/src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,98 @@ where
}
}

/// Execution context for resolving GraphQL types.
pub trait Context {}

impl<C: Context> Context for &C {}

/// Injects the provided value into this [`Context`].
///
/// # Implementation
///
/// Default implementation does nothing.
///
/// This trait should be implemented for a [`Context`] implementation to be populated with
/// [request `extensions`][0].
///
/// ```rust
/// # use juniper::{
/// # Context, DefaultScalarValue, EmptyMutation, EmptySubscription, Inject, RootNode,
/// # graphql_object, graphql_value, http::GraphQLRequest,
/// # };
/// # use serde::{Deserialize, Serialize};
/// # use serde_json::json;
/// #
/// #[derive(Deserialize, Serialize)]
/// #[serde(rename_all = "camelCase")]
/// struct CustomExtensions {
/// persisted_query: PersistedQueryExtensions,
/// }
/// #[derive(Deserialize, Serialize)]
/// #[serde(rename_all = "camelCase")]
/// struct PersistedQueryExtensions {
/// sha256_hash: Box<str>,
/// }
///
/// type CustomGraphQLRequest<S = DefaultScalarValue> = GraphQLRequest<S, CustomExtensions>;
///
/// #[derive(Default)]
/// struct CustomContext {
/// persisted_query_sha256_hash: Option<Box<str>>,
/// }
/// impl Context for CustomContext {}
/// impl Inject<CustomExtensions> for CustomContext {
/// fn inject(&mut self, extensions: &CustomExtensions) {
/// self.persisted_query_sha256_hash = Some(extensions.persisted_query.sha256_hash.clone());
/// }
/// }
///
/// struct Query;
///
/// #[graphql_object]
/// impl Query {
/// fn is_persisted_query(context: &CustomContext) -> bool {
/// context.persisted_query_sha256_hash.is_some()
/// }
/// }
/// #
/// # type Schema = RootNode<
/// # Query, EmptyMutation<CustomContext>, EmptySubscription<CustomContext>,
/// # >;
/// #
/// # #[tokio::main]
/// # async fn main() {
/// # let request: CustomGraphQLRequest = serde_json::from_value(json!({
/// # "query": "{ isPersistedQuery }",
/// # "extensions": {
/// # "persistedQuery": {
/// # "sha256Hash":
/// # "c205cf782b5c43c3fc67b5233445b78fbea47b99a0302cf31bda2a8e2162e1e6",
/// # },
/// # },
/// # })).unwrap();
/// # let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new());
/// # let context = CustomContext::default();
/// #
/// # assert_eq!(
/// # request.execute(&schema, context).await.into_result(),
/// # Ok((graphql_value!({"isPersistedQuery": true}), vec![])),
/// # );
/// # }
/// ```
///
/// [0]: https://spec.graphql.org/September2025#sel-FANHLBBgBBvC0vW
pub trait Inject<V: ?Sized = Variables> {
/// Injects the provided `value` into this [`Context`].
///
/// Default implementation does nothing.
fn inject(&mut self, value: &V) {
_ = value;
}
}

impl<V: ?Sized> Inject<V> for () {}

/// Conversion trait for context types
///
/// Used to support different context types for different parts of an
Expand All @@ -394,12 +486,6 @@ pub trait FromContext<T> {
/// Perform the conversion
fn from(value: &T) -> &Self;
}

/// Marker trait for types that can act as context objects for `GraphQL` types.
pub trait Context {}

impl<C: Context> Context for &C {}

static NULL_CONTEXT: () = ();

impl<T> FromContext<T> for () {
Expand Down
Loading