@@ -44,29 +44,24 @@ impl std::error::Error for GeneralError {}
4444
4545type BoxError = Box < dyn std:: error:: Error + Send + Sync + ' static > ;
4646type CacheMap < T > = std:: sync:: Mutex < BTreeMap < std:: path:: PathBuf , T > > ;
47+ type CachedQuery = ( String , graphql_parser:: query:: Document < ' static , String > ) ;
4748
4849lazy_static ! {
4950 static ref SCHEMA_CACHE : CacheMap <schema:: Schema > = CacheMap :: default ( ) ;
50- static ref QUERY_CACHE : CacheMap <( String , graphql_parser:: query:: Document <' static , String >) > =
51- CacheMap :: default ( ) ;
51+ static ref QUERY_CACHE : CacheMap <CachedQuery > = CacheMap :: default ( ) ;
5252}
5353
54- /// Generates Rust code given a query document, a schema and options.
55- pub fn generate_module_token_stream (
56- query_path : std:: path:: PathBuf ,
57- schema_path : & std:: path:: Path ,
58- options : GraphQLClientCodegenOptions ,
59- ) -> Result < TokenStream , BoxError > {
54+ fn get_schema ( schema_path : & std:: path:: Path ) -> Result < schema:: Schema , BoxError > {
6055 use std:: collections:: btree_map;
6156
6257 let schema_extension = schema_path
6358 . extension ( )
6459 . and_then ( std:: ffi:: OsStr :: to_str)
6560 . unwrap_or ( "INVALID" ) ;
66- let schema_string;
61+ let schema_string: String ;
6762
6863 // Check the schema cache.
69- let schema : schema:: Schema = {
64+ let cached_schema : schema:: Schema = {
7065 let mut lock = SCHEMA_CACHE . lock ( ) . expect ( "schema cache is poisoned" ) ;
7166 match lock. entry ( schema_path. to_path_buf ( ) ) {
7267 btree_map:: Entry :: Occupied ( o) => o. get ( ) . clone ( ) ,
@@ -89,37 +84,68 @@ pub fn generate_module_token_stream(
8984 }
9085 } ;
9186
92- // We need to qualify the query with the path to the crate it is part of
93- let ( query_string, query) = {
94- let mut lock = QUERY_CACHE . lock ( ) . expect ( "query cache is poisoned" ) ;
95- match lock. entry ( query_path) {
96- btree_map:: Entry :: Occupied ( o) => o. get ( ) . clone ( ) ,
97- btree_map:: Entry :: Vacant ( v) => {
98- let query_string = read_file ( v. key ( ) ) ?;
99- let query = graphql_parser:: parse_query ( & query_string)
100- . map_err ( |err| GeneralError ( format ! ( "Query parser error: {}" , err) ) ) ?
101- . into_static ( ) ;
102- v. insert ( ( query_string, query) ) . clone ( )
103- }
87+ Ok ( cached_schema)
88+ }
89+
90+ fn get_query ( query_path : std:: path:: PathBuf ) -> Result < CachedQuery , BoxError > {
91+ use std:: collections:: btree_map;
92+
93+ let mut lock = QUERY_CACHE . lock ( ) . expect ( "query cache is poisoned" ) ;
94+ let cached_query = match lock. entry ( query_path) {
95+ btree_map:: Entry :: Occupied ( o) => o. get ( ) . clone ( ) ,
96+ btree_map:: Entry :: Vacant ( v) => {
97+ let query_string = read_file ( v. key ( ) ) ?;
98+ let query_document = graphql_parser:: parse_query ( & query_string)
99+ . map_err ( |err| GeneralError ( format ! ( "Query parser error: {}" , err) ) ) ?
100+ . into_static ( ) ;
101+ v. insert ( ( query_string, query_document) ) . clone ( )
104102 }
105103 } ;
106104
107- let query = crate :: query:: resolve ( & schema, & query) ?;
105+ Ok ( cached_query)
106+ }
107+
108+ /// Generates Rust code given a path to a query file, a path to a schema file, and options.
109+ pub fn generate_module_token_stream (
110+ query_path : std:: path:: PathBuf ,
111+ schema_path : & std:: path:: Path ,
112+ options : GraphQLClientCodegenOptions ,
113+ ) -> Result < TokenStream , BoxError > {
114+ let ( query_string, _) = get_query ( query_path) ?;
115+
116+ generate_module_token_stream_from_string ( query_string, schema_path, options)
117+ }
118+
119+ /// Generates Rust code given a query string, a path to a schema file, and options.
120+ pub fn generate_module_token_stream_from_string (
121+ query_string : String ,
122+ schema_path : & std:: path:: Path ,
123+ options : GraphQLClientCodegenOptions ,
124+ ) -> Result < TokenStream , BoxError > {
125+ let schema = get_schema ( schema_path) ?;
126+ let query_document = graphql_parser:: parse_query ( & query_string)
127+ . map_err ( |err| GeneralError ( format ! ( "Query parser error: {}" , err) ) ) ?
128+ . into_static ( ) ;
129+
130+ // We need to qualify the query with the path to the crate it is part of
131+ let generated_query = crate :: query:: resolve ( & schema, & query_document) ?;
108132
109133 // Determine which operation we are generating code for. This will be used in operationName.
110134 let operations = options
111135 . operation_name
112136 . as_ref ( )
113- . and_then ( |operation_name| query. select_operation ( operation_name, * options. normalization ( ) ) )
137+ . and_then ( |operation_name| {
138+ generated_query. select_operation ( operation_name, * options. normalization ( ) )
139+ } )
114140 . map ( |op| vec ! [ op] ) ;
115141
116142 let operations = match ( operations, & options. mode ) {
117143 ( Some ( ops) , _) => ops,
118- ( None , & CodegenMode :: Cli ) => query . operations ( ) . collect ( ) ,
144+ ( None , & CodegenMode :: Cli ) => generated_query . operations ( ) . collect ( ) ,
119145 ( None , & CodegenMode :: Derive ) => {
120146 return Err ( GeneralError ( derive_operation_not_found_error (
121147 options. struct_ident ( ) ,
122- & query ,
148+ & generated_query ,
123149 ) )
124150 . into ( ) ) ;
125151 }
@@ -132,7 +158,7 @@ pub fn generate_module_token_stream(
132158 let generated = generated_module:: GeneratedModule {
133159 query_string : query_string. as_str ( ) ,
134160 schema : & schema,
135- resolved_query : & query ,
161+ resolved_query : & generated_query ,
136162 operation : & operation. 1 . name ,
137163 options : & options,
138164 }
0 commit comments