8000 Add `DynamicRequestExt::root_value` to specify the root value for the… · async-graphql/async-graphql@1befbb1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1befbb1

Browse files
committed
Add DynamicRequestExt::root_value to specify the root value for the request #1166
1 parent 7162bf8 commit 1befbb1

File tree

4 files changed

+77
-16
lines changed

4 files changed

+77
-16
lines changed

src/dynamic/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ mod input_object;
4141
mod input_value;
4242
mod interface;
4343
mod object;
44+
mod request;
4445
mod resolve;
4546
mod scalar;
4647
mod schema;
@@ -58,6 +59,7 @@ pub use interface::{Interface, InterfaceField};
5859
pub use object::Object;
5960
pub use r#enum::{Enum, EnumItem};
6061
pub use r#type::Type;
62+
pub use request::{DynamicRequest, DynamicRequestExt};
6163
pub use scalar::Scalar;
6264
pub use schema::{Schema, SchemaBuilder};
6365
pub use subscription::{Subscription, SubscriptionField, SubscriptionFieldFuture};

src/dynamic/request.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use crate::{dynamic::FieldValue, Request};
2+
3+
/// GraphQL request for dynamic schema.
4+
pub struct DynamicRequest {
5+
pub(crate) inner: Request,
6+
pub(crate) root_value: FieldValue<'static>,
7+
}
8+
9+
/// A trait for [`DynamicRequest`]
10+
pub trait DynamicRequestExt {
11+
/// Specify the root value for the request
12+
fn root_value(self, value: FieldValue<'static>) -> DynamicRequest;
13+
}
14+
15+
impl<T: Into<Request>> DynamicRequestExt for T {
16+
fn root_value(self, value: FieldValue<'static>) -> DynamicRequest {
17+
DynamicRequest {
18+
inner: self.into(),
19+
root_value: value,
20+
}
21+
}
22+
}
23+
24+
impl<T: Into<Request>> From<T> for DynamicRequest {
25+
fn from(req: T) -> Self {
26+
Self {
27+
inner: req.into(),
28+
root_value: FieldValue::NULL,
29+
}
30+
}
31+
}

src/dynamic/schema.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use indexmap::IndexMap;
66

77
use crate::{
88
dynamic::{
9-
field::BoxResolverFn, r#type::Type, resolve::resolve_container, FieldFuture, FieldValue,
10-
Object, ResolverContext, Scalar, SchemaError, Subscription,
9+
field::BoxResolverFn, r#type::Type, resolve::resolve_container, DynamicRequest,
10+
FieldFuture, FieldValue, Object, ResolverContext, Scalar, SchemaError, Subscription,
1111
},
1212
extensions::{ExtensionFactory, Extensions},
1313
registry::{MetaType, Registry},
@@ -284,21 +284,21 @@ impl Schema {
284284
self.0.env.registry.export_sdl(options)
285285
}
286286

287-
async fn execute_once(&self, env: QueryEnv) -> Response {
287+
async fn execute_once(&self, env: QueryEnv, root_value: &FieldValue<'static>) -> Response {
288288
// execute
289289
let ctx = env.create_context(&self.0.env, None, &env.operation.node.selection_set);
290290
let res = match &env.operation.node.ty {
291291
OperationType::Query => {
292292
async move { self.query_root() }
293293
.and_then(|query_root| {
294-
resolve_container(self, query_root, &ctx, &FieldValue::NULL, false)
294+
resolve_container(self, query_root, &ctx, root_value, false)
295295
})
296296
.await
297297
}
298298
OperationType::Mutation => {
299299
async move { self.mutation_root() }
300300
.and_then(|query_root| {
301-
resolve_container(self, query_root, &ctx, &FieldValue::NULL, true)
301+
resolve_container(self, query_root, &ctx, root_value, true)
302302
})
303303
.await
304304
}
@@ -320,15 +320,15 @@ impl Schema {
320320
}
321321

322322
/// Execute a GraphQL query.
323-
pub async fn execute(&self, request: impl Into<Request>) -> Response {
323+
pub async fn execute(&self, request: impl Into<DynamicRequest>) -> Response {
324324
let request = request.into();
325325
let extensions = self.create_extensions(Default::default());
326326
let request_fut = {
327327
let extensions = extensions.clone();
328328
async move {
329329
match prepare_request(
330330
extensions,
331-
request,
331+
request.inner,
332332
Default::default(),
333333
&self.0.env.registry,
334334
self.0.validation_mode,
@@ -340,7 +340,7 @@ impl Schema {
340340
{
341341
Ok((env, cache_control)) => {
342342
let fut = async {
343-
self.execute_once(env.clone())
343+
self.execute_once(env.clone(), &request.root_value)
344344
.await
345345
.cache_control(cache_control)
346346
};
@@ -360,7 +360,7 @@ impl Schema {
360360
/// Execute a GraphQL subscription with session data.
361361
pub fn execute_stream_with_session_data(
362362
&self,
363-
request: impl Into<Request>,
363+
request: impl Into<DynamicRequest>,
364364
session_data: Arc<Data>,
365365
) -> impl Stream<Item = Response> + Send + Unpin {
366366
let schema = self.clone();
@@ -381,7 +381,7 @@ impl Schema {
381381

382382
let (env, _) = match prepare_request(
383383
extensions,
384-
request,
384+
request.inner,
385385
session_data,
386386
&schema.0.env.registry,
387387
schema.0.validation_mode,
@@ -398,7 +398,7 @@ impl Schema {
398398
};
399399

400400
if env.operation.node.ty != OperationType::Subscription {
401-
yield schema.execute_once(env).await;
401+
yield schema.execute_once(env, &request.root_value).await;
402402
return;
403403
}
404404

@@ -408,7 +408,7 @@ impl Schema {
408408
&env.operation.node.selection_set,
409409
);
410410
let mut streams = Vec::new();
411-
subscription.collect_streams(&schema, &ctx, &mut streams);
411+
subscription.collect_streams(&schema, &ctx, &mut streams, &request.root_value);
412412

413413
let mut stream = futures_util::stream::select_all(streams);
414414
while let Some(resp) = stream.next().await {
@@ -422,7 +422,7 @@ impl Schema {
422422
/// Execute a GraphQL subscription.
423423
pub fn execute_stream(
424424
&self,
425-
request: impl Into<Request>,
425+
request: impl Into<DynamicRequest>,
426426
) -> impl Stream<Item = Response> + Send + Unpin {
427427
self.execute_stream_with_session_data(request, Default::default())
428428
}
@@ -482,8 +482,9 @@ mod tests {
482482
use tokio::sync::Mutex;
483483

484484
use crate::{
485-
dynamic::*, extensions::*, value, PathSegment, Request, Response, ServerError,
486-
ServerResult, ValidationResult, Value,
485+
dynamic::{DynamicRequestExt, *},
486+
extensions::*,
487+
value, PathSegment, Request, Response, ServerError, ServerResult, ValidationResult, Value,
487488
};
488489

489490
#[tokio::test]
@@ -528,6 +529,32 @@ mod tests {
528529
);
529530
}
530531

532+
#[tokio::test]
533+
async fn root_value() {
534+
let query =
535+
Object::new("Query").field(Field::new("value", TypeRef::named(TypeRef::INT), |ctx| {
536+
FieldFuture::new(async {
537+
Ok(Some(Value::Number(
538+
(*ctx.parent_value.try_downcast_ref::<i32>()?).into(),
539+
)))
540+
})
541+
}));
542+
543+
let schema = Schema::build("Query", None, None)
544+
.register(query)
545+
.finish()
546+
.unwrap();
547+
assert_eq!(
548+
schema
549+
.execute("{ value }".root_value(FieldValue::owned_any(100)))
550+
.await
551+
.into_result()
552+
.unwrap()
553+
.data,
554+
value!({ "value": 100, })
555+
);
556+
}
557+
531558
#[tokio::test]
532559
async fn field_alias() {
533560
let query =

src/dynamic/subscription.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ impl Subscription {
192192
schema: &Schema,
193193
ctx: &ContextSelectionSet<'a>,
194194
streams: &mut Vec<BoxFieldStream<'a>>,
195+
root_value: &'a FieldValue<'static>,
195196
) {
196197
for selection in &ctx.item.node.items {
197198
if let Selection::Field(field) = &selection.node {
@@ -221,7 +222,7 @@ impl Subscription {
221222
let mut stream = resolver_fn(ResolverContext {
222223
ctx: &ctx_field,
223224
args: arguments,
224-
parent_value: &FieldValue::NULL,
225+
parent_value: root_value,
225226
})
226227
.0
227228
.await

0 commit comments

Comments
 (0)
0