From 9a50f131b72d677ecfa557c900d04578ef48dc91 Mon Sep 17 00:00:00 2001 From: laststylebender <43403528+laststylebender14@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:11:02 +0530 Subject: [PATCH] fix(jit): add field aliases and args support (#2709) Co-authored-by: Panagiotis Karatakis Co-authored-by: Panagiotis Co-authored-by: Kiryl Mialeshka <8974488+meskill@users.noreply.github.com> --- src/core/blueprint/from_config.rs | 3 +- src/core/config/config.rs | 6 ++- src/core/config/from_document.rs | 9 ++-- ...nion_input_type__tests__union_in_type.snap | 18 ++++---- .../json_to_config_spec__add_cart.json.snap | 2 +- src/core/ir/resolver_context_like.rs | 2 +- src/core/jit/builder.rs | 27 +++++++++--- src/core/jit/context.rs | 39 ++++++++++------ src/core/jit/error.rs | 2 +- src/core/jit/exec.rs | 22 ++-------- src/core/jit/model.rs | 9 ++++ ...ore__jit__builder__tests__alias_query.snap | 44 +++++++++++++++++++ ...e__jit__builder__tests__default_value.snap | 2 + ...core__jit__builder__tests__directives.snap | 3 ++ ..._core__jit__builder__tests__fragments.snap | 6 +++ ...e__jit__builder__tests__from_document.snap | 4 ++ ...__builder__tests__multiple_operations.snap | 6 +++ ...builder__tests__resolving_operation-2.snap | 5 +++ ...__builder__tests__resolving_operation.snap | 4 ++ ..._jit__builder__tests__simple_mutation.snap | 7 +++ ...re__jit__builder__tests__simple_query.snap | 3 ++ ...ll__core__jit__builder__tests__unions.snap | 3 ++ ..._core__jit__builder__tests__variables.snap | 3 ++ src/core/jit/synth/synth.rs | 17 ++++--- .../snapshots/call-mutation.md_client.snap | 2 +- .../snapshots/call-mutation.md_merged.snap | 2 +- .../graphql-conformance-003.md_client.snap | 2 +- .../graphql-conformance-003.md_merged.snap | 2 +- .../graphql-conformance-015.md_client.snap | 2 +- .../graphql-conformance-015.md_merged.snap | 2 +- ...raphql-conformance-http-003.md_client.snap | 2 +- ...raphql-conformance-http-003.md_merged.snap | 2 +- ...raphql-conformance-http-004.md_client.snap | 2 +- ...raphql-conformance-http-004.md_merged.snap | 2 +- ...raphql-conformance-http-006.md_client.snap | 2 +- ...raphql-conformance-http-006.md_merged.snap | 2 +- ...raphql-conformance-http-015.md_client.snap | 2 +- ...raphql-conformance-http-015.md_merged.snap | 2 +- .../yaml-union-in-type.md_client.snap | 18 ++++---- .../yaml-union-in-type.md_merged.snap | 18 ++++---- 40 files changed, 212 insertions(+), 98 deletions(-) create mode 100644 src/core/jit/snapshots/tailcall__core__jit__builder__tests__alias_query.snap diff --git a/src/core/blueprint/from_config.rs b/src/core/blueprint/from_config.rs index 697f6e2d06..af450b56e0 100644 --- a/src/core/blueprint/from_config.rs +++ b/src/core/blueprint/from_config.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, BTreeSet}; use async_graphql::dynamic::SchemaBuilder; +use indexmap::IndexMap; use self::telemetry::to_opentelemetry; use super::{Server, TypeLike}; @@ -70,7 +71,7 @@ pub fn apply_batching(mut blueprint: Blueprint) -> Blueprint { pub fn to_json_schema_for_field(field: &Field, config: &Config) -> JsonSchema { to_json_schema(field, config) } -pub fn to_json_schema_for_args(args: &BTreeMap, config: &Config) -> JsonSchema { +pub fn to_json_schema_for_args(args: &IndexMap, config: &Config) -> JsonSchema { let mut schema_fields = BTreeMap::new(); for (name, arg) in args.iter() { schema_fields.insert(name.clone(), to_json_schema(arg, config)); diff --git a/src/core/config/config.rs b/src/core/config/config.rs index 702715493a..cb22208d47 100644 --- a/src/core/config/config.rs +++ b/src/core/config/config.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::fmt::{self, Display}; use std::num::NonZeroU64; @@ -6,6 +6,7 @@ use anyhow::Result; use async_graphql::parser::types::{ConstDirective, ServiceDocument}; use async_graphql::Positioned; use derive_setters::Setters; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value; use tailcall_macros::{CustomResolver, DirectiveDefinition, InputDefinition}; @@ -254,7 +255,8 @@ pub struct Field { /// /// Map of argument name and its definition. #[serde(default, skip_serializing_if = "is_default")] - pub args: BTreeMap, + #[schemars(with = "HashMap::")] + pub args: IndexMap, /// /// Publicly visible documentation for the field. diff --git a/src/core/config/from_document.rs b/src/core/config/from_document.rs index da6a94847e..5835a79542 100644 --- a/src/core/config/from_document.rs +++ b/src/core/config/from_document.rs @@ -8,6 +8,7 @@ use async_graphql::parser::types::{ use async_graphql::parser::Positioned; use async_graphql::Name; use async_graphql_value::ConstValue; +use indexmap::IndexMap; use super::telemetry::Telemetry; use super::Alias; @@ -294,7 +295,7 @@ fn to_field(field_definition: &FieldDefinition) -> Valid fn to_input_object_field(field_definition: &InputValueDefinition) -> Valid { to_common_field( field_definition, - BTreeMap::new(), + IndexMap::new(), field_definition .default_value .as_ref() @@ -303,7 +304,7 @@ fn to_input_object_field(field_definition: &InputValueDefinition) -> Valid( field: &F, - args: BTreeMap, + args: IndexMap, default_value: Option, ) -> Valid where @@ -356,8 +357,8 @@ fn to_type_of(type_: &Type) -> String { BaseType::List(ty) => to_type_of(ty), } } -fn to_args(field_definition: &FieldDefinition) -> BTreeMap { - let mut args: BTreeMap = BTreeMap::new(); +fn to_args(field_definition: &FieldDefinition) -> IndexMap { + let mut args = IndexMap::new(); for arg in field_definition.arguments.iter() { let arg_name = pos_name_to_string(&arg.node.name); diff --git a/src/core/config/transformer/snapshots/tailcall__core__config__transformer__union_input_type__tests__union_in_type.snap b/src/core/config/transformer/snapshots/tailcall__core__config__transformer__union_input_type__tests__union_in_type.snap index a18578c838..78dd4c5006 100644 --- a/src/core/config/transformer/snapshots/tailcall__core__config__transformer__union_input_type__tests__union_in_type.snap +++ b/src/core/config/transformer/snapshots/tailcall__core__config__transformer__union_input_type__tests__union_in_type.snap @@ -66,13 +66,13 @@ type NU { } type Query { - testVar0Var0(nnu: NNU__nu0, nu: NU__u0!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar0Var1(nnu: NNU__nu0, nu: NU__u1!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar0Var2(nnu: NNU__nu0, nu: NU__u2!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar1Var0(nnu: NNU__nu1, nu: NU__u0!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar1Var1(nnu: NNU__nu1, nu: NU__u1!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar1Var2(nnu: NNU__nu1, nu: NU__u2!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar2Var0(nnu: NNU__nu2, nu: NU__u0!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar2Var1(nnu: NNU__nu2, nu: NU__u1!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar2Var2(nnu: NNU__nu2, nu: NU__u2!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar0Var0(nu: NU__u0!, nnu: NNU__nu0): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar0Var1(nu: NU__u0!, nnu: NNU__nu1): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar0Var2(nu: NU__u0!, nnu: NNU__nu2): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar1Var0(nu: NU__u1!, nnu: NNU__nu0): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar1Var1(nu: NU__u1!, nnu: NNU__nu1): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar1Var2(nu: NU__u1!, nnu: NNU__nu2): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar2Var0(nu: NU__u2!, nnu: NNU__nu0): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar2Var1(nu: NU__u2!, nnu: NNU__nu1): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar2Var2(nu: NU__u2!, nnu: NNU__nu2): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") } diff --git a/src/core/generator/tests/snapshots/json_to_config_spec__add_cart.json.snap b/src/core/generator/tests/snapshots/json_to_config_spec__add_cart.json.snap index 5360dbccf8..7811cf43a2 100644 --- a/src/core/generator/tests/snapshots/json_to_config_spec__add_cart.json.snap +++ b/src/core/generator/tests/snapshots/json_to_config_spec__add_cart.json.snap @@ -17,7 +17,7 @@ input T4 { } type Mutation { - addCart(addCartInput: T4, code: String): T2 @http(baseURL: "https://dummyjson.com", body: "{{.args.addCartInput}}", method: "POST", path: "/carts/add", query: [{key: "code", value: "{{.args.code}}"}]) + addCart(code: String, addCartInput: T4): T2 @http(baseURL: "https://dummyjson.com", body: "{{.args.addCartInput}}", method: "POST", path: "/carts/add", query: [{key: "code", value: "{{.args.code}}"}]) } type T1 { diff --git a/src/core/ir/resolver_context_like.rs b/src/core/ir/resolver_context_like.rs index 6733a43875..190f91e5b2 100644 --- a/src/core/ir/resolver_context_like.rs +++ b/src/core/ir/resolver_context_like.rs @@ -95,7 +95,7 @@ impl SelectionField { fn from_jit_field( field: &crate::core::jit::Field, ConstValue>, ) -> SelectionField { - let name = field.name.clone(); + let name = field.output_name.to_string(); let selection_set = field .nested_iter(field.type_of.name()) .map(Self::from_jit_field) diff --git a/src/core/jit/builder.rs b/src/core/jit/builder.rs index 16a85e0ae6..69698d1456 100644 --- a/src/core/jit/builder.rs +++ b/src/core/jit/builder.rs @@ -206,18 +206,18 @@ impl Builder { Some(Flat::new(id.clone())), fragments, ); - let name = gql_field - .alias - .as_ref() - .map(|alias| alias.node.to_string()) - .unwrap_or(field_name.to_string()); let ir = match field_def { QueryField::Field((field_def, _)) => field_def.resolver.clone(), _ => None, }; let flat_field = Field { id, - name, + name: field_name.to_string(), + output_name: gql_field + .alias + .as_ref() + .map(|a| a.node.to_string()) + .unwrap_or(field_name.to_owned()), ir, type_of, type_condition: type_condition.to_string(), @@ -404,6 +404,21 @@ mod tests { insta::assert_debug_snapshot!(plan.into_nested()); } + #[test] + fn test_alias_query() { + let plan = plan( + r#" + query { + articles: posts { author: user { identifier: id } } + } + "#, + &Variables::new(), + ); + + assert!(plan.is_query()); + insta::assert_debug_snapshot!(plan.into_nested()); + } + #[test] fn test_simple_mutation() { let plan = plan( diff --git a/src/core/jit/context.rs b/src/core/jit/context.rs index d5ff29cd13..f52b34223b 100644 --- a/src/core/jit/context.rs +++ b/src/core/jit/context.rs @@ -2,6 +2,7 @@ use std::sync::{Arc, Mutex, MutexGuard}; use async_graphql::{Name, ServerError}; use async_graphql_value::ConstValue; +use indexmap::IndexMap; use super::error::*; use super::{Field, Nested, OperationPlan, Positioned}; @@ -39,8 +40,8 @@ pub struct Context<'a, Input, Output> { request: &'a RequestContext, } impl<'a, Input: Clone, Output> Context<'a, Input, Output> { - pub fn new(field: &'a Field, Input>, env: &'a RequestContext) -> Self { - Self { value: None, args: None, field, request: env } + pub fn new(field: &'a Field, Input>, request: &'a RequestContext) -> Self { + Self { request, value: None, args: Self::build_args(field), field } } pub fn with_value_and_field( @@ -48,19 +49,11 @@ impl<'a, Input: Clone, Output> Context<'a, Input, Output> { value: &'a Output, field: &'a Field, Input>, ) -> Self { - Self { args: None, value: Some(value), field, request: self.request } - } - - pub fn with_args(&self, args: indexmap::IndexMap<&str, Input>) -> Self { - let mut map = indexmap::IndexMap::new(); - for (key, value) in args { - map.insert(Name::new(key), value); - } Self { - value: self.value, - args: Some(map), - field: self.field, request: self.request, + args: Self::build_args(field), + value: Some(value), + field, } } @@ -71,6 +64,26 @@ impl<'a, Input: Clone, Output> Context<'a, Input, Output> { pub fn field(&self) -> &Field, Input> { self.field } + + fn build_args(field: &Field, Input>) -> Option> { + let mut arg_map = IndexMap::new(); + + for arg in field.args.iter() { + let name = arg.name.as_str(); + let value = arg + .value + .clone() + // TODO: default value resolution should happen in the InputResolver + .or_else(|| arg.default_value.clone()); + if let Some(value) = value { + arg_map.insert(Name::new(name), value); + } else if !arg.type_of.is_nullable() { + // TODO: throw error here + todo!() + } + } + Some(arg_map) + } } impl<'a> ResolverContextLike for Context<'a, ConstValue, ConstValue> { diff --git a/src/core/jit/error.rs b/src/core/jit/error.rs index 5bef9c43c6..8689b61ca4 100644 --- a/src/core/jit/error.rs +++ b/src/core/jit/error.rs @@ -27,7 +27,7 @@ pub enum ValidationError { // TODO: replace with sane error message. Right now, it's defined as is only for compatibility // with async_graphql error message for this case #[error(r#"internal: invalid value for scalar "{type_of}", expected "FieldValue::Value""#)] - ScalarInvalid { type_of: String, path: String }, + ScalarInvalid { type_of: String }, #[error("TypeName shape doesn't satisfy the processed object")] TypeNameMismatch, #[error(r#"internal: invalid item for enum "{type_of}""#)] diff --git a/src/core/jit/exec.rs b/src/core/jit/exec.rs index 6b4f855151..26e22c78ad 100644 --- a/src/core/jit/exec.rs +++ b/src/core/jit/exec.rs @@ -31,7 +31,7 @@ where Exec: IRExecutor, { pub fn new(plan: OperationPlan, exec: Exec) -> Self { - Self { exec, ctx: RequestContext::new(plan) } + Self { exec, ctx: RequestContext::new(plan.clone()) } } pub async fn store(&self) -> Store, Positioned>> { @@ -73,25 +73,9 @@ where async fn init(&mut self) { join_all(self.request.plan().as_nested().iter().map(|field| async { - let mut arg_map = indexmap::IndexMap::new(); - for arg in field.args.iter() { - let name = arg.name.as_str(); - let value: Option = arg - .value - .clone() - // TODO: default value resolution should happen in the InputResolver - .or_else(|| arg.default_value.clone()); - - if let Some(value) = value { - arg_map.insert(name, value); - } else if !arg.type_of.is_nullable() { - // TODO: throw error here - todo!() - } - } + let ctx = Context::new(field, self.request); // TODO: with_args should be called on inside iter_field on any level, not only // for root fields - let ctx = Context::new(field, self.request).with_args(arg_map); self.execute(&ctx, DataPath::new()).await })) .await; @@ -176,7 +160,7 @@ where let default_obj = Output::object(Output::JsonObject::new()); let value = ctx .value() - .and_then(|v| v.get_key(&field.name)) + .and_then(|v| v.get_key(&field.output_name)) // in case there is no value we still put some dumb empty value anyway // to force execution of the nested fields even when parent object is not present. // For async_graphql it's done by `fix_dangling_resolvers` fn that basically creates diff --git a/src/core/jit/model.rs b/src/core/jit/model.rs index a2d8a3e8cf..2fe51567fa 100644 --- a/src/core/jit/model.rs +++ b/src/core/jit/model.rs @@ -108,7 +108,11 @@ impl FieldId { #[derive(Clone)] pub struct Field { pub id: FieldId, + /// Name of key in the value object for this field pub name: String, + /// Output name (i.e. with alias) that should be used for the result value + /// of this field + pub output_name: String, pub ir: Option, pub type_of: crate::core::blueprint::Type, /// Specifies the name of type used in condition to fetch that field @@ -158,6 +162,7 @@ impl Field, Input> { Ok(Field { id: self.id, name: self.name, + output_name: self.output_name, ir: self.ir, type_of: self.type_of, type_condition: self.type_condition, @@ -187,6 +192,7 @@ impl Field { Ok(Field { id: self.id, name: self.name, + output_name: self.output_name, ir: self.ir, type_of: self.type_of, type_condition: self.type_condition, @@ -262,6 +268,7 @@ impl Field { Field { id: self.id, name: self.name, + output_name: self.output_name, ir: self.ir, type_of: self.type_of, type_condition: self.type_condition, @@ -280,6 +287,7 @@ impl Debug for Field { let mut debug_struct = f.debug_struct("Field"); debug_struct.field("id", &self.id); debug_struct.field("name", &self.name); + debug_struct.field("output_name", &self.output_name); if self.ir.is_some() { debug_struct.field("ir", &"Some(..)"); } @@ -298,6 +306,7 @@ impl Debug for Field { debug_struct.field("include", &self.include); } debug_struct.field("directives", &self.directives); + debug_struct.finish() } } diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__alias_query.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__alias_query.snap new file mode 100644 index 0000000000..0e0d13d8e2 --- /dev/null +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__alias_query.snap @@ -0,0 +1,44 @@ +--- +source: src/core/jit/builder.rs +expression: plan.into_nested() +--- +[ + Field { + id: 0, + name: "posts", + output_name: "articles", + ir: "Some(..)", + type_of: [Post], + type_condition: "Query", + extensions: Some( + Nested( + [ + Field { + id: 1, + name: "user", + output_name: "author", + ir: "Some(..)", + type_of: User, + type_condition: "Post", + extensions: Some( + Nested( + [ + Field { + id: 2, + name: "id", + output_name: "identifier", + type_of: ID!, + type_condition: "User", + directives: [], + }, + ], + ), + ), + directives: [], + }, + ], + ), + ), + directives: [], + }, +] diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__default_value.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__default_value.snap index 9bfb9e3660..b9ce57c2f4 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__default_value.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__default_value.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "createPost", + output_name: "createPost", ir: "Some(..)", type_of: Post, type_condition: "Mutation", @@ -44,6 +45,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "Post", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__directives.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__directives.snap index 624169f64e..a93aafa00d 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__directives.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__directives.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "users", + output_name: "users", ir: "Some(..)", type_of: [User], type_condition: "Query", @@ -15,6 +16,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "User", directives: [ @@ -34,6 +36,7 @@ expression: plan.into_nested() Field { id: 2, name: "name", + output_name: "name", type_of: String!, type_condition: "User", include: Some( diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__fragments.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__fragments.snap index cb7089873b..40266d97e5 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__fragments.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__fragments.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "user", + output_name: "user", ir: "Some(..)", type_of: User, type_condition: "Query", @@ -28,6 +29,7 @@ expression: plan.into_nested() Field { id: 1, name: "name", + output_name: "name", type_of: String!, type_condition: "User", directives: [], @@ -35,6 +37,7 @@ expression: plan.into_nested() Field { id: 2, name: "email", + output_name: "email", type_of: String!, type_condition: "User", directives: [], @@ -42,6 +45,7 @@ expression: plan.into_nested() Field { id: 3, name: "phone", + output_name: "phone", type_of: String, type_condition: "User", directives: [], @@ -49,6 +53,7 @@ expression: plan.into_nested() Field { id: 4, name: "title", + output_name: "title", type_of: String!, type_condition: "Post", directives: [], @@ -56,6 +61,7 @@ expression: plan.into_nested() Field { id: 5, name: "body", + output_name: "body", type_of: String!, type_condition: "Post", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__from_document.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__from_document.snap index e984aa64c0..c1e6d168b7 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__from_document.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__from_document.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "posts", + output_name: "posts", ir: "Some(..)", type_of: [Post], type_condition: "Query", @@ -15,6 +16,7 @@ expression: plan.into_nested() Field { id: 1, name: "user", + output_name: "user", ir: "Some(..)", type_of: User, type_condition: "Post", @@ -24,6 +26,7 @@ expression: plan.into_nested() Field { id: 2, name: "id", + output_name: "id", type_of: ID!, type_condition: "User", directives: [], @@ -31,6 +34,7 @@ expression: plan.into_nested() Field { id: 3, name: "name", + output_name: "name", type_of: String!, type_condition: "User", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__multiple_operations.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__multiple_operations.snap index 4f9c230fc0..31fc82f0ba 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__multiple_operations.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__multiple_operations.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "user", + output_name: "user", ir: "Some(..)", type_of: User, type_condition: "Query", @@ -28,6 +29,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "User", directives: [], @@ -35,6 +37,7 @@ expression: plan.into_nested() Field { id: 2, name: "username", + output_name: "username", type_of: String!, type_condition: "User", directives: [], @@ -47,6 +50,7 @@ expression: plan.into_nested() Field { id: 3, name: "posts", + output_name: "posts", ir: "Some(..)", type_of: [Post], type_condition: "Query", @@ -56,6 +60,7 @@ expression: plan.into_nested() Field { id: 4, name: "id", + output_name: "id", type_of: ID!, type_condition: "Post", directives: [], @@ -63,6 +68,7 @@ expression: plan.into_nested() Field { id: 5, name: "title", + output_name: "title", type_of: String!, type_condition: "Post", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation-2.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation-2.snap index a73a36b7d9..84141b1a62 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation-2.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation-2.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "createPost", + output_name: "createPost", ir: "Some(..)", type_of: Post, type_condition: "Mutation", @@ -44,6 +45,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "Post", directives: [], @@ -51,6 +53,7 @@ expression: plan.into_nested() Field { id: 2, name: "userId", + output_name: "userId", type_of: ID!, type_condition: "Post", directives: [], @@ -58,6 +61,7 @@ expression: plan.into_nested() Field { id: 3, name: "title", + output_name: "title", type_of: String!, type_condition: "Post", directives: [], @@ -65,6 +69,7 @@ expression: plan.into_nested() Field { id: 4, name: "body", + output_name: "body", type_of: String!, type_condition: "Post", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation.snap index 2df3bc5121..9a433b4292 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__resolving_operation.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "posts", + output_name: "posts", ir: "Some(..)", type_of: [Post], type_condition: "Query", @@ -15,6 +16,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "Post", directives: [], @@ -22,6 +24,7 @@ expression: plan.into_nested() Field { id: 2, name: "userId", + output_name: "userId", type_of: ID!, type_condition: "Post", directives: [], @@ -29,6 +32,7 @@ expression: plan.into_nested() Field { id: 3, name: "title", + output_name: "title", type_of: String!, type_condition: "Post", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_mutation.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_mutation.snap index 7f8bbbe66b..d447afdc34 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_mutation.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_mutation.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "createUser", + output_name: "createUser", ir: "Some(..)", type_of: User, type_condition: "Mutation", @@ -59,6 +60,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "User", directives: [], @@ -66,6 +68,7 @@ expression: plan.into_nested() Field { id: 2, name: "name", + output_name: "name", type_of: String!, type_condition: "User", directives: [], @@ -73,6 +76,7 @@ expression: plan.into_nested() Field { id: 3, name: "email", + output_name: "email", type_of: String!, type_condition: "User", directives: [], @@ -80,6 +84,7 @@ expression: plan.into_nested() Field { id: 4, name: "phone", + output_name: "phone", type_of: String, type_condition: "User", directives: [], @@ -87,6 +92,7 @@ expression: plan.into_nested() Field { id: 5, name: "website", + output_name: "website", type_of: String, type_condition: "User", directives: [], @@ -94,6 +100,7 @@ expression: plan.into_nested() Field { id: 6, name: "username", + output_name: "username", type_of: String!, type_condition: "User", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_query.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_query.snap index 1dc043d477..305af5ecbe 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_query.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__simple_query.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "posts", + output_name: "posts", ir: "Some(..)", type_of: [Post], type_condition: "Query", @@ -15,6 +16,7 @@ expression: plan.into_nested() Field { id: 1, name: "user", + output_name: "user", ir: "Some(..)", type_of: User, type_condition: "Post", @@ -24,6 +26,7 @@ expression: plan.into_nested() Field { id: 2, name: "id", + output_name: "id", type_of: ID!, type_condition: "User", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__unions.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__unions.snap index 9432388d5d..5d1a5b0b6f 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__unions.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__unions.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "getUserIdOrEmail", + output_name: "getUserIdOrEmail", ir: "Some(..)", type_of: UserIdOrEmail, type_condition: "Query", @@ -28,6 +29,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "UserId", directives: [], @@ -35,6 +37,7 @@ expression: plan.into_nested() Field { id: 2, name: "email", + output_name: "email", type_of: String!, type_condition: "UserEmail", directives: [], diff --git a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__variables.snap b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__variables.snap index 733a1018c8..0c7d65e877 100644 --- a/src/core/jit/snapshots/tailcall__core__jit__builder__tests__variables.snap +++ b/src/core/jit/snapshots/tailcall__core__jit__builder__tests__variables.snap @@ -6,6 +6,7 @@ expression: plan.into_nested() Field { id: 0, name: "user", + output_name: "user", ir: "Some(..)", type_of: User, type_condition: "Query", @@ -28,6 +29,7 @@ expression: plan.into_nested() Field { id: 1, name: "id", + output_name: "id", type_of: ID!, type_condition: "User", directives: [], @@ -35,6 +37,7 @@ expression: plan.into_nested() Field { id: 2, name: "name", + output_name: "name", type_of: String!, type_condition: "User", directives: [], diff --git a/src/core/jit/synth/synth.rs b/src/core/jit/synth/synth.rs index 23ed77d578..5c40f41f35 100644 --- a/src/core/jit/synth/synth.rs +++ b/src/core/jit/synth/synth.rs @@ -62,7 +62,8 @@ where continue; } let val = self.iter(child, None, &DataPath::new())?; - data.insert_key(child.name.as_str(), val); + + data.insert_key(&child.output_name, val); } Ok(Value::object(data)) @@ -148,11 +149,10 @@ where if scalar.validate(value) { Ok(value.clone()) } else { - Err(ValidationError::ScalarInvalid { - type_of: node.type_of.name().to_string(), - path: node.name.to_string(), - } - .into()) + Err( + ValidationError::ScalarInvalid { type_of: node.type_of.name().to_string() } + .into(), + ) } } else if self.plan.field_is_enum(node) { if value @@ -193,9 +193,8 @@ where let include = self.include(child); if include { let val = obj.get_key(child.name.as_str()); - ans.insert_key( - child.name.as_str(), + &child.output_name, self.iter(child, val.map(TypedValueRef::new), data_path)?, ); } @@ -234,7 +233,7 @@ where let mut parent = self.plan.find_field(node.id.clone()); while let Some(field) = parent { - path.push(PathSegment::Field(field.name.to_string())); + path.push(PathSegment::Field(field.output_name.to_string())); parent = field .parent() .and_then(|id| self.plan.find_field(id.clone())); diff --git a/tests/core/snapshots/call-mutation.md_client.snap b/tests/core/snapshots/call-mutation.md_client.snap index 86b6c44f11..4485a75813 100644 --- a/tests/core/snapshots/call-mutation.md_client.snap +++ b/tests/core/snapshots/call-mutation.md_client.snap @@ -26,7 +26,7 @@ scalar JSON type Mutation { attachPostToFirstUser(postId: Int!): User - attachPostToUser(postId: Int!, userId: Int!): User + attachPostToUser(userId: Int!, postId: Int!): User insertMockedPost: Post insertPost(input: PostInput): Post insertPostToFirstUser(input: PostInputWithoutUserId): Post diff --git a/tests/core/snapshots/call-mutation.md_merged.snap b/tests/core/snapshots/call-mutation.md_merged.snap index ee40791749..ccdcdba79b 100644 --- a/tests/core/snapshots/call-mutation.md_merged.snap +++ b/tests/core/snapshots/call-mutation.md_merged.snap @@ -22,7 +22,7 @@ input PostInputWithoutUserId { type Mutation { attachPostToFirstUser(postId: Int!): User @call(steps: [{mutation: "attachPostToUser", args: {postId: "{{.args.postId}}", userId: 1}}]) - attachPostToUser(postId: Int!, userId: Int!): User + attachPostToUser(userId: Int!, postId: Int!): User @http(body: "{\"postId\":{{.args.postId}}}", method: "PATCH", path: "/users/{{.args.userId}}") insertMockedPost: Post @call(steps: [{mutation: "insertPost", args: {input: {body: "post-body", title: "post-title", userId: 1}}}]) diff --git a/tests/core/snapshots/graphql-conformance-003.md_client.snap b/tests/core/snapshots/graphql-conformance-003.md_client.snap index 0c28ea612b..dacaf4db9f 100644 --- a/tests/core/snapshots/graphql-conformance-003.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-003.md_client.snap @@ -45,7 +45,7 @@ scalar Url type User { id: ID! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! } schema { diff --git a/tests/core/snapshots/graphql-conformance-003.md_merged.snap b/tests/core/snapshots/graphql-conformance-003.md_merged.snap index d704383baf..db0f96da00 100644 --- a/tests/core/snapshots/graphql-conformance-003.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-003.md_merged.snap @@ -15,5 +15,5 @@ type Query { type User { id: ID! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! } diff --git a/tests/core/snapshots/graphql-conformance-015.md_client.snap b/tests/core/snapshots/graphql-conformance-015.md_client.snap index 1e26b06309..770537c269 100644 --- a/tests/core/snapshots/graphql-conformance-015.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-015.md_client.snap @@ -47,7 +47,7 @@ type User { featuredVideoPreview(video: VideoSize! = {}): String! id: ID! name: String! - profilePic(height: Int = 100, size: Int! = 100, width: Int): String! + profilePic(size: Int! = 100, width: Int, height: Int = 100): String! searchComments(query: [String]! = [["today"]]): String! } diff --git a/tests/core/snapshots/graphql-conformance-015.md_merged.snap b/tests/core/snapshots/graphql-conformance-015.md_merged.snap index a9166dcdc9..28820191aa 100644 --- a/tests/core/snapshots/graphql-conformance-015.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-015.md_merged.snap @@ -25,7 +25,7 @@ type User { @expr(body: "video_{{.value.id}}_{{.args.video.width}}_{{.args.video.height}}_{{.args.video.hdr}}") id: ID! name: String! - profilePic(height: Int = 100, size: Int! = 100, width: Int): String! + profilePic(size: Int! = 100, width: Int, height: Int = 100): String! @expr(body: "{{.value.id}}_{{.args.size}}_{{.args.width}}_{{.args.height}}") searchComments(query: [String]! = [["today"]]): String! @expr(body: "video_{{.value.id}}_{{.args.query}}") } diff --git a/tests/core/snapshots/graphql-conformance-http-003.md_client.snap b/tests/core/snapshots/graphql-conformance-http-003.md_client.snap index 0c28ea612b..dacaf4db9f 100644 --- a/tests/core/snapshots/graphql-conformance-http-003.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-http-003.md_client.snap @@ -45,7 +45,7 @@ scalar Url type User { id: ID! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! } schema { diff --git a/tests/core/snapshots/graphql-conformance-http-003.md_merged.snap b/tests/core/snapshots/graphql-conformance-http-003.md_merged.snap index 621a90aea1..15c61094e1 100644 --- a/tests/core/snapshots/graphql-conformance-http-003.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-http-003.md_merged.snap @@ -15,7 +15,7 @@ type Query { type User { id: ID! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! @http( path: "/pic" query: [ diff --git a/tests/core/snapshots/graphql-conformance-http-004.md_client.snap b/tests/core/snapshots/graphql-conformance-http-004.md_client.snap index 0c28ea612b..dacaf4db9f 100644 --- a/tests/core/snapshots/graphql-conformance-http-004.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-http-004.md_client.snap @@ -45,7 +45,7 @@ scalar Url type User { id: ID! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! } schema { diff --git a/tests/core/snapshots/graphql-conformance-http-004.md_merged.snap b/tests/core/snapshots/graphql-conformance-http-004.md_merged.snap index 621a90aea1..15c61094e1 100644 --- a/tests/core/snapshots/graphql-conformance-http-004.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-http-004.md_merged.snap @@ -15,7 +15,7 @@ type Query { type User { id: ID! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! @http( path: "/pic" query: [ diff --git a/tests/core/snapshots/graphql-conformance-http-006.md_client.snap b/tests/core/snapshots/graphql-conformance-http-006.md_client.snap index b746f0b983..ba98860b7c 100644 --- a/tests/core/snapshots/graphql-conformance-http-006.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-http-006.md_client.snap @@ -47,7 +47,7 @@ type User { id: ID! mutualFriends(first: Int): [User!]! name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! } schema { diff --git a/tests/core/snapshots/graphql-conformance-http-006.md_merged.snap b/tests/core/snapshots/graphql-conformance-http-006.md_merged.snap index 5ead572f39..02b99f0acb 100644 --- a/tests/core/snapshots/graphql-conformance-http-006.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-http-006.md_merged.snap @@ -22,6 +22,6 @@ type User { query: [{key: "id", value: "{{.value.id}}"}, {key: "first", value: "{{.args.first}}"}] ) name: String! - profilePic(height: Int, size: Int, width: Int): String! + profilePic(size: Int, width: Int, height: Int): String! @expr(body: "{{.value.id}}_{{.args.size}}_{{.args.width}}_{{.args.height}}") } diff --git a/tests/core/snapshots/graphql-conformance-http-015.md_client.snap b/tests/core/snapshots/graphql-conformance-http-015.md_client.snap index b0ad1b799d..6f41f83b4d 100644 --- a/tests/core/snapshots/graphql-conformance-http-015.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-http-015.md_client.snap @@ -47,7 +47,7 @@ type User { featuredVideoPreview(video: VideoSize! = {}): String! id: ID! name: String! - profilePic(height: Int = 100, size: Int! = 100, width: Int): String! + profilePic(size: Int! = 100, width: Int, height: Int = 100): String! searchComments(query: [String]! = [["today"]]): String! } diff --git a/tests/core/snapshots/graphql-conformance-http-015.md_merged.snap b/tests/core/snapshots/graphql-conformance-http-015.md_merged.snap index 880d478b00..38b944a41b 100644 --- a/tests/core/snapshots/graphql-conformance-http-015.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-http-015.md_merged.snap @@ -25,7 +25,7 @@ type User { @expr(body: "video_{{.value.id}}_{{.args.video.width}}_{{.args.video.height}}_{{.args.video.hdr}}") id: ID! name: String! - profilePic(height: Int = 100, size: Int! = 100, width: Int): String! + profilePic(size: Int! = 100, width: Int, height: Int = 100): String! @expr(body: "{{.value.id}}_{{.args.size}}_{{.args.width}}_{{.args.height}}") searchComments(query: [String]! = [["today"]]): String! @expr(body: "video_{{.value.id}}_{{.args.query}}") } diff --git a/tests/core/snapshots/yaml-union-in-type.md_client.snap b/tests/core/snapshots/yaml-union-in-type.md_client.snap index 0910863dd4..27c018f483 100644 --- a/tests/core/snapshots/yaml-union-in-type.md_client.snap +++ b/tests/core/snapshots/yaml-union-in-type.md_client.snap @@ -60,15 +60,15 @@ input NU__u2 { scalar PhoneNumber type Query { - testVar0Var0(nnu: NNU__nu0, nu: NU__u0!): U - testVar0Var1(nnu: NNU__nu0, nu: NU__u1!): U - testVar0Var2(nnu: NNU__nu0, nu: NU__u2!): U - testVar1Var0(nnu: NNU__nu1, nu: NU__u0!): U - testVar1Var1(nnu: NNU__nu1, nu: NU__u1!): U - testVar1Var2(nnu: NNU__nu1, nu: NU__u2!): U - testVar2Var0(nnu: NNU__nu2, nu: NU__u0!): U - testVar2Var1(nnu: NNU__nu2, nu: NU__u1!): U - testVar2Var2(nnu: NNU__nu2, nu: NU__u2!): U + testVar0Var0(nu: NU__u0!, nnu: NNU__nu0): U + testVar0Var1(nu: NU__u0!, nnu: NNU__nu1): U + testVar0Var2(nu: NU__u0!, nnu: NNU__nu2): U + testVar1Var0(nu: NU__u1!, nnu: NNU__nu0): U + testVar1Var1(nu: NU__u1!, nnu: NNU__nu1): U + testVar1Var2(nu: NU__u1!, nnu: NNU__nu2): U + testVar2Var0(nu: NU__u2!, nnu: NNU__nu0): U + testVar2Var1(nu: NU__u2!, nnu: NNU__nu1): U + testVar2Var2(nu: NU__u2!, nnu: NNU__nu2): U } type T1 { diff --git a/tests/core/snapshots/yaml-union-in-type.md_merged.snap b/tests/core/snapshots/yaml-union-in-type.md_merged.snap index 9d92d84dba..75f49f1e71 100644 --- a/tests/core/snapshots/yaml-union-in-type.md_merged.snap +++ b/tests/core/snapshots/yaml-union-in-type.md_merged.snap @@ -66,15 +66,15 @@ type NU { } type Query { - testVar0Var0(nnu: NNU__nu0, nu: NU__u0!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar0Var1(nnu: NNU__nu0, nu: NU__u1!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar0Var2(nnu: NNU__nu0, nu: NU__u2!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar1Var0(nnu: NNU__nu1, nu: NU__u0!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar1Var1(nnu: NNU__nu1, nu: NU__u1!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar1Var2(nnu: NNU__nu1, nu: NU__u2!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar2Var0(nnu: NNU__nu2, nu: NU__u0!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar2Var1(nnu: NNU__nu2, nu: NU__u1!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") - testVar2Var2(nnu: NNU__nu2, nu: NU__u2!): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar0Var0(nu: NU__u0!, nnu: NNU__nu0): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar0Var1(nu: NU__u0!, nnu: NNU__nu1): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar0Var2(nu: NU__u0!, nnu: NNU__nu2): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar1Var0(nu: NU__u1!, nnu: NNU__nu0): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar1Var1(nu: NU__u1!, nnu: NNU__nu1): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar1Var2(nu: NU__u1!, nnu: NNU__nu2): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar2Var0(nu: NU__u2!, nnu: NNU__nu0): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar2Var1(nu: NU__u2!, nnu: NNU__nu1): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") + testVar2Var2(nu: NU__u2!, nnu: NNU__nu2): U @http(baseURL: "http://localhost", path: "/users/{{args.nu.u}}") } type T1 {