libgraphql_core/operation/
executable_document_builder.rs1use crate::ast;
2use crate::file_reader;
3use crate::operation::ExecutableDocument;
4use crate::operation::FragmentRegistry;
5use crate::operation::Operation;
6use crate::operation::OperationBuildError;
7use crate::operation::OperationBuilder;
8use crate::schema::Schema;
9use std::path::Path;
10use std::sync::Arc;
11use thiserror::Error;
12
13type Result<T> = std::result::Result<T, ExecutableDocumentBuildError>;
14
15pub struct ExecutableDocumentBuilder<'schema: 'fragreg, 'fragreg> {
16 fragment_registry: &'fragreg FragmentRegistry<'schema>,
17 operations: Vec<Operation<'schema, 'fragreg>>,
18 schema: &'schema Schema,
19}
20
21impl<'schema, 'fragreg> ExecutableDocumentBuilder<'schema, 'fragreg> {
22 pub fn build(self) -> Result<ExecutableDocument<'schema, 'fragreg>> {
23 Ok(ExecutableDocument {
24 fragment_registry: self.fragment_registry,
25 operations: self.operations,
26 schema: self.schema,
27 })
28 }
29
30 pub fn new(
31 schema: &'schema Schema,
32 fragment_registry: &'fragreg FragmentRegistry<'schema>,
33 ) -> Self {
34 Self {
35 fragment_registry,
36 operations: vec![],
37 schema,
38 }
39 }
40
41 pub fn from_ast(
42 schema: &'schema Schema,
43 fragment_registry: &'fragreg FragmentRegistry<'schema>,
44 ast: &ast::operation::Document,
45 file_path: Option<&Path>,
46 ) -> Result<Self> {
47 let mut operation_build_errors = vec![];
48 let mut operations = vec![];
49 for def in &ast.definitions {
50 use ast::operation::Definition as Def;
51 match def {
52 Def::Fragment(_frag_def) => {
53 },
55
56 Def::Operation(op_def) => {
57 let mut maybe_op = OperationBuilder::from_ast(
69 schema,
70 fragment_registry,
71 op_def,
72 file_path,
73 ).and_then(|op_builder| op_builder.build());
74
75 if let Err(errs) = &mut maybe_op {
76 operation_build_errors.append(errs);
77 continue;
78 }
79 operations.push(maybe_op.unwrap())
80 },
81 }
82 }
83
84 if !operation_build_errors.is_empty() {
85 return Err(ExecutableDocumentBuildError::OperationBuildErrors(
86 operation_build_errors,
87 ));
88 }
89
90 Ok(Self {
91 fragment_registry,
92 schema,
93 operations,
94 })
95 }
96
97 pub fn from_file(
98 schema: &'schema Schema,
99 fragment_registry: &'fragreg FragmentRegistry<'schema>,
100 file_path: impl AsRef<Path>,
101 ) -> Result<Self> {
102 let file_path = file_path.as_ref();
103 let file_content = file_reader::read_content(file_path)
104 .map_err(|e| ExecutableDocumentBuildError::ExecutableDocumentFileReadError(
105 Box::new(e),
106 ))?;
107 Self::from_str(schema, fragment_registry, file_content, Some(file_path))
108 }
109
110 pub fn from_str(
111 schema: &'schema Schema,
112 fragment_registry: &'fragreg FragmentRegistry<'schema>,
113 content: impl AsRef<str>,
114 file_path: Option<&Path>,
115 ) -> Result<Self> {
116 let ast_doc = ast::operation::parse(content.as_ref())?;
117 Self::from_ast(schema, fragment_registry, &ast_doc, file_path)
118 }
119}
120
121#[derive(Clone, Debug, Error)]
122pub enum ExecutableDocumentBuildError {
123 #[error(
124 "Failure while trying to read an executable document file from disk: $0"
125 )]
126 ExecutableDocumentFileReadError(Box<file_reader::ReadContentError>),
127
128 #[error(
129 "Encountered errors while building operations within this \
130 executable document: {0:?}",
131 )]
132 OperationBuildErrors(Vec<OperationBuildError>),
133
134 #[error("Error parsing executable document: $0")]
135 ParseError(Arc<ast::operation::ParseError>),
136}
137impl std::convert::From<ast::operation::ParseError> for ExecutableDocumentBuildError {
138 fn from(value: ast::operation::ParseError) -> Self {
139 Self::ParseError(Arc::new(value))
140 }
141}