From 10a8b71adbba0a5a93e1d38c89729a55aa9d2696 Mon Sep 17 00:00:00 2001 From: sunli Date: Sat, 16 May 2020 10:05:48 +0800 Subject: [PATCH] Preserve field order for introspection. #89 --- Cargo.toml | 7 ++--- async-graphql-actix-web/Cargo.toml | 4 +-- async-graphql-derive/Cargo.toml | 4 +-- async-graphql-derive/src/enum.rs | 2 +- async-graphql-derive/src/input_object.rs | 2 +- async-graphql-derive/src/interface.rs | 6 ++--- async-graphql-derive/src/object.rs | 4 +-- async-graphql-derive/src/simple_object.rs | 2 +- async-graphql-derive/src/subscription.rs | 4 +-- async-graphql-derive/src/union.rs | 2 +- async-graphql-lambda/Cargo.toml | 2 +- async-graphql-parser/Cargo.toml | 2 +- async-graphql-tide/Cargo.toml | 4 +-- async-graphql-warp/Cargo.toml | 4 +-- src/lib.rs | 2 ++ src/model/field.rs | 7 ++--- src/model/type.rs | 8 +++--- src/registry.rs | 26 ++++++++++--------- src/schema.rs | 6 ++--- src/types/connection/connection_type.rs | 4 +-- src/types/connection/edge.rs | 4 +-- src/types/query_root.rs | 4 +-- .../rules/arguments_of_correct_type.rs | 4 +-- src/validation/rules/known_argument_names.rs | 4 +-- 24 files changed, 59 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 97f47dcf..f1383cd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "async-graphql" -version = "1.12.7" +version = "1.12.8" authors = ["sunli "] edition = "2018" description = "The GraphQL server library implemented by rust" @@ -17,8 +17,8 @@ readme = "README.md" default = ["bson", "uuid", "url", "chrono-tz"] [dependencies] -async-graphql-parser = { path = "async-graphql-parser", version = "0.3.1" } -async-graphql-derive = { path = "async-graphql-derive", version = "1.12.7" } +async-graphql-parser = { path = "async-graphql-parser", version = "0.4.0" } +async-graphql-derive = { path = "async-graphql-derive", version = "1.12.8" } anyhow = "1.0.26" thiserror = "1.0.11" async-trait = "0.1.30" @@ -42,6 +42,7 @@ http = "0.2.1" fnv = "1.0.6" regex = "1.3.5" tracing = "0.1.13" +indexmap = "1.3.2" bson = { version = "0.14.1", optional = true } uuid = { version = "0.8.1", optional = true } url = { version = "2.1.1", optional = true } diff --git a/async-graphql-actix-web/Cargo.toml b/async-graphql-actix-web/Cargo.toml index 73febc12..0ed54f84 100644 --- a/async-graphql-actix-web/Cargo.toml +++ b/async-graphql-actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "async-graphql-actix-web" -version = "1.4.7" +version = "1.4.8" authors = ["sunli "] edition = "2018" description = "async-graphql for actix-web" @@ -13,7 +13,7 @@ keywords = ["futures", "async", "graphql"] categories = ["network-programming", "asynchronous"] [dependencies] -async-graphql = { path = "..", version = "1.12.7" } +async-graphql = { path = "..", version = "1.12.8" } actix-web = "2.0.0" actix-web-actors = "2.0.0" actix = "0.9.0" diff --git a/async-graphql-derive/Cargo.toml b/async-graphql-derive/Cargo.toml index 75c262db..ad5270ff 100644 --- a/async-graphql-derive/Cargo.toml +++ b/async-graphql-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "async-graphql-derive" -version = "1.12.7" +version = "1.12.8" authors = ["sunli "] edition = "2018" description = "Macros for async-graphql" @@ -16,7 +16,7 @@ categories = ["network-programming", "asynchronous"] proc-macro = true [dependencies] -async-graphql-parser = { path = "../async-graphql-parser", version = "0.3.1" } +async-graphql-parser = { path = "../async-graphql-parser", version = "0.4.0" } proc-macro2 = "1.0.6" syn = { version = "1.0.20", features = ["full", "extra-traits"] } quote = "1.0.3" diff --git a/async-graphql-derive/src/enum.rs b/async-graphql-derive/src/enum.rs index a8359a34..dcf4bb76 100644 --- a/async-graphql-derive/src/enum.rs +++ b/async-graphql-derive/src/enum.rs @@ -146,7 +146,7 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result Result< name: #gql_typename.to_string(), description: #desc, input_fields: { - let mut fields = std::collections::HashMap::new(); + let mut fields = #crate_name::indexmap::IndexMap::new(); #(#schema_fields)* fields } diff --git a/async-graphql-derive/src/interface.rs b/async-graphql-derive/src/interface.rs index 3a649f1c..8d526275 100644 --- a/async-graphql-derive/src/interface.rs +++ b/async-graphql-derive/src/interface.rs @@ -223,7 +223,7 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result name: #name.to_string(), description: #desc, args: { - let mut args = std::collections::HashMap::new(); + let mut args = #crate_name::indexmap::IndexMap::new(); #(#schema_args)* args }, @@ -286,12 +286,12 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result name: #gql_typename.to_string(), description: #desc, fields: { - let mut fields = std::collections::HashMap::new(); + let mut fields = #crate_name::indexmap::IndexMap::new(); #(#schema_fields)* fields }, possible_types: { - let mut possible_types = std::collections::HashSet::new(); + let mut possible_types = #crate_name::indexmap::IndexSet::new(); #(#possible_types)* possible_types }, diff --git a/async-graphql-derive/src/object.rs b/async-graphql-derive/src/object.rs index 503f5a05..2901debb 100644 --- a/async-graphql-derive/src/object.rs +++ b/async-graphql-derive/src/object.rs @@ -343,7 +343,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result< name: #field_name.to_string(), description: #field_desc, args: { - let mut args = std::collections::HashMap::new(); + let mut args = #crate_name::indexmap::IndexMap::new(); #(#schema_args)* args }, @@ -441,7 +441,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result< name: #gql_typename.to_string(), description: #desc, fields: { - let mut fields = std::collections::HashMap::new(); + let mut fields = #crate_name::indexmap::IndexMap::new(); #(#schema_fields)* fields }, diff --git a/async-graphql-derive/src/simple_object.rs b/async-graphql-derive/src/simple_object.rs index cedf549d..aac22320 100644 --- a/async-graphql-derive/src/simple_object.rs +++ b/async-graphql-derive/src/simple_object.rs @@ -161,7 +161,7 @@ pub fn generate(object_args: &args::Object, input: &mut DeriveInput) -> Result Result< name: #field_name.to_string(), description: #field_desc, args: { - let mut args = std::collections::HashMap::new(); + let mut args = #crate_name::indexmap::IndexMap::new(); #(#schema_args)* args }, @@ -316,7 +316,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result< name: #gql_typename.to_string(), description: #desc, fields: { - let mut fields = std::collections::HashMap::new(); + let mut fields = #crate_name::indexmap::IndexMap::new(); #(#schema_fields)* fields }, diff --git a/async-graphql-derive/src/union.rs b/async-graphql-derive/src/union.rs index 82a892c6..096fde5c 100644 --- a/async-graphql-derive/src/union.rs +++ b/async-graphql-derive/src/union.rs @@ -119,7 +119,7 @@ pub fn generate(union_args: &args::Interface, input: &DeriveInput) -> Result"] edition = "2018" description = "GraphQL query parser for async-graphql" diff --git a/async-graphql-tide/Cargo.toml b/async-graphql-tide/Cargo.toml index 5ee6bef9..2ac77e79 100644 --- a/async-graphql-tide/Cargo.toml +++ b/async-graphql-tide/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "async-graphql-tide" -version = "1.4.7" +version = "1.4.8" authors = ["vkill "] edition = "2018" description = "async-graphql for tide" @@ -13,7 +13,7 @@ keywords = ["futures", "async", "graphql"] categories = ["network-programming", "asynchronous"] [dependencies] -async-graphql = { path = "..", version = "1.12.7" } +async-graphql = { path = "..", version = "1.12.8" } tide = "0.8" async-trait = "0.1.30" serde_json = "1.0.51" diff --git a/async-graphql-warp/Cargo.toml b/async-graphql-warp/Cargo.toml index ed3b9306..67ccc647 100644 --- a/async-graphql-warp/Cargo.toml +++ b/async-graphql-warp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "async-graphql-warp" -version = "1.4.7" +version = "1.4.8" authors = ["sunli "] edition = "2018" description = "async-graphql for warp" @@ -13,7 +13,7 @@ keywords = ["futures", "async", "graphql"] categories = ["network-programming", "asynchronous"] [dependencies] -async-graphql = { path = "..", version = "1.12.7" } +async-graphql = { path = "..", version = "1.12.8" } warp = "0.2.2" futures = "0.3.0" bytes = "0.5.4" diff --git a/src/lib.rs b/src/lib.rs index ca65fb2e..d889a35d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,6 +109,8 @@ pub use async_trait; #[doc(hidden)] pub use futures; #[doc(hidden)] +pub use indexmap; +#[doc(hidden)] pub use serde_json; pub mod http; diff --git a/src/model/field.rs b/src/model/field.rs index dcaadcdb..9888f8d1 100644 --- a/src/model/field.rs +++ b/src/model/field.rs @@ -20,17 +20,14 @@ impl<'a> __Field<'a> { } async fn args(&self) -> Vec<__InputValue<'a>> { - let mut args = self - .field + self.field .args .values() .map(|input_value| __InputValue { registry: self.registry, input_value, }) - .collect_vec(); - args.sort_by(|a, b| a.input_value.name.cmp(b.input_value.name)); - args + .collect_vec() } #[field(name = "type")] diff --git a/src/model/type.rs b/src/model/type.rs index 999fc419..c5166aa2 100644 --- a/src/model/type.rs +++ b/src/model/type.rs @@ -96,8 +96,8 @@ impl<'a> __Type<'a> { #[arg(default = "false")] include_deprecated: bool, ) -> Option>> { if let TypeDetail::Named(ty) = &self.detail { - ty.fields().and_then(|fields| { - let mut fields = fields + ty.fields().map(|fields| { + fields .values() .filter(|field| { (include_deprecated || field.deprecation.is_none()) @@ -107,9 +107,7 @@ impl<'a> __Type<'a> { registry: self.registry, field, }) - .collect_vec(); - fields.sort_by(|a, b| a.field.name.cmp(&b.field.name)); - Some(fields) + .collect_vec() }) } else { None diff --git a/src/registry.rs b/src/registry.rs index a0b3d83d..4732b436 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -1,6 +1,8 @@ use crate::parser::query::Type as ParsedType; use crate::validators::InputValueValidator; use crate::{model, Any, Type as _, Value}; +use indexmap::map::IndexMap; +use indexmap::set::IndexSet; use std::collections::{HashMap, HashSet}; use std::fmt::Write; use std::sync::Arc; @@ -102,7 +104,7 @@ pub struct MetaInputValue { pub struct MetaField { pub name: String, pub description: Option<&'static str>, - pub args: HashMap<&'static str, MetaInputValue>, + pub args: IndexMap<&'static str, MetaInputValue>, pub ty: String, pub deprecation: Option<&'static str>, pub cache_control: CacheControl, @@ -203,7 +205,7 @@ pub enum MetaType { Object { name: String, description: Option<&'static str>, - fields: HashMap, + fields: IndexMap, cache_control: CacheControl, extends: bool, keys: Option>, @@ -211,25 +213,25 @@ pub enum MetaType { Interface { name: String, description: Option<&'static str>, - fields: HashMap, - possible_types: HashSet, + fields: IndexMap, + possible_types: IndexSet, extends: bool, keys: Option>, }, Union { name: String, description: Option<&'static str>, - possible_types: HashSet, + possible_types: IndexSet, }, Enum { name: String, description: Option<&'static str>, - enum_values: HashMap<&'static str, MetaEnumValue>, + enum_values: IndexMap<&'static str, MetaEnumValue>, }, InputObject { name: String, description: Option<&'static str>, - input_fields: HashMap, + input_fields: IndexMap, }, } @@ -238,7 +240,7 @@ impl MetaType { self.fields().and_then(|fields| fields.get(name)) } - pub fn fields(&self) -> Option<&HashMap> { + pub fn fields(&self) -> Option<&IndexMap> { match self { MetaType::Object { fields, .. } => Some(&fields), MetaType::Interface { fields, .. } => Some(&fields), @@ -300,7 +302,7 @@ impl MetaType { } } - pub fn possible_types(&self) -> Option<&HashSet> { + pub fn possible_types(&self) -> Option<&IndexSet> { match self { MetaType::Interface { possible_types, .. } => Some(possible_types), MetaType::Union { possible_types, .. } => Some(possible_types), @@ -331,7 +333,7 @@ pub struct MetaDirective { pub name: &'static str, pub description: Option<&'static str>, pub locations: Vec, - pub args: HashMap<&'static str, MetaInputValue>, + pub args: IndexMap<&'static str, MetaInputValue>, } pub struct Registry { @@ -552,7 +554,7 @@ impl Registry { name: "_Service".to_string(), description: None, fields: { - let mut fields = HashMap::new(); + let mut fields = IndexMap::new(); fields.insert( "sdl".to_string(), MetaField { @@ -600,7 +602,7 @@ impl Registry { name: "_entities".to_string(), description: None, args: { - let mut args = HashMap::new(); + let mut args = IndexMap::new(); args.insert( "representations", MetaInputValue { diff --git a/src/schema.rs b/src/schema.rs index 34ecdd49..003924d1 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -14,8 +14,8 @@ use crate::{ use bytes::Bytes; use futures::channel::mpsc; use futures::Stream; +use indexmap::map::IndexMap; use std::any::Any; -use std::collections::HashMap; use std::sync::atomic::AtomicUsize; use std::sync::Arc; @@ -143,7 +143,7 @@ where __DirectiveLocation::INLINE_FRAGMENT ], args: { - let mut args = HashMap::new(); + let mut args = IndexMap::new(); args.insert("if", MetaInputValue { name: "if", description: Some("Included when true."), @@ -164,7 +164,7 @@ where __DirectiveLocation::INLINE_FRAGMENT ], args: { - let mut args = HashMap::new(); + let mut args = IndexMap::new(); args.insert("if", MetaInputValue { name: "if", description: Some("Skipped when true."), diff --git a/src/types/connection/connection_type.rs b/src/types/connection/connection_type.rs index 2cc16438..3c332220 100644 --- a/src/types/connection/connection_type.rs +++ b/src/types/connection/connection_type.rs @@ -5,10 +5,10 @@ use crate::{ do_resolve, registry, Context, ContextSelectionSet, EmptyEdgeFields, Error, ObjectType, OutputValueType, Pos, QueryError, Result, Type, }; +use indexmap::map::IndexMap; use inflector::Inflector; use itertools::Itertools; use std::borrow::Cow; -use std::collections::HashMap; /// Connection type /// @@ -103,7 +103,7 @@ impl Type for Con name: Self::type_name().to_string(), description: None, fields: { - let mut fields = HashMap::new(); + let mut fields = IndexMap::new(); fields.insert( "pageInfo".to_string(), diff --git a/src/types/connection/edge.rs b/src/types/connection/edge.rs index b7481843..7ed81ea1 100644 --- a/src/types/connection/edge.rs +++ b/src/types/connection/edge.rs @@ -2,8 +2,8 @@ use crate::{ do_resolve, registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Pos, Result, Type, }; +use indexmap::map::IndexMap; use std::borrow::Cow; -use std::collections::HashMap; pub struct Edge<'a, T, E> { pub cursor: &'a str, @@ -53,7 +53,7 @@ where name: Self::type_name().to_string(), description: Some("An edge in a connection."), fields: { - let mut fields = HashMap::new(); + let mut fields = IndexMap::new(); fields.insert( "node".to_string(), diff --git a/src/types/query_root.rs b/src/types/query_root.rs index 76ed1c12..664c07c2 100644 --- a/src/types/query_root.rs +++ b/src/types/query_root.rs @@ -5,8 +5,8 @@ use crate::{ QueryError, Result, Type, Value, }; use async_graphql_derive::SimpleObject; +use indexmap::map::IndexMap; use std::borrow::Cow; -use std::collections::HashMap; /// Federation service #[SimpleObject(internal)] @@ -51,7 +51,7 @@ impl Type for QueryRoot { name: "__type".to_string(), description: Some("Request the type information of a single type."), args: { - let mut args = HashMap::new(); + let mut args = IndexMap::new(); args.insert( "name", registry::MetaInputValue { diff --git a/src/validation/rules/arguments_of_correct_type.rs b/src/validation/rules/arguments_of_correct_type.rs index 85d7a9ac..c60856b3 100644 --- a/src/validation/rules/arguments_of_correct_type.rs +++ b/src/validation/rules/arguments_of_correct_type.rs @@ -4,11 +4,11 @@ use crate::registry::MetaInputValue; use crate::validation::utils::is_valid_input_value; use crate::validation::visitor::{Visitor, VisitorContext}; use crate::{Positioned, QueryPathSegment, Value}; -use std::collections::HashMap; +use indexmap::map::IndexMap; #[derive(Default)] pub struct ArgumentsOfCorrectType<'a> { - current_args: Option<&'a HashMap<&'static str, MetaInputValue>>, + current_args: Option<&'a IndexMap<&'static str, MetaInputValue>>, } impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> { diff --git a/src/validation/rules/known_argument_names.rs b/src/validation/rules/known_argument_names.rs index 31e32719..2c0eb4da 100644 --- a/src/validation/rules/known_argument_names.rs +++ b/src/validation/rules/known_argument_names.rs @@ -3,7 +3,7 @@ use crate::registry::MetaInputValue; use crate::validation::suggestion::make_suggestion; use crate::validation::visitor::{Visitor, VisitorContext}; use crate::{Positioned, Value}; -use std::collections::HashMap; +use indexmap::map::IndexMap; enum ArgsType<'a> { Directive(&'a str), @@ -15,7 +15,7 @@ enum ArgsType<'a> { #[derive(Default)] pub struct KnownArgumentNames<'a> { - current_args: Option<(&'a HashMap<&'static str, MetaInputValue>, ArgsType<'a>)>, + current_args: Option<(&'a IndexMap<&'static str, MetaInputValue>, ArgsType<'a>)>, } impl<'a> KnownArgumentNames<'a> {