libgraphql_core/operation/mutation_builder.rs
1use crate::ast;
2use crate::DirectiveAnnotation;
3use crate::schema::Schema;
4use crate::operation::FragmentRegistry;
5use crate::operation::Operation;
6use crate::operation::OperationBuilder;
7use crate::operation::OperationBuildError;
8use crate::operation::OperationBuilderTrait;
9use crate::operation::Mutation;
10use crate::operation::Selection;
11use crate::operation::Variable;
12use inherent::inherent;
13use std::path::Path;
14use thiserror::Error;
15
16type Result<T> = std::result::Result<T, MutationBuildError>;
17
18#[derive(Clone, Debug, PartialEq)]
19pub struct MutationBuilder<'schema: 'fragreg, 'fragreg>(
20 OperationBuilder<'schema, 'fragreg>,
21);
22
23#[inherent]
24impl<'schema: 'fragreg, 'fragreg> OperationBuilderTrait<
25 'schema,
26 'fragreg,
27 ast::operation::Mutation,
28 MutationBuildError,
29 Mutation<'schema, 'fragreg>,
30> for MutationBuilder<'schema, 'fragreg> {
31 /// Add a [`DirectiveAnnotation`] after any previously added
32 /// `DirectiveAnnotation`s.
33 pub fn add_directive(self, annot: DirectiveAnnotation) -> Result<Self> {
34 Ok(Self(self.0.add_directive(annot)?))
35 }
36
37 /// Add a [`Selection`] after any previously added `Selection`s.
38 pub fn add_selection(self, selection: Selection<'schema>) -> Result<Self> {
39 Ok(Self(self.0.add_selection(selection)?))
40 }
41
42 /// Add a [`Variable`] after any previously added `Variable`s.
43 pub fn add_variable(self, variable: Variable) -> Result<Self> {
44 Ok(Self(self.0.add_variable(variable)?))
45 }
46
47 /// Consume this [`MutationBuilder`] to produce a [`Mutation`].
48 pub fn build(self) -> Result<Mutation<'schema, 'fragreg>> {
49 let operation_kind = self.0.operation_kind.to_owned();
50 match self.0.build()? {
51 Operation::Mutation(query) => Ok(*query),
52 _ => panic!("Unexpected OperationKind: `{operation_kind:#?}`"),
53 }
54 }
55
56 /// Produce a [`Mutation`] from a
57 /// [`ast::operation::Mutation`](ast::operation::Mutation).
58 pub fn build_from_ast(
59 schema: &'schema Schema,
60 fragment_registry: &'fragreg FragmentRegistry<'schema>,
61 ast: &ast::operation::Mutation,
62 file_path: Option<&Path>,
63 ) -> Result<Mutation<'schema, 'fragreg>> {
64 Self::build_from_ast(schema, fragment_registry, ast, file_path)
65 }
66
67 /// Produce a [`Mutation`] from a file on disk that whose contents contain
68 /// an
69 /// [executable document](https://spec.graphql.org/October2021/#ExecutableDocument)
70 /// with only a single query defined in it.
71 ///
72 /// If multiple operations are defined in the document, an error will be
73 /// returned. For cases where multiple operations may be defined in a single
74 /// document, use
75 /// [`ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
76 ///
77 /// If the document contents include any fragment definitions, an error will
78 /// be returned. For cases where operations and fragments may be defined
79 /// together in a single document, use
80 /// ['ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
81 pub fn build_from_file(
82 schema: &'schema Schema,
83 fragment_registry: &'fragreg FragmentRegistry<'schema>,
84 file_path: impl AsRef<Path>,
85 ) -> Result<Mutation<'schema, 'fragreg>> {
86 Self::build_from_file(schema, fragment_registry, file_path)
87 }
88
89 /// Produce a [`Mutation`] from a string whose contents contain a
90 /// [document](https://spec.graphql.org/October2021/#sec-Document) with only
91 /// a single query defined in it.
92 ///
93 /// If multiple operations are defined in the document, an error will be
94 /// returned. For cases where multiple operations may be defined in a single
95 /// document, use
96 /// [`ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
97 ///
98 /// If the document contents include any fragment definitions, an error will
99 /// be returned. For cases where operations and fragments may be defined
100 /// together in a single document, use
101 /// ['ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
102 pub fn build_from_str(
103 schema: &'schema Schema,
104 fragment_registry: &'fragreg FragmentRegistry<'schema>,
105 file_path: Option<&Path>,
106 content: impl AsRef<str>,
107 ) -> Result<Mutation<'schema, 'fragreg>> {
108 Self::build_from_str(schema, fragment_registry, file_path, content)
109 }
110
111 /// Produce a [`MutationBuilder`] from a [`Mutation`](ast::operation::Mutation).
112 pub fn from_ast(
113 schema: &'schema Schema,
114 fragment_registry: &'fragreg FragmentRegistry<'schema>,
115 ast: &ast::operation::Mutation,
116 file_path: Option<&Path>,
117 ) -> Result<Self> {
118 Ok(Self(OperationBuilder::from_ast(
119 schema,
120 fragment_registry,
121 &ast::operation::OperationDefinition::Mutation(ast.to_owned()),
122 file_path
123 )?))
124 }
125
126 /// Produce a [`MutationBuilder`] from a file on disk that whose contents
127 /// contain an
128 /// [executable document](https://spec.graphql.org/October2021/#ExecutableDocument)
129 /// with only a single query defined in it.
130 ///
131 /// If multiple operations are defined in the document, an error will be
132 /// returned. For cases where multiple operations may be defined in a single
133 /// document, use
134 /// [`ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
135 ///
136 /// If the document contents include any fragment definitions, an error will
137 /// be returned. For cases where operations and fragments may be defined
138 /// together in a single document, use
139 /// ['ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
140 pub fn from_file(
141 schema: &'schema Schema,
142 fragment_registry: &'fragreg FragmentRegistry<'schema>,
143 file_path: impl AsRef<Path>,
144 ) -> Result<Self> {
145 Ok(Self(OperationBuilder::from_file(schema, fragment_registry, file_path)?))
146 }
147
148 /// Produce a [`MutationBuilder`] from a string whose contents contain a
149 /// [document](https://spec.graphql.org/October2021/#sec-Document) with only
150 /// a single query defined in it.
151 ///
152 /// If multiple operations are defined in the document, an error will be
153 /// returned. For cases where multiple operations may be defined in a single
154 /// document, use
155 /// [`ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
156 ///
157 /// If the document contents include any fragment definitions, an error will
158 /// be returned. For cases where operations and fragments may be defined
159 /// together in a single document, use
160 /// ['ExecutableDocumentBuilder`](crate::operation::ExecutableDocumentBuilder).
161 pub fn from_str(
162 schema: &'schema Schema,
163 fragment_registry: &'fragreg FragmentRegistry<'schema>,
164 content: impl AsRef<str>,
165 file_path: Option<&Path>,
166 ) -> Result<Self> {
167 Ok(Self(OperationBuilder::from_str(schema, fragment_registry, content, file_path)?))
168 }
169
170 pub fn new(
171 schema: &'schema Schema,
172 fragment_registry: &'fragreg FragmentRegistry<'schema>,
173 ) -> Self {
174 Self(OperationBuilder::new(schema, fragment_registry))
175 }
176
177 /// Set the list of [`DirectiveAnnotation`]s.
178 ///
179 /// NOTE: If any previous directives were added (either using this function
180 /// or [`MutationBuilder::add_directive()`]), they will be fully replaced by
181 /// the [`DirectiveAnnotation`]s passed here.
182 pub fn set_directives(
183 self,
184 directives: &[DirectiveAnnotation],
185 ) -> Result<Self> {
186 Ok(Self(self.0.set_directives(directives)?))
187 }
188
189 /// Set the name of the [`Mutation`].
190 pub fn set_name(self, name: Option<String>) -> Result<Self> {
191 Ok(Self(self.0.set_name(name)?))
192 }
193
194 /// Set the list of [`Variable`]s.
195 ///
196 /// NOTE: If any previous variables were added (either using this function
197 /// or [`MutationBuilder::add_variable()`]), they will be fully replaced by the
198 /// collection of variables passed here.
199 pub fn set_variables(self, variables: Vec<Variable>) -> Result<Self> {
200 Ok(Self(self.0.set_variables(variables)?))
201 }
202}
203
204#[derive(Clone, Debug, Error)]
205pub enum MutationBuildError {
206 #[error("Error building Mutation operation: $0")]
207 OperationBuildErrors(Vec<OperationBuildError>),
208}
209impl std::convert::From<Vec<OperationBuildError>> for MutationBuildError {
210 fn from(value: Vec<OperationBuildError>) -> Self {
211 Self::OperationBuildErrors(value)
212 }
213}