From 26da27b8e67b1075df3e5871a30ec004b934fb0d Mon Sep 17 00:00:00 2001 From: Heikel Date: Wed, 30 Oct 2024 15:37:54 +0100 Subject: [PATCH 01/12] fix: bug with graphql nested queries --- generated/.tailcallrc.graphql | 2 + generated/.tailcallrc.schema.json | 8 +++ src/core/blueprint/operators/graphql.rs | 32 +++++---- src/core/config/directives/graphql.rs | 8 +++ .../graphql-conformance-019.md_0.snap | 23 +++++++ .../graphql-conformance-019.md_client.snap | 29 +++++++++ .../graphql-conformance-019.md_merged.snap | 29 +++++++++ tests/execution/graphql-conformance-019.md | 65 +++++++++++++++++++ 8 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 tests/core/snapshots/graphql-conformance-019.md_0.snap create mode 100644 tests/core/snapshots/graphql-conformance-019.md_client.snap create mode 100644 tests/core/snapshots/graphql-conformance-019.md_merged.snap create mode 100644 tests/execution/graphql-conformance-019.md diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index 9dc5ed9dc1..e4c7a8dd49 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -79,6 +79,7 @@ directive @graphQL( as nonce-based APIs. """ dedupe: Boolean + depth: Int """ The headers parameter allows you to customize the headers of the GraphQL request made by the `@graphQL` operator. It is used by specifying a key-value map of header @@ -797,6 +798,7 @@ input GraphQL { as nonce-based APIs. """ dedupe: Boolean + depth: Int """ The headers parameter allows you to customize the headers of the GraphQL request made by the `@graphQL` operator. It is used by specifying a key-value map of header diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index e32e9b91f8..04d702216d 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -595,6 +595,14 @@ "null" ] }, + "depth": { + "type": [ + "integer", + "null" + ], + "format": "uint", + "minimum": 0.0 + }, "headers": { "description": "The headers parameter allows you to customize the headers of the GraphQL request made by the `@graphQL` operator. It is used by specifying a key-value map of header names and their values.", "type": "array", diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index d54547b714..067ed31ce6 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, VecDeque}; use crate::core::blueprint::FieldDefinition; use crate::core::config::{ @@ -13,17 +13,20 @@ use crate::core::valid::{Valid, ValidationError, Validator}; fn create_related_fields( config: &Config, - type_name: &str, - visited: &mut HashSet, + type_names: VecDeque, + visited: &mut HashSet>, ) -> RelatedFields { let mut map = HashMap::new(); - if visited.contains(type_name) { + if visited.contains(&type_names) { return RelatedFields(map); } - visited.insert(type_name.to_string()); - + visited.insert(type_names.clone()); + let type_name = type_names.back().unwrap(); if let Some(type_) = config.find_type(type_name) { for (name, field) in &type_.fields { + let mut new_type_names = type_names.clone(); + new_type_names.pop_front(); + new_type_names.push_back(field.type_of.name().to_string()); if !field.has_resolver() { if let Some(modify) = &field.modify { if let Some(modified_name) = &modify.name { @@ -31,7 +34,7 @@ fn create_related_fields( modified_name.clone(), ( name.clone(), - create_related_fields(config, field.type_of.name(), visited), + create_related_fields(config, new_type_names, visited), ), ); } @@ -40,15 +43,18 @@ fn create_related_fields( name.clone(), ( name.clone(), - create_related_fields(config, field.type_of.name(), visited), + create_related_fields(config, new_type_names, visited), ), ); } } } - } else if let Some(union_) = config.find_union(type_name) { + } else if let Some(union_) = config.find_union(type_names.back().unwrap()) { for type_name in &union_.types { - map.extend(create_related_fields(config, type_name, visited).0); + let mut new_type_names = type_names.clone(); + new_type_names.pop_front(); + new_type_names.push_back(type_name.to_string()); + map.extend(create_related_fields(config, new_type_names, visited).0); } }; @@ -72,7 +78,11 @@ pub fn compile_graphql( &graphql.name, args, headers, - create_related_fields(config, type_name, &mut HashSet::new()), + create_related_fields( + config, + VecDeque::from(vec![type_name.to_string(); graphql.depth.unwrap_or(5)]), + &mut HashSet::new(), + ), ) .map_err(|e| ValidationError::new(e.to_string())), ) diff --git a/src/core/config/directives/graphql.rs b/src/core/config/directives/graphql.rs index e366bbaaa2..6c9c73a79f 100644 --- a/src/core/config/directives/graphql.rs +++ b/src/core/config/directives/graphql.rs @@ -56,4 +56,12 @@ pub struct GraphQL { /// with APIs that expect unique results for identical inputs, such as /// nonce-based APIs. pub dedupe: Option, + /// Specifies the maximum depth for nested queries. + /// + /// When set, this value determines the depth of nested queries beyond which + /// no further subfields will be returned. This helps to limit the complexity + /// and size of the query results. If this value is not set, the default depth + /// is 5, ensuring that queries are manageable and preventing excessively + /// deep nesting. + pub depth: Option, } diff --git a/tests/core/snapshots/graphql-conformance-019.md_0.snap b/tests/core/snapshots/graphql-conformance-019.md_0.snap new file mode 100644 index 0000000000..0b3e1b3e22 --- /dev/null +++ b/tests/core/snapshots/graphql-conformance-019.md_0.snap @@ -0,0 +1,23 @@ +--- +source: tests/core/spec.rs +expression: response +--- +{ + "status": 200, + "headers": { + "content-type": "application/json" + }, + "body": { + "data": { + "queryNodeA": { + "name": "nodeA", + "nodeB": { + "name": "nodeB" + }, + "nodeC": { + "name": "nodeC" + } + } + } + } +} diff --git a/tests/core/snapshots/graphql-conformance-019.md_client.snap b/tests/core/snapshots/graphql-conformance-019.md_client.snap new file mode 100644 index 0000000000..8998a39c3c --- /dev/null +++ b/tests/core/snapshots/graphql-conformance-019.md_client.snap @@ -0,0 +1,29 @@ +--- +source: tests/core/spec.rs +expression: formatted +--- +type NodeA { + name: String + nodeB: NodeB + nodeC: NodeC +} + +type NodeB { + name: String + nodeA: NodeA + nodeC: NodeC +} + +type NodeC { + name: String + nodeA: NodeA + nodeB: NodeB +} + +type Query { + queryNodeA: NodeA +} + +schema { + query: Query +} diff --git a/tests/core/snapshots/graphql-conformance-019.md_merged.snap b/tests/core/snapshots/graphql-conformance-019.md_merged.snap new file mode 100644 index 0000000000..dec55dba71 --- /dev/null +++ b/tests/core/snapshots/graphql-conformance-019.md_merged.snap @@ -0,0 +1,29 @@ +--- +source: tests/core/spec.rs +expression: formatter +--- +schema @server(hostname: "0.0.0.0", port: 8000) @upstream { + query: Query +} + +type NodeA { + name: String + nodeB: NodeB + nodeC: NodeC +} + +type NodeB { + name: String + nodeA: NodeA + nodeC: NodeC +} + +type NodeC { + name: String + nodeA: NodeA + nodeB: NodeB +} + +type Query { + queryNodeA: NodeA @graphQL(url: "http://upstream/graphql", name: "nodeA", depth: 3) +} diff --git a/tests/execution/graphql-conformance-019.md b/tests/execution/graphql-conformance-019.md new file mode 100644 index 0000000000..ee92b992b9 --- /dev/null +++ b/tests/execution/graphql-conformance-019.md @@ -0,0 +1,65 @@ +# Complicated queries + +```graphql @config +schema @server(port: 8000, hostname: "0.0.0.0") { + query: Query +} + +type Query { + queryNodeA: NodeA @graphQL(url: "http://upstream/graphql", name: "nodeA", depth: 3) +} + +type NodeA { + name: String + nodeB: NodeB + nodeC: NodeC +} + +type NodeB { + name: String + nodeA: NodeA + nodeC: NodeC +} + +type NodeC { + name: String + nodeA: NodeA + nodeB: NodeB +} +``` + +```yml @mock +- request: + method: POST + url: http://upstream/graphql + textBody: '{ "query": "query { nodeA { name nodeB { name } nodeC { name } } }" }' + expectedHits: 1 + response: + status: 200 + body: + data: + nodeA: + name: nodeA + nodeB: + name: nodeB + nodeC: + name: nodeC +``` + +```yml @test +- method: POST + url: http://localhost:8080/graphql + body: + query: | + query queryNodeA { + queryNodeA { + name + nodeB { + name + } + nodeC { + name + } + } + } +``` From 8ec733aa7546b6429a22944d33554322227974cf Mon Sep 17 00:00:00 2001 From: Heikel Date: Wed, 30 Oct 2024 15:59:57 +0100 Subject: [PATCH 02/12] fix: linting --- generated/.tailcallrc.graphql | 14 ++++++++++++++ generated/.tailcallrc.schema.json | 1 + 2 files changed, 15 insertions(+) diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index e4c7a8dd49..e0391adb81 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -79,6 +79,13 @@ directive @graphQL( as nonce-based APIs. """ dedupe: Boolean + """ + Specifies the maximum depth for nested queries.When set, this value determines the + depth of nested queries beyond which no further subfields will be returned. This + helps to limit the complexity and size of the query results. If this value is not + set, the default depth is 5, ensuring that queries are manageable and preventing + excessively deep nesting. + """ depth: Int """ The headers parameter allows you to customize the headers of the GraphQL request @@ -798,6 +805,13 @@ input GraphQL { as nonce-based APIs. """ dedupe: Boolean + """ + Specifies the maximum depth for nested queries.When set, this value determines the + depth of nested queries beyond which no further subfields will be returned. This + helps to limit the complexity and size of the query results. If this value is not + set, the default depth is 5, ensuring that queries are manageable and preventing + excessively deep nesting. + """ depth: Int """ The headers parameter allows you to customize the headers of the GraphQL request diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index 04d702216d..b8a07edadf 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -596,6 +596,7 @@ ] }, "depth": { + "description": "Specifies the maximum depth for nested queries.\n\nWhen set, this value determines the depth of nested queries beyond which no further subfields will be returned. This helps to limit the complexity and size of the query results. If this value is not set, the default depth is 5, ensuring that queries are manageable and preventing excessively deep nesting.", "type": [ "integer", "null" From e766c228019257f93acce2ea8e3e1ce34b66d193 Mon Sep 17 00:00:00 2001 From: Heikel Date: Wed, 30 Oct 2024 16:10:14 +0100 Subject: [PATCH 03/12] fix: linting --- generated/.tailcallrc.graphql | 4 ++-- generated/.tailcallrc.schema.json | 2 +- src/core/config/directives/graphql.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index e0391adb81..5a67d2159c 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -80,7 +80,7 @@ directive @graphQL( """ dedupe: Boolean """ - Specifies the maximum depth for nested queries.When set, this value determines the + Specifies the maximum depth for nested queries. When set, this value determines the depth of nested queries beyond which no further subfields will be returned. This helps to limit the complexity and size of the query results. If this value is not set, the default depth is 5, ensuring that queries are manageable and preventing @@ -806,7 +806,7 @@ input GraphQL { """ dedupe: Boolean """ - Specifies the maximum depth for nested queries.When set, this value determines the + Specifies the maximum depth for nested queries. When set, this value determines the depth of nested queries beyond which no further subfields will be returned. This helps to limit the complexity and size of the query results. If this value is not set, the default depth is 5, ensuring that queries are manageable and preventing diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index b8a07edadf..7dc8cb215c 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -596,7 +596,7 @@ ] }, "depth": { - "description": "Specifies the maximum depth for nested queries.\n\nWhen set, this value determines the depth of nested queries beyond which no further subfields will be returned. This helps to limit the complexity and size of the query results. If this value is not set, the default depth is 5, ensuring that queries are manageable and preventing excessively deep nesting.", + "description": "Specifies the maximum depth for nested queries. When set, this value determines the depth of nested queries beyond which no further subfields will be returned. This helps to limit the complexity and size of the query results. If this value is not set, the default depth is 5, ensuring that queries are manageable and preventing excessively deep nesting.", "type": [ "integer", "null" diff --git a/src/core/config/directives/graphql.rs b/src/core/config/directives/graphql.rs index 6c9c73a79f..00900c45d5 100644 --- a/src/core/config/directives/graphql.rs +++ b/src/core/config/directives/graphql.rs @@ -56,8 +56,8 @@ pub struct GraphQL { /// with APIs that expect unique results for identical inputs, such as /// nonce-based APIs. pub dedupe: Option, + /// Specifies the maximum depth for nested queries. - /// /// When set, this value determines the depth of nested queries beyond which /// no further subfields will be returned. This helps to limit the complexity /// and size of the query results. If this value is not set, the default depth From 859a1797d0c7f82af118c3b205adc64d1d58697b Mon Sep 17 00:00:00 2001 From: Sandipsinh Rathod Date: Wed, 30 Oct 2024 11:11:09 -0400 Subject: [PATCH 04/12] avoid unwrapping in the logic --- src/core/blueprint/operators/graphql.rs | 50 ++++++++++++++----------- src/core/config/directives/graphql.rs | 8 ++-- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 067ed31ce6..1aa01b5c42 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -15,13 +15,13 @@ fn create_related_fields( config: &Config, type_names: VecDeque, visited: &mut HashSet>, -) -> RelatedFields { +) -> Option { let mut map = HashMap::new(); if visited.contains(&type_names) { - return RelatedFields(map); + return Some(RelatedFields(map)); } visited.insert(type_names.clone()); - let type_name = type_names.back().unwrap(); + let type_name = type_names.back()?; if let Some(type_) = config.find_type(type_name) { for (name, field) in &type_.fields { let mut new_type_names = type_names.clone(); @@ -34,7 +34,7 @@ fn create_related_fields( modified_name.clone(), ( name.clone(), - create_related_fields(config, new_type_names, visited), + create_related_fields(config, new_type_names, visited)?, ), ); } @@ -43,22 +43,22 @@ fn create_related_fields( name.clone(), ( name.clone(), - create_related_fields(config, new_type_names, visited), + create_related_fields(config, new_type_names, visited)?, ), ); } } } - } else if let Some(union_) = config.find_union(type_names.back().unwrap()) { + } else if let Some(union_) = config.find_union(type_names.back()?) { for type_name in &union_.types { let mut new_type_names = type_names.clone(); new_type_names.pop_front(); new_type_names.push_back(type_name.to_string()); - map.extend(create_related_fields(config, new_type_names, visited).0); + map.extend(create_related_fields(config, new_type_names, visited)?.0); } }; - RelatedFields(map) + Some(RelatedFields(map)) } pub fn compile_graphql( @@ -71,21 +71,27 @@ pub fn compile_graphql( Valid::succeed(graphql.url.as_str()) .zip(helpers::headers::to_mustache_headers(&graphql.headers)) .and_then(|(base_url, headers)| { - Valid::from( - RequestTemplate::new( - base_url.to_owned(), - operation_type, - &graphql.name, - args, - headers, - create_related_fields( - config, - VecDeque::from(vec![type_name.to_string(); graphql.depth.unwrap_or(5)]), - &mut HashSet::new(), - ), - ) - .map_err(|e| ValidationError::new(e.to_string())), + Valid::from_option( + create_related_fields( + config, + VecDeque::from(vec![type_name.to_string(); graphql.depth.unwrap_or(5)]), + &mut HashSet::new(), + ), + "Logical error occurred while creating Related Fields".to_string(), ) + .and_then(|related_fields| { + Valid::from( + RequestTemplate::new( + base_url.to_owned(), + operation_type, + &graphql.name, + args, + headers, + related_fields, + ) + .map_err(|e| ValidationError::new(e.to_string())), + ) + }) }) .map(|req_template| { let field_name = graphql.name.clone(); diff --git a/src/core/config/directives/graphql.rs b/src/core/config/directives/graphql.rs index 6c9c73a79f..d51dc8d421 100644 --- a/src/core/config/directives/graphql.rs +++ b/src/core/config/directives/graphql.rs @@ -59,9 +59,9 @@ pub struct GraphQL { /// Specifies the maximum depth for nested queries. /// /// When set, this value determines the depth of nested queries beyond which - /// no further subfields will be returned. This helps to limit the complexity - /// and size of the query results. If this value is not set, the default depth - /// is 5, ensuring that queries are manageable and preventing excessively - /// deep nesting. + /// no further subfields will be returned. This helps to limit the + /// complexity and size of the query results. If this value is not set, + /// the default depth is 5, ensuring that queries are manageable and + /// preventing excessively deep nesting. pub depth: Option, } From a8c89d82db24c445b2b73454f3a601a9aaffd004 Mon Sep 17 00:00:00 2001 From: Heikel Date: Fri, 1 Nov 2024 10:50:52 +0100 Subject: [PATCH 05/12] fix: query on nodes with the same type --- src/core/blueprint/operators/graphql.rs | 26 +++++++++++-------- src/core/ir/eval_context.rs | 8 ++++-- src/core/ir/mod.rs | 4 +-- .../graphql-conformance-019.md_0.snap | 4 +++ .../graphql-conformance-019.md_client.snap | 2 ++ .../graphql-conformance-019.md_merged.snap | 2 ++ tests/execution/graphql-conformance-019.md | 8 +++++- 7 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 1aa01b5c42..6cd8fff5e2 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -26,24 +26,28 @@ fn create_related_fields( for (name, field) in &type_.fields { let mut new_type_names = type_names.clone(); new_type_names.pop_front(); + let bool_self = field.type_of.name() == new_type_names.back()?; new_type_names.push_back(field.type_of.name().to_string()); if !field.has_resolver() { - if let Some(modify) = &field.modify { - if let Some(modified_name) = &modify.name { - map.insert( - modified_name.clone(), - ( - name.clone(), - create_related_fields(config, new_type_names, visited)?, - ), - ); - } + let used_name = match &field.modify { + Some(modify) => match &modify.name { + Some(modified_name) => Some(modified_name), + _ => None, + }, + _ => Some(name), + }; + if bool_self { + map.insert( + used_name?.to_string(), + (name.clone(), RelatedFields(HashMap::new()), true), + ); } else { map.insert( - name.clone(), + used_name?.to_string(), ( name.clone(), create_related_fields(config, new_type_names, visited)?, + false, ), ); } diff --git a/src/core/ir/eval_context.rs b/src/core/ir/eval_context.rs index c733882f85..4407b414df 100644 --- a/src/core/ir/eval_context.rs +++ b/src/core/ir/eval_context.rs @@ -130,8 +130,12 @@ fn format_selection_set<'a>( let set = selection_set .filter_map(|field| { // add to set only related fields that should be resolved with current resolver - related_fields.get(field.name()).map(|related_fields| { - format_selection_field(field, &related_fields.0, &related_fields.1) + related_fields.get(field.name()).map(|new_related_fields| { + if new_related_fields.2 { + format_selection_field(field, &new_related_fields.0, related_fields) + } else { + format_selection_field(field, &new_related_fields.0, &new_related_fields.1) + } }) }) .collect::>(); diff --git a/src/core/ir/mod.rs b/src/core/ir/mod.rs index 4540424848..60a3006065 100644 --- a/src/core/ir/mod.rs +++ b/src/core/ir/mod.rs @@ -21,10 +21,10 @@ pub use resolver_context_like::{ /// resolver i.e. fields that don't have their own resolver and are resolved by /// the ancestor #[derive(Debug, Default, Clone)] -pub struct RelatedFields(pub HashMap); +pub struct RelatedFields(pub HashMap); impl Deref for RelatedFields { - type Target = HashMap; + type Target = HashMap; fn deref(&self) -> &Self::Target { &self.0 diff --git a/tests/core/snapshots/graphql-conformance-019.md_0.snap b/tests/core/snapshots/graphql-conformance-019.md_0.snap index 0b3e1b3e22..8e83a92a48 100644 --- a/tests/core/snapshots/graphql-conformance-019.md_0.snap +++ b/tests/core/snapshots/graphql-conformance-019.md_0.snap @@ -1,6 +1,7 @@ --- source: tests/core/spec.rs expression: response +snapshot_kind: text --- { "status": 200, @@ -16,6 +17,9 @@ expression: response }, "nodeC": { "name": "nodeC" + }, + "child": { + "name": "nodeA" } } } diff --git a/tests/core/snapshots/graphql-conformance-019.md_client.snap b/tests/core/snapshots/graphql-conformance-019.md_client.snap index 8998a39c3c..eeb5a90041 100644 --- a/tests/core/snapshots/graphql-conformance-019.md_client.snap +++ b/tests/core/snapshots/graphql-conformance-019.md_client.snap @@ -1,8 +1,10 @@ --- source: tests/core/spec.rs expression: formatted +snapshot_kind: text --- type NodeA { + child: NodeA name: String nodeB: NodeB nodeC: NodeC diff --git a/tests/core/snapshots/graphql-conformance-019.md_merged.snap b/tests/core/snapshots/graphql-conformance-019.md_merged.snap index dec55dba71..e3cbb1674b 100644 --- a/tests/core/snapshots/graphql-conformance-019.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-019.md_merged.snap @@ -1,6 +1,7 @@ --- source: tests/core/spec.rs expression: formatter +snapshot_kind: text --- schema @server(hostname: "0.0.0.0", port: 8000) @upstream { query: Query @@ -8,6 +9,7 @@ schema @server(hostname: "0.0.0.0", port: 8000) @upstream { type NodeA { name: String + nodeA: NodeA @modify(name: "child") nodeB: NodeB nodeC: NodeC } diff --git a/tests/execution/graphql-conformance-019.md b/tests/execution/graphql-conformance-019.md index ee92b992b9..4ffaf83463 100644 --- a/tests/execution/graphql-conformance-019.md +++ b/tests/execution/graphql-conformance-019.md @@ -13,6 +13,7 @@ type NodeA { name: String nodeB: NodeB nodeC: NodeC + nodeA: NodeA @modify(name: "child") } type NodeB { @@ -32,7 +33,7 @@ type NodeC { - request: method: POST url: http://upstream/graphql - textBody: '{ "query": "query { nodeA { name nodeB { name } nodeC { name } } }" }' + textBody: '{ "query": "query { nodeA { name nodeB { name } nodeC { name } nodeA { name } } }" }' expectedHits: 1 response: status: 200 @@ -44,6 +45,8 @@ type NodeC { name: nodeB nodeC: name: nodeC + nodeA: + name: nodeA ``` ```yml @test @@ -60,6 +63,9 @@ type NodeC { nodeC { name } + child { + name + } } } ``` From c5514867000e26eba97aba5f0a6a940cee43927d Mon Sep 17 00:00:00 2001 From: Heikel Date: Tue, 5 Nov 2024 15:47:07 +0100 Subject: [PATCH 06/12] fix: remove the depth dependency --- generated/.tailcallrc.graphql | 18 +---- generated/.tailcallrc.schema.json | 11 +-- src/core/blueprint/operators/graphql.rs | 71 +++++++++++-------- src/core/config/directives/graphql.rs | 8 --- src/core/ir/eval_context.rs | 34 ++++++--- src/core/ir/mod.rs | 4 +- .../graphql-conformance-019.md_merged.snap | 2 +- tests/execution/graphql-conformance-019.md | 2 +- 8 files changed, 72 insertions(+), 78 deletions(-) diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index 5a67d2159c..9db2a5fec3 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -80,14 +80,6 @@ directive @graphQL( """ dedupe: Boolean """ - Specifies the maximum depth for nested queries. When set, this value determines the - depth of nested queries beyond which no further subfields will be returned. This - helps to limit the complexity and size of the query results. If this value is not - set, the default depth is 5, ensuring that queries are manageable and preventing - excessively deep nesting. - """ - depth: Int - """ The headers parameter allows you to customize the headers of the GraphQL request made by the `@graphQL` operator. It is used by specifying a key-value map of header names and their values. @@ -806,14 +798,6 @@ input GraphQL { """ dedupe: Boolean """ - Specifies the maximum depth for nested queries. When set, this value determines the - depth of nested queries beyond which no further subfields will be returned. This - helps to limit the complexity and size of the query results. If this value is not - set, the default depth is 5, ensuring that queries are manageable and preventing - excessively deep nesting. - """ - depth: Int - """ The headers parameter allows you to customize the headers of the GraphQL request made by the `@graphQL` operator. It is used by specifying a key-value map of header names and their values. @@ -1049,4 +1033,4 @@ Output format for prometheus data enum PrometheusFormat { text protobuf -} \ No newline at end of file +} diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index 7dc8cb215c..e3f09ec7a7 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -595,15 +595,6 @@ "null" ] }, - "depth": { - "description": "Specifies the maximum depth for nested queries. When set, this value determines the depth of nested queries beyond which no further subfields will be returned. This helps to limit the complexity and size of the query results. If this value is not set, the default depth is 5, ensuring that queries are manageable and preventing excessively deep nesting.", - "type": [ - "integer", - "null" - ], - "format": "uint", - "minimum": 0.0 - }, "headers": { "description": "The headers parameter allows you to customize the headers of the GraphQL request made by the `@graphQL` operator. It is used by specifying a key-value map of header names and their values.", "type": "array", @@ -1822,4 +1813,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 6cd8fff5e2..05e83348d0 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet, VecDeque}; +use std::collections::{HashMap, HashSet}; use crate::core::blueprint::FieldDefinition; use crate::core::config::{ @@ -13,21 +13,19 @@ use crate::core::valid::{Valid, ValidationError, Validator}; fn create_related_fields( config: &Config, - type_names: VecDeque, - visited: &mut HashSet>, + type_name: &str, + visited: &mut HashSet, + paths: &mut HashMap>, + path: Vec, + root: bool, ) -> Option { let mut map = HashMap::new(); - if visited.contains(&type_names) { + if visited.contains(type_name) { return Some(RelatedFields(map)); } - visited.insert(type_names.clone()); - let type_name = type_names.back()?; + visited.insert(type_name.to_string()); if let Some(type_) = config.find_type(type_name) { for (name, field) in &type_.fields { - let mut new_type_names = type_names.clone(); - new_type_names.pop_front(); - let bool_self = field.type_of.name() == new_type_names.back()?; - new_type_names.push_back(field.type_of.name().to_string()); if !field.has_resolver() { let used_name = match &field.modify { Some(modify) => match &modify.name { @@ -36,29 +34,39 @@ fn create_related_fields( }, _ => Some(name), }; - if bool_self { - map.insert( - used_name?.to_string(), - (name.clone(), RelatedFields(HashMap::new()), true), - ); - } else { - map.insert( - used_name?.to_string(), - ( - name.clone(), - create_related_fields(config, new_type_names, visited)?, + let mut next_path = path.clone(); + next_path.push(used_name?.to_string()); + if !(paths.contains_key(field.type_of.name())) { + paths.insert(field.type_of.name().to_string(), next_path.clone()); + }; + map.insert( + used_name?.to_string(), + ( + name.clone(), + create_related_fields( + config, + field.type_of.name(), + visited, + paths, + next_path.clone(), false, - ), - ); - } + )?, + paths.get(field.type_of.name())?.to_vec(), + root && (type_name == field.type_of.name()), + ), + ); } } - } else if let Some(union_) = config.find_union(type_names.back()?) { + } else if let Some(union_) = config.find_union(type_name) { for type_name in &union_.types { - let mut new_type_names = type_names.clone(); - new_type_names.pop_front(); - new_type_names.push_back(type_name.to_string()); - map.extend(create_related_fields(config, new_type_names, visited)?.0); + let mut next_path = path.clone(); + next_path.push(type_name.to_string()); + if !(paths.contains_key(type_name)) { + paths.insert(type_name.to_string(), next_path.clone()); + }; + map.extend( + create_related_fields(config, type_name, visited, paths, next_path, root)?.0, + ); } }; @@ -78,8 +86,11 @@ pub fn compile_graphql( Valid::from_option( create_related_fields( config, - VecDeque::from(vec![type_name.to_string(); graphql.depth.unwrap_or(5)]), + type_name, &mut HashSet::new(), + &mut HashMap::new(), + vec![], + true, ), "Logical error occurred while creating Related Fields".to_string(), ) diff --git a/src/core/config/directives/graphql.rs b/src/core/config/directives/graphql.rs index dde6e41ce0..e366bbaaa2 100644 --- a/src/core/config/directives/graphql.rs +++ b/src/core/config/directives/graphql.rs @@ -56,12 +56,4 @@ pub struct GraphQL { /// with APIs that expect unique results for identical inputs, such as /// nonce-based APIs. pub dedupe: Option, - - /// Specifies the maximum depth for nested queries. - /// When set, this value determines the depth of nested queries beyond which - /// no further subfields will be returned. This helps to limit the - /// complexity and size of the query results. If this value is not set, - /// the default depth is 5, ensuring that queries are manageable and - /// preventing excessively deep nesting. - pub depth: Option, } diff --git a/src/core/ir/eval_context.rs b/src/core/ir/eval_context.rs index 4407b414df..019eeb54e0 100644 --- a/src/core/ir/eval_context.rs +++ b/src/core/ir/eval_context.rs @@ -119,23 +119,37 @@ impl<'a, Ctx: ResolverContextLike> GraphQLOperationContext for EvalContext<'a, C fn selection_set(&self, related_fields: &RelatedFields) -> Option { let selection_field = self.graphql_ctx.field()?; - format_selection_set(selection_field.selection_set(), related_fields) + format_selection_set( + selection_field.selection_set(), + Some(related_fields), + related_fields, + ) } } fn format_selection_set<'a>( selection_set: impl Iterator, - related_fields: &RelatedFields, + related_fields: Option<&RelatedFields>, + global_related_fields: &RelatedFields, ) -> Option { let set = selection_set .filter_map(|field| { // add to set only related fields that should be resolved with current resolver - related_fields.get(field.name()).map(|new_related_fields| { - if new_related_fields.2 { - format_selection_field(field, &new_related_fields.0, related_fields) + related_fields?.get(field.name()).map(|new_related_fields| { + let next_related_fields = if new_related_fields.3 { + Some(global_related_fields) } else { - format_selection_field(field, &new_related_fields.0, &new_related_fields.1) - } + new_related_fields.2.iter().fold( + Some(global_related_fields), + |parent_related_fields, node| Some(&parent_related_fields?.get(node)?.1), + ) + }; + format_selection_field( + field, + &new_related_fields.0, + next_related_fields, + global_related_fields, + ) }) }) .collect::>(); @@ -150,10 +164,12 @@ fn format_selection_set<'a>( fn format_selection_field( field: &SelectionField, name: &str, - related_fields: &RelatedFields, + related_fields: Option<&RelatedFields>, + global_related_fields: &RelatedFields, ) -> String { let arguments = format_selection_field_arguments(field); - let selection_set = format_selection_set(field.selection_set(), related_fields); + let selection_set = + format_selection_set(field.selection_set(), related_fields, global_related_fields); let mut output = format!("{}{}", name, arguments); diff --git a/src/core/ir/mod.rs b/src/core/ir/mod.rs index 60a3006065..076d4c0187 100644 --- a/src/core/ir/mod.rs +++ b/src/core/ir/mod.rs @@ -21,10 +21,10 @@ pub use resolver_context_like::{ /// resolver i.e. fields that don't have their own resolver and are resolved by /// the ancestor #[derive(Debug, Default, Clone)] -pub struct RelatedFields(pub HashMap); +pub struct RelatedFields(pub HashMap, bool)>); impl Deref for RelatedFields { - type Target = HashMap; + type Target = HashMap, bool)>; fn deref(&self) -> &Self::Target { &self.0 diff --git a/tests/core/snapshots/graphql-conformance-019.md_merged.snap b/tests/core/snapshots/graphql-conformance-019.md_merged.snap index e3cbb1674b..bd3b791805 100644 --- a/tests/core/snapshots/graphql-conformance-019.md_merged.snap +++ b/tests/core/snapshots/graphql-conformance-019.md_merged.snap @@ -27,5 +27,5 @@ type NodeC { } type Query { - queryNodeA: NodeA @graphQL(url: "http://upstream/graphql", name: "nodeA", depth: 3) + queryNodeA: NodeA @graphQL(url: "http://upstream/graphql", name: "nodeA") } diff --git a/tests/execution/graphql-conformance-019.md b/tests/execution/graphql-conformance-019.md index 4ffaf83463..949ef7e02f 100644 --- a/tests/execution/graphql-conformance-019.md +++ b/tests/execution/graphql-conformance-019.md @@ -6,7 +6,7 @@ schema @server(port: 8000, hostname: "0.0.0.0") { } type Query { - queryNodeA: NodeA @graphQL(url: "http://upstream/graphql", name: "nodeA", depth: 3) + queryNodeA: NodeA @graphQL(url: "http://upstream/graphql", name: "nodeA") } type NodeA { From 92a9d2c36a9ecd277fbf56ef3635ee6d689ba5a5 Mon Sep 17 00:00:00 2001 From: Heikel Date: Tue, 5 Nov 2024 23:08:06 +0100 Subject: [PATCH 07/12] fix: ci --- src/core/blueprint/operators/graphql.rs | 1 + src/core/ir/eval_context.rs | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 05e83348d0..6873156628 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -11,6 +11,7 @@ use crate::core::ir::RelatedFields; use crate::core::try_fold::TryFold; use crate::core::valid::{Valid, ValidationError, Validator}; +#[allow(clippy::too_many_arguments)] fn create_related_fields( config: &Config, type_name: &str, diff --git a/src/core/ir/eval_context.rs b/src/core/ir/eval_context.rs index 019eeb54e0..967491908e 100644 --- a/src/core/ir/eval_context.rs +++ b/src/core/ir/eval_context.rs @@ -139,9 +139,15 @@ fn format_selection_set<'a>( let next_related_fields = if new_related_fields.3 { Some(global_related_fields) } else { - new_related_fields.2.iter().fold( - Some(global_related_fields), - |parent_related_fields, node| Some(&parent_related_fields?.get(node)?.1), + new_related_fields.2.iter().try_fold( + global_related_fields, + |parent_related_fields, node| { + parent_related_fields.get(node).map( + |(_nickname, next_related_fields, _path, _root)| { + next_related_fields + }, + ) + }, ) }; format_selection_field( From 2bd576ec3ce7e14c8bb0444751f560490835570a Mon Sep 17 00:00:00 2001 From: Heikel Date: Wed, 6 Nov 2024 09:10:07 +0100 Subject: [PATCH 08/12] fix: ci --- generated/.tailcallrc.graphql | 1 + generated/.tailcallrc.schema.json | 1 + 2 files changed, 2 insertions(+) diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index 9db2a5fec3..eaed6455f9 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -1034,3 +1034,4 @@ enum PrometheusFormat { text protobuf } + diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index e3f09ec7a7..2ef7d8e271 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -1814,3 +1814,4 @@ } } } + From 351c1f705094aadd6d99bcc17ae1fc9c904aa737 Mon Sep 17 00:00:00 2001 From: Heikel Date: Wed, 6 Nov 2024 09:11:25 +0100 Subject: [PATCH 09/12] fix: ci --- generated/.tailcallrc.graphql | 1 - generated/.tailcallrc.schema.json | 1 - 2 files changed, 2 deletions(-) diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index eaed6455f9..9db2a5fec3 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -1034,4 +1034,3 @@ enum PrometheusFormat { text protobuf } - diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index 2ef7d8e271..e3f09ec7a7 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -1814,4 +1814,3 @@ } } } - From b9f8cf0361c1564579fab8d39d876243f740dbba Mon Sep 17 00:00:00 2001 From: Heikel Date: Wed, 6 Nov 2024 09:24:30 +0100 Subject: [PATCH 10/12] fix: ci --- generated/.tailcallrc.graphql | 2 +- generated/.tailcallrc.schema.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/generated/.tailcallrc.graphql b/generated/.tailcallrc.graphql index 9db2a5fec3..9dc5ed9dc1 100644 --- a/generated/.tailcallrc.graphql +++ b/generated/.tailcallrc.graphql @@ -1033,4 +1033,4 @@ Output format for prometheus data enum PrometheusFormat { text protobuf -} +} \ No newline at end of file diff --git a/generated/.tailcallrc.schema.json b/generated/.tailcallrc.schema.json index e3f09ec7a7..e32e9b91f8 100644 --- a/generated/.tailcallrc.schema.json +++ b/generated/.tailcallrc.schema.json @@ -1813,4 +1813,4 @@ ] } } -} +} \ No newline at end of file From 2fa57cf305bd4cf4bd0d7f07a2320f80056fb1d9 Mon Sep 17 00:00:00 2001 From: Heikel Date: Tue, 12 Nov 2024 16:42:04 +0100 Subject: [PATCH 11/12] fix: return to root --- sdp.graphql | 807 ++++++++++++++++++++++++ src/core/blueprint/operators/graphql.rs | 8 +- 2 files changed, 811 insertions(+), 4 deletions(-) create mode 100644 sdp.graphql diff --git a/sdp.graphql b/sdp.graphql new file mode 100644 index 0000000000..55363a6f00 --- /dev/null +++ b/sdp.graphql @@ -0,0 +1,807 @@ +scalar UINT64 +schema @server(port: 8001, hostname: "0.0.0.0") @upstream(allowedHeaders: ["Authorization"]) { + query: Query +} +type Query { + getOffshoreWindFarm(filter: String!): [OffshoreWindFarm] + @graphQL( + name: "offshorewindfarm" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [{key: "filter", value: "{shortname: {eq: {{.args.filter}}}}"}] + ) + queryTagsByPlantIds(filter: [String]!): [Tag] + @graphQL( + name: "offshorewindfarm" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [{key: "filter", value: "{plantid: {is_in: {{.args.filter}}}}"}] + ) + + queryOffshoreWindFarm( + filter: OffshoreWindFarmFilterInput + pagination: PaginationInput + orderBy: OffshoreWindFarmOrderByInput + first: UINT64 + cascade: [String] + ): [OffshoreWindFarm] + @graphQL( + name: "offshorewindfarm" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryOffshoreWindTurbine( + filter: OffshoreWindTurbineFilterInput + pagination: PaginationInput + orderBy: OffshoreWindTurbineOrderByInput + cascade: [String] + ): [OffshoreWindTurbine] + @graphQL( + name: "offshorewindturbine" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryOffshoreSubstation( + filter: OffshoreSubstationFilterInput + pagination: PaginationInput + orderBy: OffshoreSubstationOrderByInput + cascade: [String] + ): [OffshoreSubstation] + @graphQL( + name: "offshoresubstation" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryOnshoreSubstation( + filter: OnshoreSubstationFilterInput + pagination: PaginationInput + orderBy: OnshoreSubstationOrderByInput + cascade: [String] + ): [OnshoreSubstation] + @graphQL( + name: "onshoresubstation" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryOnshoreSubstation( + filter: OnshoreSubstationFilterInput + pagination: PaginationInput + orderBy: OnshoreSubstationOrderByInput + cascade: [String] + ): [OnshoreSubstation] + @graphQL( + name: "onshoresubstation" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryTag(filter: TagFilterInput, pagination: PaginationInput, orderBy: TagOrderByInput, cascade: [String]): [Tag] + @graphQL( + name: "tag" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + queryGeoLocation( + filter: GeoLocationFilterInput + pagination: PaginationInput + orderBy: GeoLocationOrderByInput + cascade: [String] + ): [GeoLocation] + @graphQL( + name: "geolocation" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryCable( + filter: CableFilterInput + pagination: PaginationInput + orderBy: CableOrderByInput + cascade: [String] + ): [Cable] + @graphQL( + name: "cable" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryPoint( + filter: PointFilterInput + pagination: PaginationInput + orderBy: PointOrderByInput + cascade: [String] + ): [Point] + @graphQL( + name: "point" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + queryOnshoreWarehouse( + filter: OnshoreWarehouseFilterInput + pagination: PaginationInput + orderBy: OnshoreWarehouseOrderByInput + cascade: [String] + ): [OnshoreWarehouse] + @graphQL( + name: "onshorewarehouse" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + + queryPlantLocation( + filter: PlantLocationFilterInput + pagination: PaginationInput + orderBy: PlantLocationOrderByInput + cascade: [String] + ): [PlantLocation] + @graphQL( + name: "plantlocation" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) + queryPort(filter: PortFilterInput, pagination: PaginationInput, orderBy: PortOrderByInput, cascade: [String]): [Port] + @graphQL( + name: "port" + url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" + args: [ + {key: "filter", value: "{{.args.filter}}"} + {key: "pagination", value: "{{.args.pagination}}"} + {key: "orderBy", value: "{{.args.orderBy}}"} + {key: "cascade", value: "{{.args.cascade}}"} + ] + ) +} + +enum LocationType { + OFFSHOREWINDTURBINE + OFFSHORESUBSTATION + ONSHORESUBSTATION +} +enum AssetStates { + COMMISSIONING + CONSTRUCTION + OPERATION + PLANNING + UNKNOWN +} + +enum WattUnits { + GW + kVAr + kW + MVAr + MW + W +} + +enum CableType { + EXPORTCABLE + INTERARRAYCABLE + ONSHORECABLE +} + +enum VoltUnits { + kV + MV + mV +} + +input StringFilterInput { + eq: String + ne: String + gt: String + gte: String + lt: String + lte: String + in: [String!] @modify(name: "is_in") + is_not_in: [String!] + is_null: String + is_not_null: String + contains: String + starts_with: String + ends_with: String + like: String + not_like: String + between: [String!] + not_between: [String!] +} + +input AssetStatesEnumFilterInput { + eq: AssetStates + ne: AssetStates + gt: AssetStates + gte: AssetStates + lt: AssetStates + lte: AssetStates + is_in: [AssetStates!] + is_not_in: [AssetStates!] + is_null: AssetStates + is_not_null: AssetStates +} + +input FloatFilterInput { + eq: Float + ne: Float + gt: Float + gte: Float + lt: Float + lte: Float + is_in: [Float!] + is_not_in: [Float!] + is_null: Float + is_not_null: Float + between: [Float!] + not_between: [Float!] +} + +input IntFilterInput { + eq: Int + ne: Int + gt: Int + gte: Int + lt: Int + lte: Int + is_in: [Int!] + is_not_in: [Int!] + is_null: Int + is_not_null: Int + between: [Int!] + not_between: [Int!] +} + +input TextFilterInput { + eq: String + ne: String + gt: String + gte: String + lt: String + lte: String + is_in: [String!] + is_not_in: [String!] + is_null: String + is_not_null: String + between: [String!] + not_between: [String!] +} + +input CableTypeEnumFilterInput { + eq: CableType + ne: CableType + gt: CableType + gte: CableType + lt: CableType + lte: CableType + is_in: [CableType!] + is_not_in: [CableType!] + is_null: CableType + is_not_null: CableType +} + +input WattunitsEnumFilterInput { + eq: WattUnits + ne: WattUnits + gt: WattUnits + gte: WattUnits + lt: WattUnits + lte: WattUnits + is_in: [WattUnits!] + is_not_in: [WattUnits!] + is_null: WattUnits + is_not_null: WattUnits +} + +input PageInput { + page: Int! + limit: Int! +} + +input OffsetInput { + offset: Int! + limit: Int! +} + +input PaginationInput { + page: PageInput + offset: OffsetInput +} + +enum OrderByEnum { + ASC + DESC +} + +input OffshoreSubstationFilterInput { + name: StringFilterInput + shortname: StringFilterInput + saplocationid: StringFilterInput + and: [OffshoreSubstationFilterInput!] + or: [OffshoreSubstationFilterInput!] +} + +input OnshoreSubstationFilterInput { + name: StringFilterInput + shortname: StringFilterInput + saplocationid: StringFilterInput + and: [OnshoreSubstationFilterInput!] + or: [OnshoreSubstationFilterInput!] +} + +input OffshoreWindFarmFilterInput { + name: StringFilterInput + shortname: StringFilterInput + state: AssetStatesEnumFilterInput + commercialdatetimeoperation: TextFilterInput + ratedcapacity: FloatFilterInput + ratedcapacityunit: WattunitsEnumFilterInput + plantid: StringFilterInput + and: [OffshoreWindFarmFilterInput!] + or: [OffshoreWindFarmFilterInput!] +} + +input OffshoreWindTurbineFilterInput { + name: StringFilterInput + shortname: StringFilterInput + plannedcommissioneddate: TextFilterInput + actualcommissiondate: TextFilterInput + actualrnainstallationdate: TextFilterInput + saplocationid: StringFilterInput + stringposition: StringFilterInput + stringname: StringFilterInput + and: [OffshoreWindTurbineFilterInput!] + or: [OffshoreWindTurbineFilterInput!] +} + +input TagFilterInput { + name: StringFilterInput + id: StringFilterInput + description: StringFilterInput + category: IntFilterInput + categorydescription: StringFilterInput + system: StringFilterInput + subsystem: StringFilterInput + status: StringFilterInput + functionallocation: StringFilterInput + locationcode: StringFilterInput + plantid: StringFilterInput + and: [TagFilterInput!] + or: [TagFilterInput!] +} + +input CableFilterInput { + id: StringFilterInput + type: CableTypeEnumFilterInput + name: StringFilterInput + saplocationid: StringFilterInput + and: [CableFilterInput!] + or: [CableFilterInput!] +} + +input GeoLocationFilterInput { + id: StringFilterInput + name: StringFilterInput + and: [GeoLocationFilterInput!] + or: [GeoLocationFilterInput!] +} + +input PointFilterInput { + longitude: FloatFilterInput + latitude: FloatFilterInput +} + +input OnshoreWarehouseFilterInput { + name: StringFilterInput + shortname: StringFilterInput + and: [OnshoreWarehouseFilterInput!] + or: [OnshoreWarehouseFilterInput!] +} + +input PlantLocationFilterInput { + id: StringFilterInput + locationcode: StringFilterInput + shortname: StringFilterInput + prevlocationcode: StringFilterInput + areaclass: StringFilterInput + description: StringFilterInput + instcode: StringFilterInput + validflg: StringFilterInput + insertedby: StringFilterInput + insertddate: TextFilterInput + updatedby: StringFilterInput + updateddate: StringFilterInput + locationtype: StringFilterInput + locationtypedescription: StringFilterInput + and: [PlantLocationFilterInput!] + or: [PlantLocationFilterInput] +} + +input PortFilterInput { + id: StringFilterInput + name: StringFilterInput + shortname: StringFilterInput + and: [PortFilterInput!] + or: [PortFilterInput!] +} + +input OnshoreOfficeFilterInput { + name: StringFilterInput + shortname: StringFilterInput + saplocationid: StringFilterInput + and: [OnshoreOfficeFilterInput!] + or: [OnshoreOfficeFilterInput!] +} + +input OffshoreSubstationOrderByInput { + name: OrderByEnum + shortname: OrderByEnum + saplocationid: OrderByEnum +} + +input OnshoreSubstationOrderByInput { + name: OrderByEnum + shortname: OrderByEnum + saplocationid: OrderByEnum +} + +input OffshoreWindFarmOrderByInput { + name: OrderByEnum + shortname: OrderByEnum + state: OrderByEnum + commercialdatetimeoperation: OrderByEnum + ratedcapacity: OrderByEnum + ratedcapacityunit: OrderByEnum + plantid: OrderByEnum +} + +input OffshoreWindTurbineOrderByInput { + name: OrderByEnum + shortname: OrderByEnum + plannedcommissioneddate: OrderByEnum + actualcommissiondate: OrderByEnum + actualrnainstallationdate: OrderByEnum + saplocationid: OrderByEnum + stringposition: OrderByEnum + stringname: OrderByEnum +} + +input TagOrderByInput { + name: OrderByEnum + id: OrderByEnum + description: OrderByEnum + category: OrderByEnum + categorydescription: OrderByEnum + system: OrderByEnum + subsystem: OrderByEnum + status: OrderByEnum + functionallocation: OrderByEnum + locationcode: OrderByEnum + plantid: OrderByEnum +} + +input CableOrderByInput { + id: OrderByEnum + type: OrderByEnum + name: OrderByEnum + saplocationid: OrderByEnum +} + +input GeoLocationOrderByInput { + id: OrderByEnum + name: OrderByEnum +} + +input PointOrderByInput { + longitude: OrderByEnum + latitude: OrderByEnum +} + +input OnshoreWarehouseOrderByInput { + name: OrderByEnum + shortname: OrderByEnum +} + +input PlantLocationOrderByInput { + id: OrderByEnum + locationcode: OrderByEnum + shortname: OrderByEnum + prevlocationcode: OrderByEnum + areaclass: OrderByEnum + description: OrderByEnum + instcode: OrderByEnum + validflg: OrderByEnum + insertedby: OrderByEnum + insertddate: OrderByEnum + updatedby: OrderByEnum + updateddate: OrderByEnum + locationtype: OrderByEnum + locationtypedescription: OrderByEnum +} + +input PortOrderByInput { + id: OrderByEnum + name: OrderByEnum + shortname: OrderByEnum +} + +input OnshoreOfficeOrderByInput { + name: OrderByEnum + shortname: OrderByEnum + saplocationid: OrderByEnum +} + +type OffshoreWindFarm { + name: String! + shortname: String! @modify(name: "shortName") + state: AssetStates! + commercialdatetimeofoperation: DateTime @modify(name: "commercialDateTimeOfOperation") + ratedcapacity: Float @modify(name: "ratedCapacity") + ratedcapacityunit: WattUnits @modify(name: "ratedCapacityUnit") + plantid: String @modify(name: "plantId") + onshoresubstation( + filter: OnshoreSubstationFilterInput + orderBy: OnshoreSubstationOrderByInput + pagination: PaginationInput + ): [OnshoreSubstation!] @modify(name: "hasOnshoreSubstation") + offshoresubstation( + filter: OffshoreSubstationFilterInput + orderBy: OffshoreSubstationOrderByInput + pagination: PaginationInput + ): [OffshoreSubstation!] @modify(name: "hasOffshoreSubstation") + offshorewindturbine( + filter: OffshoreWindTurbineFilterInput + orderBy: OffshoreWindTurbineOrderByInput + pagination: PaginationInput + ): [OffshoreWindTurbine!] @modify(name: "hasOffshoreWindTurbine") + geolocation: GeoLocation @modify(name: "location") + onshorewarehouse: OnshoreWarehouse @modify(name: "usesWarehouse") + plantlocation( + filter: PlantLocationFilterInput + orderBy: PlantLocationOrderByInput + pagination: PaginationInput + ): [PlantLocation!] @modify(name: "hasPlantLocation") + port: Port @modify(name: "usesPort") + onshoreoffice( + filter: OnshoreOfficeFilterInput + orderBy: OnshoreOfficeOrderByInput + pagination: PaginationInput + ): [OnshoreOffice!] @modify(name: "hasOnshoreOffice") +} + +type OffshoreWindTurbine { + name: String! + shortname: String! @modify(name: "shortName") + plannedcommissioneddate: DateTime @modify(name: "plannedCommissionedDate") + actualcommissiondate: DateTime @modify(name: "actualCommissionDate") + actualrnainstallationdate: DateTime @modify(name: "actualRNAInstallationDate") + saplocationid: String @modify(name: "sapLocationId") + offshorewindfarm: OffshoreWindFarm @modify(name: "partOfOffshoreWindFarm") + stringposition: String @modify(name: "stringPosition") + stringname: String @modify(name: "stringName") + selfRef1: OffshoreWindTurbine @modify(name: "next") + selfRef2: OffshoreWindTurbine @modify(name: "previous") + tag(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] + offshoresubstation: OffshoreSubstation @modify(name: "connectedToOffshoreSubstation") + geolocation: GeoLocation @modify(name: "location") + cable(filter: CableFilterInput, orderBy: CableOrderByInput, pagination: PaginationInput): [Cable!] + @modify(name: "hasCable") + plantlocation( + filer: PlantLocationFilterInput + orderBy: PlantLocationOrderByInput + pagination: PaginationInput + ): [PlantLocation!] @modify(name: "plantLocation") +} + +type OffshoreSubstation { + name: String! + shortname: String! @modify(name: "shortName") + saplocationid: String @modify(name: "sapLocationId") + offshorewindfarm: OffshoreWindFarm @modify(name: "partOfOffshoreWindFarm") + offshorewindturbine( + filter: OffshoreWindTurbineFilterInput + orderBy: OffshoreWindTurbineOrderByInput + pagination: PaginationInput + ): [OffshoreWindTurbine!] @modify(name: "hasOffshoreWindTurbine") + tag(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] + geolocation: GeoLocation @modify(name: "location") + cable(filter: CableFilterInput, orderBy: CableOrderByInput, pagination: PaginationInput): [Cable!] + @modify(name: "connectedToCable") + plantlocation( + filter: PlantLocationFilterInput + orderBy: PlantLocationOrderByInput + pagination: PaginationInput + ): [PlantLocation!] @modify(name: "plantLocation") +} + +type OnshoreSubstation { + name: String! + shortname: String @modify(name: "shortName") + saplocationid: String @modify(name: "sapLocationId") + offshorewindfarm: OffshoreWindFarm @modify(name: "partOfOffshoreWindFarm") + tag(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] + geolocation: GeoLocation @modify(name: "location") + cable(filter: CableFilterInput, orderBy: CableOrderByInput, pagination: PaginationInput): [Cable!] + @modify(name: "connectedToCable") + plantlocation( + filter: PlantLocationFilterInput + orderBy: PlantLocationOrderByInput + pagination: PaginationInput + ): [PlantLocation!] @modify(name: "plantLocation") +} + +type Tag { + name: String! + id: String! + description: String + category: Int + categorydescription: String @modify(name: "categoryDescription") + system: String + subsystem: String @modify(name: "subSystem") + functionallocation: String @modify(name: "functionlLocation") + locationcode: String @modify(name: "locationCode") + plantid: String @modify(name: "plantId") + offshorewindturbine: [OffshoreWindTurbine!] @modify(name: "hasOffshoreWindTurbine") + offshoresubstation: [OffshoreSubstation!] @modify(name: "hasOffshoreSubstation") + onshoresubstation: [OnshoreSubstation!] @modify(name: "hasOnshoreSubstation") + selfRef: Tag @modify(name: "hasParentTag") + selfRefReverse(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] + @modify(name: "hasChildTags") +} + +type GeoLocation { + id: String! + name: String + polygon: Polygon @modify(name: "area") + point: Point +} + +type Point { + longitude: Float! + latitude: Float! +} + +type PointList { + point(filter: PointFilterInput, orderBy: PointOrderByInput, pagination: PaginationInput): [Point!] + @modify(name: "points") +} + +type Polygon { + pointlist: [PointList!] @modify(name: "coordinates") +} + +type OnshoreWarehouse { + name: String! + shortname: String! @modify(name: "shortName") + offshorewindfarm: OffshoreWindFarm @modify(name: "usedByOffshoreWindFarm") + geolocation: GeoLocation @modify(name: "location") +} + +type Cable { + id: String! + type: CableType! + name: String! + saplocationid: String @modify(name: "sapLocationId") + ratedvoltage: RatedVoltage @modify(name: "ratedVoltage") + offshorewindturbine( + filter: OffshoreWindTurbineFilterInput + orderBy: OffshoreWindTurbineOrderByInput + pagination: PaginationInput + ): [OffshoreWindTurbine!] @modify(name: "connectedToOffshoreWindTurbine") + offshoresubstation( + filter: OffshoreSubstationFilterInput + orderBy: OffshoreSubstationOrderByInput + pagination: PaginationInput + ): [OffshoreSubstation] @modify(name: "connectedToOffshoreSubstation") + onshoresubstation: OnshoreSubstation @modify(name: "connectedToOnshoreSubstation") + geolocation( + filter: GeoLocationFilterInput + orderBy: GeoLocationOrderByInput + pagination: PaginationInput + ): [GeoLocation!] @modify(name: "location") +} + +type RatedVoltage { + value: Float! + unit: VoltUnits! + cable(filter: CableFilterInput, order: CableOrderByInput, pagination: PaginationInput): [Cable!] +} + +type PlantLocation { + id: String! + locationcode: String! @modify(name: "locationCode") + shortname: String @modify(name: "shortName") + prevlocationcode: String @modify(name: "prevLocationCode") + areaclass: String @modify(name: "areaClass") + description: String + instcode: String @modify(name: "instCode") + offshorewindfarm: OffshoreWindFarm @modify(name: "usedByOffshoreWindFarm") + validflg: String @modify(name: "validFlg") + insertedby: String @modify(name: "insertedBy") + insertddate: String @modify(name: "insertedDate") + updatedby: String @modify(name: "updatedBy") + updateddate: String @modify(name: "updatedDate") + locationtype: LocationType @modify(name: "locationType") + locationtypedescription: String @modify(name: "locationTypeDescription") + offshorewindturbine: OffshoreWindTurbine @modify(name: "hasOffshoreWindTurbine") + offshoresubstation: OffshoreSubstation @modify(name: "hasOffshoreSubstation") + onshoresubstation: OnshoreSubstation @modify(name: "hasOnshoreSubstation") +} + +type Port { + id: String! + name: String! + shortname: String! @modify(name: "shortName") + offshorewindfarm( + filter: OffshoreWindFarmFilterInput + orderBy: OffshoreWindFarmOrderByInput + pagination: PaginationInput + ): [OffshoreWindFarm!] @modify(name: "usedByOffshoreWindFarm") + geolocation: GeoLocation @modify(name: "location") +} + +type OnshoreOffice { + name: String! + shortname: String! @modify(name: "shortName") + saplocationid: String @modify(name: "sapLocationId") + offshorewindfarm( + filter: OffshoreWindFarmFilterInput + orderBy: OffshoreWindFarmOrderByInput + pagination: PaginationInput + ): [OffshoreWindFarm!] @modify(name: "usedByOffshoreWindFarm") + geolocation: GeoLocation @modify(name: "location") +} diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index 95f16a9f6a..15349f3aa6 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -19,7 +19,7 @@ fn create_related_fields( visited: &mut HashSet, paths: &mut HashMap>, path: Vec, - root: bool, + root: &str, ) -> Option { let mut map = HashMap::new(); if visited.contains(type_name) { @@ -51,10 +51,10 @@ fn create_related_fields( visited, paths, next_path.clone(), - false, + root, )?, paths.get(field.type_of.name())?.to_vec(), - root && (type_name == field.type_of.name()), + root == field.type_of.name(), ), ); } @@ -92,7 +92,7 @@ pub fn compile_graphql( &mut HashSet::new(), &mut HashMap::new(), vec![], - true, + type_name, ), "Logical error occurred while creating Related Fields".to_string(), ) From 2a594d18c954c0c1775e25a2c4c6b276dfefe1f5 Mon Sep 17 00:00:00 2001 From: Heikel Date: Tue, 12 Nov 2024 16:42:41 +0100 Subject: [PATCH 12/12] fix: return to root --- sdp.graphql | 807 ---------------------------------------------------- 1 file changed, 807 deletions(-) delete mode 100644 sdp.graphql diff --git a/sdp.graphql b/sdp.graphql deleted file mode 100644 index 55363a6f00..0000000000 --- a/sdp.graphql +++ /dev/null @@ -1,807 +0,0 @@ -scalar UINT64 -schema @server(port: 8001, hostname: "0.0.0.0") @upstream(allowedHeaders: ["Authorization"]) { - query: Query -} -type Query { - getOffshoreWindFarm(filter: String!): [OffshoreWindFarm] - @graphQL( - name: "offshorewindfarm" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [{key: "filter", value: "{shortname: {eq: {{.args.filter}}}}"}] - ) - queryTagsByPlantIds(filter: [String]!): [Tag] - @graphQL( - name: "offshorewindfarm" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [{key: "filter", value: "{plantid: {is_in: {{.args.filter}}}}"}] - ) - - queryOffshoreWindFarm( - filter: OffshoreWindFarmFilterInput - pagination: PaginationInput - orderBy: OffshoreWindFarmOrderByInput - first: UINT64 - cascade: [String] - ): [OffshoreWindFarm] - @graphQL( - name: "offshorewindfarm" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryOffshoreWindTurbine( - filter: OffshoreWindTurbineFilterInput - pagination: PaginationInput - orderBy: OffshoreWindTurbineOrderByInput - cascade: [String] - ): [OffshoreWindTurbine] - @graphQL( - name: "offshorewindturbine" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryOffshoreSubstation( - filter: OffshoreSubstationFilterInput - pagination: PaginationInput - orderBy: OffshoreSubstationOrderByInput - cascade: [String] - ): [OffshoreSubstation] - @graphQL( - name: "offshoresubstation" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryOnshoreSubstation( - filter: OnshoreSubstationFilterInput - pagination: PaginationInput - orderBy: OnshoreSubstationOrderByInput - cascade: [String] - ): [OnshoreSubstation] - @graphQL( - name: "onshoresubstation" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryOnshoreSubstation( - filter: OnshoreSubstationFilterInput - pagination: PaginationInput - orderBy: OnshoreSubstationOrderByInput - cascade: [String] - ): [OnshoreSubstation] - @graphQL( - name: "onshoresubstation" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryTag(filter: TagFilterInput, pagination: PaginationInput, orderBy: TagOrderByInput, cascade: [String]): [Tag] - @graphQL( - name: "tag" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - queryGeoLocation( - filter: GeoLocationFilterInput - pagination: PaginationInput - orderBy: GeoLocationOrderByInput - cascade: [String] - ): [GeoLocation] - @graphQL( - name: "geolocation" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryCable( - filter: CableFilterInput - pagination: PaginationInput - orderBy: CableOrderByInput - cascade: [String] - ): [Cable] - @graphQL( - name: "cable" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryPoint( - filter: PointFilterInput - pagination: PaginationInput - orderBy: PointOrderByInput - cascade: [String] - ): [Point] - @graphQL( - name: "point" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - queryOnshoreWarehouse( - filter: OnshoreWarehouseFilterInput - pagination: PaginationInput - orderBy: OnshoreWarehouseOrderByInput - cascade: [String] - ): [OnshoreWarehouse] - @graphQL( - name: "onshorewarehouse" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - - queryPlantLocation( - filter: PlantLocationFilterInput - pagination: PaginationInput - orderBy: PlantLocationOrderByInput - cascade: [String] - ): [PlantLocation] - @graphQL( - name: "plantlocation" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) - queryPort(filter: PortFilterInput, pagination: PaginationInput, orderBy: PortOrderByInput, cascade: [String]): [Port] - @graphQL( - name: "port" - url: "https://greaterwashdev.dev.aurora.equinor.com/storm/sdpGraphql" - args: [ - {key: "filter", value: "{{.args.filter}}"} - {key: "pagination", value: "{{.args.pagination}}"} - {key: "orderBy", value: "{{.args.orderBy}}"} - {key: "cascade", value: "{{.args.cascade}}"} - ] - ) -} - -enum LocationType { - OFFSHOREWINDTURBINE - OFFSHORESUBSTATION - ONSHORESUBSTATION -} -enum AssetStates { - COMMISSIONING - CONSTRUCTION - OPERATION - PLANNING - UNKNOWN -} - -enum WattUnits { - GW - kVAr - kW - MVAr - MW - W -} - -enum CableType { - EXPORTCABLE - INTERARRAYCABLE - ONSHORECABLE -} - -enum VoltUnits { - kV - MV - mV -} - -input StringFilterInput { - eq: String - ne: String - gt: String - gte: String - lt: String - lte: String - in: [String!] @modify(name: "is_in") - is_not_in: [String!] - is_null: String - is_not_null: String - contains: String - starts_with: String - ends_with: String - like: String - not_like: String - between: [String!] - not_between: [String!] -} - -input AssetStatesEnumFilterInput { - eq: AssetStates - ne: AssetStates - gt: AssetStates - gte: AssetStates - lt: AssetStates - lte: AssetStates - is_in: [AssetStates!] - is_not_in: [AssetStates!] - is_null: AssetStates - is_not_null: AssetStates -} - -input FloatFilterInput { - eq: Float - ne: Float - gt: Float - gte: Float - lt: Float - lte: Float - is_in: [Float!] - is_not_in: [Float!] - is_null: Float - is_not_null: Float - between: [Float!] - not_between: [Float!] -} - -input IntFilterInput { - eq: Int - ne: Int - gt: Int - gte: Int - lt: Int - lte: Int - is_in: [Int!] - is_not_in: [Int!] - is_null: Int - is_not_null: Int - between: [Int!] - not_between: [Int!] -} - -input TextFilterInput { - eq: String - ne: String - gt: String - gte: String - lt: String - lte: String - is_in: [String!] - is_not_in: [String!] - is_null: String - is_not_null: String - between: [String!] - not_between: [String!] -} - -input CableTypeEnumFilterInput { - eq: CableType - ne: CableType - gt: CableType - gte: CableType - lt: CableType - lte: CableType - is_in: [CableType!] - is_not_in: [CableType!] - is_null: CableType - is_not_null: CableType -} - -input WattunitsEnumFilterInput { - eq: WattUnits - ne: WattUnits - gt: WattUnits - gte: WattUnits - lt: WattUnits - lte: WattUnits - is_in: [WattUnits!] - is_not_in: [WattUnits!] - is_null: WattUnits - is_not_null: WattUnits -} - -input PageInput { - page: Int! - limit: Int! -} - -input OffsetInput { - offset: Int! - limit: Int! -} - -input PaginationInput { - page: PageInput - offset: OffsetInput -} - -enum OrderByEnum { - ASC - DESC -} - -input OffshoreSubstationFilterInput { - name: StringFilterInput - shortname: StringFilterInput - saplocationid: StringFilterInput - and: [OffshoreSubstationFilterInput!] - or: [OffshoreSubstationFilterInput!] -} - -input OnshoreSubstationFilterInput { - name: StringFilterInput - shortname: StringFilterInput - saplocationid: StringFilterInput - and: [OnshoreSubstationFilterInput!] - or: [OnshoreSubstationFilterInput!] -} - -input OffshoreWindFarmFilterInput { - name: StringFilterInput - shortname: StringFilterInput - state: AssetStatesEnumFilterInput - commercialdatetimeoperation: TextFilterInput - ratedcapacity: FloatFilterInput - ratedcapacityunit: WattunitsEnumFilterInput - plantid: StringFilterInput - and: [OffshoreWindFarmFilterInput!] - or: [OffshoreWindFarmFilterInput!] -} - -input OffshoreWindTurbineFilterInput { - name: StringFilterInput - shortname: StringFilterInput - plannedcommissioneddate: TextFilterInput - actualcommissiondate: TextFilterInput - actualrnainstallationdate: TextFilterInput - saplocationid: StringFilterInput - stringposition: StringFilterInput - stringname: StringFilterInput - and: [OffshoreWindTurbineFilterInput!] - or: [OffshoreWindTurbineFilterInput!] -} - -input TagFilterInput { - name: StringFilterInput - id: StringFilterInput - description: StringFilterInput - category: IntFilterInput - categorydescription: StringFilterInput - system: StringFilterInput - subsystem: StringFilterInput - status: StringFilterInput - functionallocation: StringFilterInput - locationcode: StringFilterInput - plantid: StringFilterInput - and: [TagFilterInput!] - or: [TagFilterInput!] -} - -input CableFilterInput { - id: StringFilterInput - type: CableTypeEnumFilterInput - name: StringFilterInput - saplocationid: StringFilterInput - and: [CableFilterInput!] - or: [CableFilterInput!] -} - -input GeoLocationFilterInput { - id: StringFilterInput - name: StringFilterInput - and: [GeoLocationFilterInput!] - or: [GeoLocationFilterInput!] -} - -input PointFilterInput { - longitude: FloatFilterInput - latitude: FloatFilterInput -} - -input OnshoreWarehouseFilterInput { - name: StringFilterInput - shortname: StringFilterInput - and: [OnshoreWarehouseFilterInput!] - or: [OnshoreWarehouseFilterInput!] -} - -input PlantLocationFilterInput { - id: StringFilterInput - locationcode: StringFilterInput - shortname: StringFilterInput - prevlocationcode: StringFilterInput - areaclass: StringFilterInput - description: StringFilterInput - instcode: StringFilterInput - validflg: StringFilterInput - insertedby: StringFilterInput - insertddate: TextFilterInput - updatedby: StringFilterInput - updateddate: StringFilterInput - locationtype: StringFilterInput - locationtypedescription: StringFilterInput - and: [PlantLocationFilterInput!] - or: [PlantLocationFilterInput] -} - -input PortFilterInput { - id: StringFilterInput - name: StringFilterInput - shortname: StringFilterInput - and: [PortFilterInput!] - or: [PortFilterInput!] -} - -input OnshoreOfficeFilterInput { - name: StringFilterInput - shortname: StringFilterInput - saplocationid: StringFilterInput - and: [OnshoreOfficeFilterInput!] - or: [OnshoreOfficeFilterInput!] -} - -input OffshoreSubstationOrderByInput { - name: OrderByEnum - shortname: OrderByEnum - saplocationid: OrderByEnum -} - -input OnshoreSubstationOrderByInput { - name: OrderByEnum - shortname: OrderByEnum - saplocationid: OrderByEnum -} - -input OffshoreWindFarmOrderByInput { - name: OrderByEnum - shortname: OrderByEnum - state: OrderByEnum - commercialdatetimeoperation: OrderByEnum - ratedcapacity: OrderByEnum - ratedcapacityunit: OrderByEnum - plantid: OrderByEnum -} - -input OffshoreWindTurbineOrderByInput { - name: OrderByEnum - shortname: OrderByEnum - plannedcommissioneddate: OrderByEnum - actualcommissiondate: OrderByEnum - actualrnainstallationdate: OrderByEnum - saplocationid: OrderByEnum - stringposition: OrderByEnum - stringname: OrderByEnum -} - -input TagOrderByInput { - name: OrderByEnum - id: OrderByEnum - description: OrderByEnum - category: OrderByEnum - categorydescription: OrderByEnum - system: OrderByEnum - subsystem: OrderByEnum - status: OrderByEnum - functionallocation: OrderByEnum - locationcode: OrderByEnum - plantid: OrderByEnum -} - -input CableOrderByInput { - id: OrderByEnum - type: OrderByEnum - name: OrderByEnum - saplocationid: OrderByEnum -} - -input GeoLocationOrderByInput { - id: OrderByEnum - name: OrderByEnum -} - -input PointOrderByInput { - longitude: OrderByEnum - latitude: OrderByEnum -} - -input OnshoreWarehouseOrderByInput { - name: OrderByEnum - shortname: OrderByEnum -} - -input PlantLocationOrderByInput { - id: OrderByEnum - locationcode: OrderByEnum - shortname: OrderByEnum - prevlocationcode: OrderByEnum - areaclass: OrderByEnum - description: OrderByEnum - instcode: OrderByEnum - validflg: OrderByEnum - insertedby: OrderByEnum - insertddate: OrderByEnum - updatedby: OrderByEnum - updateddate: OrderByEnum - locationtype: OrderByEnum - locationtypedescription: OrderByEnum -} - -input PortOrderByInput { - id: OrderByEnum - name: OrderByEnum - shortname: OrderByEnum -} - -input OnshoreOfficeOrderByInput { - name: OrderByEnum - shortname: OrderByEnum - saplocationid: OrderByEnum -} - -type OffshoreWindFarm { - name: String! - shortname: String! @modify(name: "shortName") - state: AssetStates! - commercialdatetimeofoperation: DateTime @modify(name: "commercialDateTimeOfOperation") - ratedcapacity: Float @modify(name: "ratedCapacity") - ratedcapacityunit: WattUnits @modify(name: "ratedCapacityUnit") - plantid: String @modify(name: "plantId") - onshoresubstation( - filter: OnshoreSubstationFilterInput - orderBy: OnshoreSubstationOrderByInput - pagination: PaginationInput - ): [OnshoreSubstation!] @modify(name: "hasOnshoreSubstation") - offshoresubstation( - filter: OffshoreSubstationFilterInput - orderBy: OffshoreSubstationOrderByInput - pagination: PaginationInput - ): [OffshoreSubstation!] @modify(name: "hasOffshoreSubstation") - offshorewindturbine( - filter: OffshoreWindTurbineFilterInput - orderBy: OffshoreWindTurbineOrderByInput - pagination: PaginationInput - ): [OffshoreWindTurbine!] @modify(name: "hasOffshoreWindTurbine") - geolocation: GeoLocation @modify(name: "location") - onshorewarehouse: OnshoreWarehouse @modify(name: "usesWarehouse") - plantlocation( - filter: PlantLocationFilterInput - orderBy: PlantLocationOrderByInput - pagination: PaginationInput - ): [PlantLocation!] @modify(name: "hasPlantLocation") - port: Port @modify(name: "usesPort") - onshoreoffice( - filter: OnshoreOfficeFilterInput - orderBy: OnshoreOfficeOrderByInput - pagination: PaginationInput - ): [OnshoreOffice!] @modify(name: "hasOnshoreOffice") -} - -type OffshoreWindTurbine { - name: String! - shortname: String! @modify(name: "shortName") - plannedcommissioneddate: DateTime @modify(name: "plannedCommissionedDate") - actualcommissiondate: DateTime @modify(name: "actualCommissionDate") - actualrnainstallationdate: DateTime @modify(name: "actualRNAInstallationDate") - saplocationid: String @modify(name: "sapLocationId") - offshorewindfarm: OffshoreWindFarm @modify(name: "partOfOffshoreWindFarm") - stringposition: String @modify(name: "stringPosition") - stringname: String @modify(name: "stringName") - selfRef1: OffshoreWindTurbine @modify(name: "next") - selfRef2: OffshoreWindTurbine @modify(name: "previous") - tag(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] - offshoresubstation: OffshoreSubstation @modify(name: "connectedToOffshoreSubstation") - geolocation: GeoLocation @modify(name: "location") - cable(filter: CableFilterInput, orderBy: CableOrderByInput, pagination: PaginationInput): [Cable!] - @modify(name: "hasCable") - plantlocation( - filer: PlantLocationFilterInput - orderBy: PlantLocationOrderByInput - pagination: PaginationInput - ): [PlantLocation!] @modify(name: "plantLocation") -} - -type OffshoreSubstation { - name: String! - shortname: String! @modify(name: "shortName") - saplocationid: String @modify(name: "sapLocationId") - offshorewindfarm: OffshoreWindFarm @modify(name: "partOfOffshoreWindFarm") - offshorewindturbine( - filter: OffshoreWindTurbineFilterInput - orderBy: OffshoreWindTurbineOrderByInput - pagination: PaginationInput - ): [OffshoreWindTurbine!] @modify(name: "hasOffshoreWindTurbine") - tag(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] - geolocation: GeoLocation @modify(name: "location") - cable(filter: CableFilterInput, orderBy: CableOrderByInput, pagination: PaginationInput): [Cable!] - @modify(name: "connectedToCable") - plantlocation( - filter: PlantLocationFilterInput - orderBy: PlantLocationOrderByInput - pagination: PaginationInput - ): [PlantLocation!] @modify(name: "plantLocation") -} - -type OnshoreSubstation { - name: String! - shortname: String @modify(name: "shortName") - saplocationid: String @modify(name: "sapLocationId") - offshorewindfarm: OffshoreWindFarm @modify(name: "partOfOffshoreWindFarm") - tag(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] - geolocation: GeoLocation @modify(name: "location") - cable(filter: CableFilterInput, orderBy: CableOrderByInput, pagination: PaginationInput): [Cable!] - @modify(name: "connectedToCable") - plantlocation( - filter: PlantLocationFilterInput - orderBy: PlantLocationOrderByInput - pagination: PaginationInput - ): [PlantLocation!] @modify(name: "plantLocation") -} - -type Tag { - name: String! - id: String! - description: String - category: Int - categorydescription: String @modify(name: "categoryDescription") - system: String - subsystem: String @modify(name: "subSystem") - functionallocation: String @modify(name: "functionlLocation") - locationcode: String @modify(name: "locationCode") - plantid: String @modify(name: "plantId") - offshorewindturbine: [OffshoreWindTurbine!] @modify(name: "hasOffshoreWindTurbine") - offshoresubstation: [OffshoreSubstation!] @modify(name: "hasOffshoreSubstation") - onshoresubstation: [OnshoreSubstation!] @modify(name: "hasOnshoreSubstation") - selfRef: Tag @modify(name: "hasParentTag") - selfRefReverse(filter: TagFilterInput, orderBy: TagOrderByInput, pagination: PaginationInput): [Tag!] - @modify(name: "hasChildTags") -} - -type GeoLocation { - id: String! - name: String - polygon: Polygon @modify(name: "area") - point: Point -} - -type Point { - longitude: Float! - latitude: Float! -} - -type PointList { - point(filter: PointFilterInput, orderBy: PointOrderByInput, pagination: PaginationInput): [Point!] - @modify(name: "points") -} - -type Polygon { - pointlist: [PointList!] @modify(name: "coordinates") -} - -type OnshoreWarehouse { - name: String! - shortname: String! @modify(name: "shortName") - offshorewindfarm: OffshoreWindFarm @modify(name: "usedByOffshoreWindFarm") - geolocation: GeoLocation @modify(name: "location") -} - -type Cable { - id: String! - type: CableType! - name: String! - saplocationid: String @modify(name: "sapLocationId") - ratedvoltage: RatedVoltage @modify(name: "ratedVoltage") - offshorewindturbine( - filter: OffshoreWindTurbineFilterInput - orderBy: OffshoreWindTurbineOrderByInput - pagination: PaginationInput - ): [OffshoreWindTurbine!] @modify(name: "connectedToOffshoreWindTurbine") - offshoresubstation( - filter: OffshoreSubstationFilterInput - orderBy: OffshoreSubstationOrderByInput - pagination: PaginationInput - ): [OffshoreSubstation] @modify(name: "connectedToOffshoreSubstation") - onshoresubstation: OnshoreSubstation @modify(name: "connectedToOnshoreSubstation") - geolocation( - filter: GeoLocationFilterInput - orderBy: GeoLocationOrderByInput - pagination: PaginationInput - ): [GeoLocation!] @modify(name: "location") -} - -type RatedVoltage { - value: Float! - unit: VoltUnits! - cable(filter: CableFilterInput, order: CableOrderByInput, pagination: PaginationInput): [Cable!] -} - -type PlantLocation { - id: String! - locationcode: String! @modify(name: "locationCode") - shortname: String @modify(name: "shortName") - prevlocationcode: String @modify(name: "prevLocationCode") - areaclass: String @modify(name: "areaClass") - description: String - instcode: String @modify(name: "instCode") - offshorewindfarm: OffshoreWindFarm @modify(name: "usedByOffshoreWindFarm") - validflg: String @modify(name: "validFlg") - insertedby: String @modify(name: "insertedBy") - insertddate: String @modify(name: "insertedDate") - updatedby: String @modify(name: "updatedBy") - updateddate: String @modify(name: "updatedDate") - locationtype: LocationType @modify(name: "locationType") - locationtypedescription: String @modify(name: "locationTypeDescription") - offshorewindturbine: OffshoreWindTurbine @modify(name: "hasOffshoreWindTurbine") - offshoresubstation: OffshoreSubstation @modify(name: "hasOffshoreSubstation") - onshoresubstation: OnshoreSubstation @modify(name: "hasOnshoreSubstation") -} - -type Port { - id: String! - name: String! - shortname: String! @modify(name: "shortName") - offshorewindfarm( - filter: OffshoreWindFarmFilterInput - orderBy: OffshoreWindFarmOrderByInput - pagination: PaginationInput - ): [OffshoreWindFarm!] @modify(name: "usedByOffshoreWindFarm") - geolocation: GeoLocation @modify(name: "location") -} - -type OnshoreOffice { - name: String! - shortname: String! @modify(name: "shortName") - saplocationid: String @modify(name: "sapLocationId") - offshorewindfarm( - filter: OffshoreWindFarmFilterInput - orderBy: OffshoreWindFarmOrderByInput - pagination: PaginationInput - ): [OffshoreWindFarm!] @modify(name: "usedByOffshoreWindFarm") - geolocation: GeoLocation @modify(name: "location") -}