diff --git a/src/builder.rs b/src/builder.rs index 8a031267..6baf1526 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,3 +1,4 @@ +use crate::constants::{aggregate, args, connection, introspection, mutation, page_info, pagination}; use crate::error::{GraphQLError, GraphQLResult}; use crate::graphql::*; use crate::gson; @@ -122,7 +123,7 @@ where T: Text<'a> + Eq + AsRef, { let at_most: gson::Value = read_argument( - "atMost", + args::AT_MOST, field, query_field, variables, @@ -217,7 +218,7 @@ where { // nodeId is a base64 encoded string of [schema, table, pkey_val1, pkey_val2, ...] let node_id_base64_encoded_json_string: gson::Value = read_argument( - "nodeId", + args::NODE_ID, field, query_field, variables, @@ -238,7 +239,7 @@ where { // [{"name": "bob", "email": "a@b.com"}, {..}] let validated: gson::Value = read_argument( - "objects", + args::OBJECTS, field, query_field, variables, @@ -247,7 +248,7 @@ where // [OrderBy!] let insert_type: InsertInputType = match field - .get_arg("objects") + .get_arg(args::OBJECTS) .expect("failed to get `objects` argument") .type_() .unmodified_type() @@ -337,7 +338,7 @@ where match &type_ { __Type::InsertResponse(xtype) => { // Raise for disallowed arguments - restrict_allowed_arguments(&["objects"], query_field)?; + restrict_allowed_arguments(&[args::OBJECTS], query_field)?; let objects: Vec = read_argument_objects(field, query_field, variables, variable_definitions)?; @@ -355,10 +356,10 @@ where match field_map.get(selection_field.name.as_ref()) { None => return Err(GraphQLError::validation("unknown field in insert")), Some(f) => builder_fields.push(match f.name().as_ref() { - "affectedCount" => InsertSelection::AffectedCount { + mutation::AFFECTED_COUNT => InsertSelection::AffectedCount { alias: alias_or_name(&selection_field), }, - "records" => { + mutation::RECORDS => { let node_builder = to_node_builder( f, &selection_field, @@ -369,7 +370,7 @@ where ); InsertSelection::Records(node_builder?) } - "__typename" => InsertSelection::Typename { + introspection::TYPENAME => InsertSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype .name() @@ -434,10 +435,10 @@ where T: Text<'a> + Eq + AsRef, { let validated: gson::Value = - read_argument("set", field, query_field, variables, variable_definitions)?; + read_argument(args::SET, field, query_field, variables, variable_definitions)?; let update_type: UpdateInputType = match field - .get_arg("set") + .get_arg(args::SET) .expect("failed to get `set` argument") .type_() .unmodified_type() @@ -506,7 +507,7 @@ where match &type_ { __Type::UpdateResponse(xtype) => { // Raise for disallowed arguments - restrict_allowed_arguments(&["set", "filter", "atMost"], query_field)?; + restrict_allowed_arguments(&[args::SET, args::FILTER, args::AT_MOST], query_field)?; let set: SetBuilder = read_argument_set(field, query_field, variables, variable_definitions)?; @@ -528,10 +529,10 @@ where match field_map.get(selection_field.name.as_ref()) { None => return Err(GraphQLError::validation("unknown field in update")), Some(f) => builder_fields.push(match f.name().as_ref() { - "affectedCount" => UpdateSelection::AffectedCount { + mutation::AFFECTED_COUNT => UpdateSelection::AffectedCount { alias: alias_or_name(&selection_field), }, - "records" => { + mutation::RECORDS => { let node_builder = to_node_builder( f, &selection_field, @@ -542,7 +543,7 @@ where ); UpdateSelection::Records(node_builder?) } - "__typename" => UpdateSelection::Typename { + introspection::TYPENAME => UpdateSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype .name() @@ -612,7 +613,7 @@ where match &type_ { __Type::DeleteResponse(xtype) => { // Raise for disallowed arguments - restrict_allowed_arguments(&["filter", "atMost"], query_field)?; + restrict_allowed_arguments(&[args::FILTER, args::AT_MOST], query_field)?; let filter: FilterBuilder = read_argument_filter(field, query_field, variables, variable_definitions)?; @@ -632,10 +633,10 @@ where match field_map.get(selection_field.name.as_ref()) { None => return Err(GraphQLError::validation("unknown field in delete")), Some(f) => builder_fields.push(match f.name().as_ref() { - "affectedCount" => DeleteSelection::AffectedCount { + mutation::AFFECTED_COUNT => DeleteSelection::AffectedCount { alias: alias_or_name(&selection_field), }, - "records" => { + mutation::RECORDS => { let node_builder = to_node_builder( f, &selection_field, @@ -646,7 +647,7 @@ where ); DeleteSelection::Records(node_builder?) } - "__typename" => DeleteSelection::Typename { + introspection::TYPENAME => DeleteSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype .name() @@ -1118,7 +1119,7 @@ where T: Text<'a> + Eq + AsRef, { let validated: gson::Value = read_argument( - "filter", + args::FILTER, field, query_field, variables, @@ -1126,7 +1127,7 @@ where )?; let filter_type = field - .get_arg("filter") + .get_arg(args::FILTER) .expect("failed to get filter argument") .type_() .unmodified_type(); @@ -1284,7 +1285,7 @@ where { // [{"id": "DescNullsLast"}] let validated: gson::Value = read_argument( - "orderBy", + args::ORDER_BY, field, query_field, variables, @@ -1293,7 +1294,7 @@ where // [
OrderBy!] let order_type: OrderByEntityType = match field - .get_arg("orderBy") + .get_arg(args::ORDER_BY) .expect("failed to get orderBy argument") .type_() .unmodified_type() @@ -1449,14 +1450,14 @@ where __Type::Connection(xtype) => { // Raise for disallowed arguments let mut allowed_args = vec![ - "first", "last", "before", "after", "offset", "filter", "orderBy", + pagination::FIRST, pagination::LAST, pagination::BEFORE, pagination::AFTER, pagination::OFFSET, args::FILTER, args::ORDER_BY, ]; allowed_args.extend(extra_allowed_args); restrict_allowed_arguments(&allowed_args, query_field)?; // TODO: only one of first/last, before/after provided let first: gson::Value = - read_argument("first", field, query_field, variables, variable_definitions)?; + read_argument(pagination::FIRST, field, query_field, variables, variable_definitions)?; let first: Option = match first { gson::Value::Absent | gson::Value::Null => None, gson::Value::Number(gson::Number::Integer(n)) if n < 0 => { @@ -1473,7 +1474,7 @@ where }; let last: gson::Value = - read_argument("last", field, query_field, variables, variable_definitions)?; + read_argument(pagination::LAST, field, query_field, variables, variable_definitions)?; let last: Option = match last { gson::Value::Absent | gson::Value::Null => None, gson::Value::Number(gson::Number::Integer(n)) if n < 0 => { @@ -1521,14 +1522,14 @@ where .unwrap_or(30); let before: Option = read_argument_cursor( - "before", + pagination::BEFORE, field, query_field, variables, variable_definitions, )?; let after: Option = - read_argument_cursor("after", field, query_field, variables, variable_definitions)?; + read_argument_cursor(pagination::AFTER, field, query_field, variables, variable_definitions)?; // Validate compatible input arguments if first.is_some() && last.is_some() { @@ -1602,7 +1603,7 @@ where )?) } __Type::Scalar(Scalar::Int) => { - if selection_field.name.as_ref() == "totalCount" { + if selection_field.name.as_ref() == connection::TOTAL_COUNT { ConnectionSelection::TotalCount { alias: alias_or_name(&selection_field), } @@ -1614,7 +1615,7 @@ where } } __Type::Scalar(Scalar::String(None)) => { - if selection_field.name.as_ref() == "__typename" { + if selection_field.name.as_ref() == introspection::TYPENAME { ConnectionSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype @@ -1700,10 +1701,10 @@ where ))?; let sub_alias = alias_or_name(&selection_field); - let col_selections = if field_name == "sum" - || field_name == "avg" - || field_name == "min" - || field_name == "max" + let col_selections = if field_name == aggregate::SUM + || field_name == aggregate::AVG + || field_name == aggregate::MIN + || field_name == aggregate::MAX { to_aggregate_column_builders( sub_field, @@ -1716,24 +1717,24 @@ where }; selections.push(match field_name { - "count" => AggregateSelection::Count { alias: sub_alias }, - "sum" => AggregateSelection::Sum { + aggregate::COUNT => AggregateSelection::Count { alias: sub_alias }, + aggregate::SUM => AggregateSelection::Sum { alias: sub_alias, column_builders: col_selections, }, - "avg" => AggregateSelection::Avg { + aggregate::AVG => AggregateSelection::Avg { alias: sub_alias, column_builders: col_selections, }, - "min" => AggregateSelection::Min { + aggregate::MIN => AggregateSelection::Min { alias: sub_alias, column_builders: col_selections, }, - "max" => AggregateSelection::Max { + aggregate::MAX => AggregateSelection::Max { alias: sub_alias, column_builders: col_selections, }, - "__typename" => AggregateSelection::Typename { + introspection::TYPENAME => AggregateSelection::Typename { alias: sub_alias, typename: field .type_() @@ -1844,19 +1845,19 @@ where match field_map.get(selection_field.name.as_ref()) { None => return Err(GraphQLError::validation("unknown field in pageInfo")), Some(f) => builder_fields.push(match f.name().as_ref() { - "startCursor" => PageInfoSelection::StartCursor { + page_info::START_CURSOR => PageInfoSelection::StartCursor { alias: alias_or_name(&selection_field), }, - "endCursor" => PageInfoSelection::EndCursor { + page_info::END_CURSOR => PageInfoSelection::EndCursor { alias: alias_or_name(&selection_field), }, - "hasPreviousPage" => PageInfoSelection::HasPreviousPage { + page_info::HAS_PREVIOUS_PAGE => PageInfoSelection::HasPreviousPage { alias: alias_or_name(&selection_field), }, - "hasNextPage" => PageInfoSelection::HasNextPage { + page_info::HAS_NEXT_PAGE => PageInfoSelection::HasNextPage { alias: alias_or_name(&selection_field), }, - "__typename" => PageInfoSelection::Typename { + introspection::TYPENAME => PageInfoSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype.name().expect("page info type should have a name"), }, @@ -1925,10 +1926,10 @@ where EdgeSelection::Node(node_builder) } _ => match f.name().as_ref() { - "cursor" => EdgeSelection::Cursor { + connection::CURSOR => EdgeSelection::Cursor { alias: alias_or_name(&selection_field), }, - "__typename" => EdgeSelection::Typename { + introspection::TYPENAME => EdgeSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype.name().expect("edge type should have a name"), }, @@ -1974,7 +1975,7 @@ where xtype.clone() } __Type::NodeInterface(node_interface) => { - restrict_allowed_arguments(&["nodeId"], query_field)?; + restrict_allowed_arguments(&[args::NODE_ID], query_field)?; // The nodeId argument is only valid on the entrypoint field for Node // relationships to "node" e.g. within edges, do not have any arguments let node_id: NodeIdInstance = @@ -2014,13 +2015,13 @@ where let field_map = field_map(&__Type::Node(xtype.clone())); let mut builder_fields = vec![]; - let mut allowed_args = vec!["nodeId"]; + let mut allowed_args = vec![args::NODE_ID]; allowed_args.extend(extra_allowed_args); restrict_allowed_arguments(&allowed_args, query_field)?; // The nodeId argument is only valid on the entrypoint field for Node // relationships to "node" e.g. within edges, do not have any arguments - let node_id: Option = match field.get_arg("nodeId").is_some() { + let node_id: Option = match field.get_arg(args::NODE_ID).is_some() { true => Some(read_argument_node_id( field, query_field, @@ -2105,7 +2106,7 @@ where } }, _ => match f.name().as_ref() { - "__typename" => NodeSelection::Typename { + introspection::TYPENAME => NodeSelection::Typename { alias: alias_or_name(&selection_field), typename: xtype.name().expect("node type should have a name"), }, @@ -2334,7 +2335,7 @@ impl __Schema { "description" => __EnumValueField::Description, "isDeprecated" => __EnumValueField::IsDeprecated, "deprecationReason" => __EnumValueField::DeprecationReason, - "__typename" => __EnumValueField::Typename { + introspection::TYPENAME => __EnumValueField::Typename { alias: alias_or_name(&selection_field), typename: enum_value.name(), }, @@ -2400,7 +2401,7 @@ impl __Schema { "defaultValue" => __InputValueField::DefaultValue, "isDeprecated" => __InputValueField::IsDeprecated, "deprecationReason" => __InputValueField::DeprecationReason, - "__typename" => __InputValueField::Typename { + introspection::TYPENAME => __InputValueField::Typename { alias: alias_or_name(&selection_field), typename: input_value.name(), }, @@ -2481,7 +2482,7 @@ impl __Schema { } "isDeprecated" => __FieldField::IsDeprecated, "deprecationReason" => __FieldField::DeprecationReason, - "__typename" => __FieldField::Typename { + introspection::TYPENAME => __FieldField::Typename { alias: alias_or_name(&selection_field), typename: field.name(), }, @@ -2525,7 +2526,7 @@ impl __Schema { } let name_arg_result: GraphQLResult = - read_argument("name", field, query_field, variables, variable_definitions); + read_argument(args::NAME, field, query_field, variables, variable_definitions); let name_arg: Option = match name_arg_result { // This builder (too) is overloaded and the arg is not present in all uses Err(_) => None, @@ -2612,7 +2613,7 @@ impl __Schema { let mut f_builders: Vec<__FieldBuilder> = vec![]; for vec_field in vec_fields { - if ["__type".to_string(), "__schema".to_string()] + if [introspection::TYPE.to_string(), introspection::SCHEMA.to_string()] .contains(&vec_field.name()) { continue; @@ -2743,7 +2744,7 @@ impl __Schema { }; __TypeField::OfType(unwrapped_type_builder) } - "__typename" => __TypeField::Typename { + introspection::TYPENAME => __TypeField::Typename { alias: alias_or_name(&selection_field), typename: type_.name(), }, @@ -2809,7 +2810,7 @@ impl __Schema { __DirectiveField::Args(builders) } "isRepeatable" => __DirectiveField::IsRepeatable, - "__typename" => __DirectiveField::Typename { + introspection::TYPENAME => __DirectiveField::Typename { alias: alias_or_name(&selection_field), typename: __Directive::TYPE.to_string(), }, @@ -2946,7 +2947,7 @@ impl __Schema { .collect::, _>>()?; __SchemaField::Directives(builders) } - "__typename" => __SchemaField::Typename { + introspection::TYPENAME => __SchemaField::Typename { alias: alias_or_name(&selection_field), typename: field.name(), }, diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 00000000..7e651cc3 --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,64 @@ +/// GraphQL field and argument name constants used throughout the codebase +/// +/// This module centralizes all magic strings to prevent typos and make refactoring easier. + +/// GraphQL introspection field names +pub mod introspection { + pub const TYPENAME: &str = "__typename"; + pub const TYPE: &str = "__type"; + pub const SCHEMA: &str = "__schema"; +} + +/// Connection-related field names +pub mod connection { + pub const EDGES: &str = "edges"; + pub const NODE: &str = "node"; + pub const PAGE_INFO: &str = "pageInfo"; + pub const TOTAL_COUNT: &str = "totalCount"; + pub const CURSOR: &str = "cursor"; +} + +/// Mutation result field names +pub mod mutation { + pub const RECORDS: &str = "records"; + pub const AFFECTED_COUNT: &str = "affectedCount"; +} + +/// Pagination argument names +pub mod pagination { + pub const FIRST: &str = "first"; + pub const LAST: &str = "last"; + pub const BEFORE: &str = "before"; + pub const AFTER: &str = "after"; + pub const OFFSET: &str = "offset"; +} + +/// Query argument names +pub mod args { + pub const FILTER: &str = "filter"; + pub const ORDER_BY: &str = "orderBy"; + pub const OBJECTS: &str = "objects"; + pub const SET: &str = "set"; + pub const AT_MOST: &str = "atMost"; + pub const AT: &str = "at"; + pub const DELETE_USING_NODE_ID: &str = "deleteUsingNodeId"; + pub const NODE_ID: &str = "nodeId"; + pub const NAME: &str = "name"; +} + +/// Aggregate function field names +pub mod aggregate { + pub const COUNT: &str = "count"; + pub const SUM: &str = "sum"; + pub const AVG: &str = "avg"; + pub const MIN: &str = "min"; + pub const MAX: &str = "max"; +} + +/// PageInfo field names +pub mod page_info { + pub const HAS_NEXT_PAGE: &str = "hasNextPage"; + pub const HAS_PREVIOUS_PAGE: &str = "hasPreviousPage"; + pub const START_CURSOR: &str = "startCursor"; + pub const END_CURSOR: &str = "endCursor"; +} diff --git a/src/graphql.rs b/src/graphql.rs index 06147774..236c3f41 100644 --- a/src/graphql.rs +++ b/src/graphql.rs @@ -1,3 +1,4 @@ +use crate::constants::{aggregate, args, connection, introspection, mutation, page_info, pagination}; use crate::sql_types::*; use cached::proc_macro::cached; use cached::SizedCache; @@ -547,9 +548,9 @@ pub fn field_map(type_: &__Type) -> HashMap { hmap.insert(field.name(), field); } hmap.insert( - "__typename".to_string(), + introspection::TYPENAME.to_string(), __Field { - name_: "__typename".to_string(), + name_: introspection::TYPENAME.to_string(), description: None, type_: __Type::Scalar(Scalar::String(None)), args: vec![], @@ -1028,21 +1029,21 @@ impl ConnectionType { fn get_connection_input_args(&self) -> Vec<__InputValue> { vec![ __InputValue { - name_: "first".to_string(), + name_: pagination::FIRST.to_string(), type_: __Type::Scalar(Scalar::Int), description: Some("Query the first `n` records in the collection".to_string()), default_value: None, sql_type: None, }, __InputValue { - name_: "last".to_string(), + name_: pagination::LAST.to_string(), type_: __Type::Scalar(Scalar::Int), description: Some("Query the last `n` records in the collection".to_string()), default_value: None, sql_type: None, }, __InputValue { - name_: "before".to_string(), + name_: pagination::BEFORE.to_string(), type_: __Type::Scalar(Scalar::Cursor), description: Some( "Query values in the collection before the provided cursor".to_string(), @@ -1051,7 +1052,7 @@ impl ConnectionType { sql_type: None, }, __InputValue { - name_: "after".to_string(), + name_: pagination::AFTER.to_string(), type_: __Type::Scalar(Scalar::Cursor), description: Some( "Query values in the collection after the provided cursor".to_string(), @@ -1060,7 +1061,7 @@ impl ConnectionType { sql_type: None, }, __InputValue { - name_: "offset".to_string(), + name_: pagination::OFFSET.to_string(), type_: __Type::Scalar(Scalar::Int), description: Some( "Skip n values from the after cursor. Alternative to cursor pagination. Backward pagination not supported.".to_string(), @@ -1069,7 +1070,7 @@ impl ConnectionType { sql_type: None, }, __InputValue { - name_: "filter".to_string(), + name_: args::FILTER.to_string(), type_: __Type::FilterEntity(FilterEntityType { table: Arc::clone(&self.table), schema: self.schema.clone(), @@ -1082,7 +1083,7 @@ impl ConnectionType { sql_type: None, }, __InputValue { - name_: "orderBy".to_string(), + name_: args::ORDER_BY.to_string(), type_: __Type::List(ListType { type_: Box::new(__Type::NonNull(NonNullType { type_: Box::new(__Type::OrderByEntity(OrderByEntityType { @@ -1197,12 +1198,12 @@ impl ___Type for QueryType { fn fields(&self, _include_deprecated: bool) -> Option> { let mut f = Vec::new(); let single_entrypoint = __Field { - name_: "node".to_string(), + name_: connection::NODE.to_string(), type_: __Type::NodeInterface(NodeInterfaceType { schema: Arc::clone(&self.schema), }), args: vec![__InputValue { - name_: "nodeId".to_string(), + name_: args::NODE_ID.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::ID)), }), @@ -1266,10 +1267,10 @@ impl ___Type for QueryType { // Default fields always preset f.extend(vec![ __Field { - name_: "__type".to_string(), + name_: introspection::TYPE.to_string(), type_: __Type::__Type(__TypeType), args: vec![__InputValue { - name_: "name".to_string(), + name_: args::NAME.to_string(), type_: __Type::Scalar(Scalar::String(None)), description: None, default_value: None, @@ -1280,7 +1281,7 @@ impl ___Type for QueryType { sql_type: None, }, __Field { - name_: "__schema".to_string(), + name_: introspection::SCHEMA.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::__Schema(__SchemaType)), }), @@ -1435,7 +1436,7 @@ impl ___Type for MutationType { schema: Arc::clone(&self.schema), }), args: vec![__InputValue { - name_: "objects".to_string(), + name_: args::OBJECTS.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::List(ListType { type_: Box::new(__Type::NonNull(NonNullType { @@ -1470,7 +1471,7 @@ impl ___Type for MutationType { }), args: vec![ __InputValue { - name_: "set".to_string(), + name_: args::SET.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::UpdateInput(UpdateInputType { table: Arc::clone(table), @@ -1482,7 +1483,7 @@ impl ___Type for MutationType { sql_type: None, }, __InputValue { - name_: "filter".to_string(), + name_: args::FILTER.to_string(), type_: __Type::FilterEntity(FilterEntityType { table: Arc::clone(table), schema: Arc::clone(&self.schema), @@ -1492,7 +1493,7 @@ impl ___Type for MutationType { sql_type: None, }, __InputValue { - name_: "atMost".to_string(), + name_: args::AT_MOST.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), @@ -1521,7 +1522,7 @@ impl ___Type for MutationType { }), args: vec![ __InputValue { - name_: "filter".to_string(), + name_: args::FILTER.to_string(), type_: __Type::FilterEntity(FilterEntityType { table: Arc::clone(table), schema: Arc::clone(&self.schema), @@ -1534,7 +1535,7 @@ impl ___Type for MutationType { sql_type: None, }, __InputValue { - name_: "atMost".to_string(), + name_: args::AT_MOST.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), @@ -1699,7 +1700,7 @@ impl ___Type for ConnectionType { }); let edge = __Field { - name_: "edges".to_string(), + name_: connection::EDGES.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::List(ListType { type_: Box::new(__Type::NonNull(NonNullType { @@ -1714,7 +1715,7 @@ impl ___Type for ConnectionType { }; let page_info = __Field { - name_: "pageInfo".to_string(), + name_: connection::PAGE_INFO.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::PageInfo(PageInfoType)), }), @@ -1730,7 +1731,7 @@ impl ___Type for ConnectionType { if let Some(total_count_directive) = self.table.directives.total_count.as_ref() { if total_count_directive.enabled { let total_count = __Field { - name_: "totalCount".to_string(), + name_: connection::TOTAL_COUNT.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), @@ -1830,7 +1831,7 @@ impl ___Type for EdgeType { fn fields(&self, _include_deprecated: bool) -> Option> { Some(vec![ __Field { - name_: "cursor".to_string(), + name_: connection::CURSOR.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::String(None))), }), @@ -1840,7 +1841,7 @@ impl ___Type for EdgeType { sql_type: None, }, __Field { - name_: "node".to_string(), + name_: connection::NODE.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Node(NodeType { table: Arc::clone(&self.table), @@ -2062,7 +2063,7 @@ impl ___Type for NodeType { if self.table.primary_key().is_some() { let node_id = __Field { - name_: "nodeId".to_string(), + name_: args::NODE_ID.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::ID)), }), @@ -2292,7 +2293,7 @@ impl ___Type for PageInfoType { fn fields(&self, _include_deprecated: bool) -> Option> { Some(vec![ __Field { - name_: "endCursor".to_string(), + name_: page_info::END_CURSOR.to_string(), type_: __Type::Scalar(Scalar::String(None)), args: vec![], description: None, @@ -2300,7 +2301,7 @@ impl ___Type for PageInfoType { sql_type: None, }, __Field { - name_: "hasNextPage".to_string(), + name_: page_info::HAS_NEXT_PAGE.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Boolean)), }), @@ -2310,7 +2311,7 @@ impl ___Type for PageInfoType { sql_type: None, }, __Field { - name_: "hasPreviousPage".to_string(), + name_: page_info::HAS_PREVIOUS_PAGE.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Boolean)), }), @@ -2320,7 +2321,7 @@ impl ___Type for PageInfoType { sql_type: None, }, __Field { - name_: "startCursor".to_string(), + name_: page_info::START_CURSOR.to_string(), type_: __Type::Scalar(Scalar::String(None)), args: vec![], description: None, @@ -2635,7 +2636,7 @@ impl ___Type for __InputValueType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::String(None))), }), - name_: "name".to_string(), + name_: args::NAME.to_string(), args: vec![], description: None, deprecation_reason: None, @@ -2711,7 +2712,7 @@ impl ___Type for __TypeType { vec![ __Field { type_: __Type::Scalar(Scalar::String(None)), - name_: "name".to_string(), + name_: args::NAME.to_string(), args: vec![], description: None, deprecation_reason: None, @@ -2859,7 +2860,7 @@ impl ___Type for __FieldType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::String(None))), }), - name_: "name".to_string(), + name_: args::NAME.to_string(), args: vec![], description: None, deprecation_reason: None, @@ -2949,7 +2950,7 @@ impl ___Type for __EnumValueType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::String(None))), }), - name_: "name".to_string(), + name_: args::NAME.to_string(), args: vec![], description: None, deprecation_reason: None, @@ -3009,7 +3010,7 @@ impl ___Type for __DirectiveType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::String(None))), }), - name_: "name".to_string(), + name_: args::NAME.to_string(), args: vec![], description: None, deprecation_reason: None, @@ -3164,7 +3165,7 @@ impl ___Type for InsertResponseType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), - name_: "affectedCount".to_string(), + name_: mutation::AFFECTED_COUNT.to_string(), args: vec![], description: Some("Count of the records impacted by the mutation".to_string()), deprecation_reason: None, @@ -3183,7 +3184,7 @@ impl ___Type for InsertResponseType { })), })), }), - name_: "records".to_string(), + name_: mutation::RECORDS.to_string(), args: vec![], description: Some("Array of records impacted by the mutation".to_string()), deprecation_reason: None, @@ -3251,7 +3252,7 @@ impl ___Type for UpdateResponseType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), - name_: "affectedCount".to_string(), + name_: mutation::AFFECTED_COUNT.to_string(), args: vec![], description: Some("Count of the records impacted by the mutation".to_string()), deprecation_reason: None, @@ -3270,7 +3271,7 @@ impl ___Type for UpdateResponseType { })), })), }), - name_: "records".to_string(), + name_: mutation::RECORDS.to_string(), args: vec![], description: Some("Array of records impacted by the mutation".to_string()), deprecation_reason: None, @@ -3298,7 +3299,7 @@ impl ___Type for DeleteResponseType { type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), - name_: "affectedCount".to_string(), + name_: mutation::AFFECTED_COUNT.to_string(), args: vec![], description: Some("Count of the records impacted by the mutation".to_string()), deprecation_reason: None, @@ -3317,7 +3318,7 @@ impl ___Type for DeleteResponseType { })), })), }), - name_: "records".to_string(), + name_: mutation::RECORDS.to_string(), args: vec![], description: Some("Array of records impacted by the mutation".to_string()), deprecation_reason: None, @@ -3804,7 +3805,7 @@ impl ___Type for FilterEntityType { .collect(); f.push(__InputValue { - name_: "nodeId".to_string(), + name_: args::NODE_ID.to_string(), type_: __Type::FilterType(FilterTypeType { entity: FilterableType::Scalar(Scalar::ID), schema: Arc::clone(&self.schema), @@ -4536,7 +4537,7 @@ impl ___Type for AggregateType { // Count field (always present) fields.push(__Field { - name_: "count".to_string(), + name_: aggregate::COUNT.to_string(), type_: __Type::NonNull(NonNullType { type_: Box::new(__Type::Scalar(Scalar::Int)), }), @@ -4560,7 +4561,7 @@ impl ___Type for AggregateType { if has_sum_avgable { fields.push(__Field { - name_: "sum".to_string(), + name_: aggregate::SUM.to_string(), type_: __Type::AggregateNumeric(AggregateNumericType { table: Arc::clone(&self.table), schema: Arc::clone(&self.schema), @@ -4572,7 +4573,7 @@ impl ___Type for AggregateType { sql_type: None, }); fields.push(__Field { - name_: "avg".to_string(), + name_: aggregate::AVG.to_string(), type_: __Type::AggregateNumeric(AggregateNumericType { table: Arc::clone(&self.table), schema: Arc::clone(&self.schema), @@ -4587,7 +4588,7 @@ impl ___Type for AggregateType { if has_min_maxable { fields.push(__Field { - name_: "min".to_string(), + name_: aggregate::MIN.to_string(), type_: __Type::AggregateNumeric(AggregateNumericType { table: Arc::clone(&self.table), schema: Arc::clone(&self.schema), @@ -4599,7 +4600,7 @@ impl ___Type for AggregateType { sql_type: None, }); fields.push(__Field { - name_: "max".to_string(), + name_: aggregate::MAX.to_string(), type_: __Type::AggregateNumeric(AggregateNumericType { table: Arc::clone(&self.table), schema: Arc::clone(&self.schema), diff --git a/src/lib.rs b/src/lib.rs index a70af9fe..88ba19d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use resolve::resolve_inner; use serde_json::json; mod builder; +mod constants; mod error; mod graphql; mod gson; diff --git a/src/resolve.rs b/src/resolve.rs index 07bfd995..8aa9efa9 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use std::hash::Hash; use crate::builder::*; +use crate::constants::introspection; use crate::error::{GraphQLError, GraphQLResult}; use crate::graphql::*; use crate::omit::*; @@ -294,7 +295,7 @@ where } } _ => match field_def.name().as_ref() { - "__typename" => { + introspection::TYPENAME => { res_data[alias_or_name(selection)] = serde_json::json!(query_type.name()) } @@ -492,7 +493,7 @@ where conn } _ => match field_def.name().as_ref() { - "__typename" => { + introspection::TYPENAME => { res_data[alias_or_name(selection)] = serde_json::json!(mutation_type.name()); conn diff --git a/src/transpile.rs b/src/transpile.rs index de590ba9..e8a0d3ec 100644 --- a/src/transpile.rs +++ b/src/transpile.rs @@ -1,4 +1,5 @@ use crate::builder::*; +use crate::constants::aggregate; use crate::error::{GraphQLError, GraphQLResult}; use crate::graphql::*; use crate::sql_types::{Column, ForeignKey, ForeignKeyTableInfo, Function, Table, TypeDetails}; @@ -959,10 +960,10 @@ impl ConnectionBuilder { column_builders: selections, } => { let pg_func = match selection { - AggregateSelection::Sum { .. } => "sum", - AggregateSelection::Avg { .. } => "avg", - AggregateSelection::Min { .. } => "min", - AggregateSelection::Max { .. } => "max", + AggregateSelection::Sum { .. } => aggregate::SUM, + AggregateSelection::Avg { .. } => aggregate::AVG, + AggregateSelection::Min { .. } => aggregate::MIN, + AggregateSelection::Max { .. } => aggregate::MAX, AggregateSelection::Count { .. } => { unreachable!("Count should be handled by its own arm") }