@@ -17,12 +17,13 @@ pub mod subscription_integration;
1717use crate :: RouterState ;
1818
1919use self :: {
20- subscription:: WorkflowsSubscription , workflow_templates:: WorkflowTemplatesQuery ,
21- workflows:: WorkflowsQuery ,
20+ subscription:: WorkflowsSubscription ,
21+ workflow_templates:: WorkflowTemplatesQuery ,
22+ workflows:: { Workflow , WorkflowsQuery } ,
2223} ;
2324use async_graphql:: {
24- parser:: parse_query, InputObject , MergedObject , MergedSubscription , Schema , SchemaBuilder ,
25- SimpleObject ,
25+ parser:: parse_query, Context , InputObject , MergedObject , MergedSubscription , Object , Schema ,
26+ SchemaBuilder , SimpleObject , Union , ID ,
2627} ;
2728use async_graphql_axum:: { GraphQLRequest , GraphQLResponse } ;
2829use axum:: extract:: State ;
@@ -50,12 +51,61 @@ pub fn root_schema_builder() -> SchemaBuilder<Query, Mutation, Subscription> {
5051
5152/// The root query of the service
5253#[ derive( Debug , Clone , Default , MergedObject ) ]
53- pub struct Query ( WorkflowsQuery , WorkflowTemplatesQuery ) ;
54+ pub struct Query ( NodeQuery , WorkflowsQuery , WorkflowTemplatesQuery ) ;
55+
56+ /// Provides Relay node resolver for fetching any Node by ID.
57+ #[ derive( Debug , Clone , Default ) ]
58+ pub struct NodeQuery ;
59+
60+ #[ Object ]
61+ impl NodeQuery {
62+ async fn node ( & self , ctx : & Context < ' _ > , id : ID ) -> Option < NodeValue > {
63+ let id_str = id. to_string ( ) ;
64+ let parts: Vec < & str > = id_str. split ( ':' ) . collect ( ) ;
65+ if parts. len ( ) != 2 {
66+ return None ;
67+ }
68+ let visit_display = parts[ 0 ] ;
69+ let workflow_name = parts[ 1 ] ;
70+
71+ let visit_input = match parse_visit_display ( visit_display) {
72+ Some ( v) => v,
73+ None => return None ,
74+ } ;
75+
76+ let workflows_query = WorkflowsQuery ;
77+ match workflows_query
78+ . workflow ( ctx, visit_input, workflow_name. to_string ( ) )
79+ . await
80+ {
81+ Ok ( workflow) => Some ( NodeValue :: Workflow ( workflow) ) ,
82+ Err ( _) => None ,
83+ }
84+ }
85+ }
86+
87+ /// Helper to parse VisitInput Display back into VisitInput
88+ fn parse_visit_display ( display : & str ) -> Option < VisitInput > {
89+ let re = regex:: Regex :: new ( r"^([A-Za-z]+)(\d+)-(\d+)$" ) . ok ( ) ?;
90+ let caps = re. captures ( display) ?;
91+ Some ( VisitInput {
92+ proposal_code : caps[ 1 ] . to_string ( ) ,
93+ proposal_number : caps[ 2 ] . parse ( ) . ok ( ) ?,
94+ number : caps[ 3 ] . parse ( ) . ok ( ) ?,
95+ } )
96+ }
5497
5598/// The root mutation of the service
5699#[ derive( Debug , Clone , Default , MergedObject ) ]
57100pub struct Mutation ( WorkflowTemplatesMutation ) ;
58101
102+ /// Represents Relay Node types
103+ #[ derive( Union ) ]
104+ enum NodeValue {
105+ /// A workflow node.
106+ Workflow ( Workflow ) ,
107+ }
108+
59109/// The root mutation of the service
60110#[ derive( Debug , Clone , Default , MergedSubscription ) ]
61111pub struct Subscription ( WorkflowsSubscription ) ;
@@ -131,13 +181,13 @@ impl Display for Visit {
131181
132182/// A visit to an instrument as part of a session
133183#[ derive( Debug , Clone , InputObject ) ]
134- struct VisitInput {
184+ pub struct VisitInput {
135185 /// Project Proposal Code
136- proposal_code : String ,
186+ pub proposal_code : String ,
137187 /// Project Proposal Number
138- proposal_number : u32 ,
188+ pub proposal_number : u32 ,
139189 /// Session visit Number
140- number : u32 ,
190+ pub number : u32 ,
141191}
142192
143193impl From < VisitInput > for Visit {
0 commit comments