1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
use crate::deprecation::DeprecationStrategy;
use crate::normalization::Normalization;
use proc_macro2::Ident;
use std::path::{Path, PathBuf};
use syn::{self, Visibility};

/// Which context is this code generation effort taking place.
#[derive(Debug)]
pub enum CodegenMode {
    /// The graphql-client CLI.
    Cli,
    /// The derive macro defined in graphql_query_derive.
    Derive,
}

/// Used to configure code generation.
pub struct GraphQLClientCodegenOptions {
    /// Which context is this code generation effort taking place.
    pub mode: CodegenMode,
    /// Name of the operation we want to generate code for. If it does not match, we use all queries.
    pub operation_name: Option<String>,
    /// The name of implementation target struct.
    pub struct_name: Option<String>,
    /// The struct for which we derive GraphQLQuery.
    struct_ident: Option<Ident>,
    /// Comma-separated list of additional traits we want to derive for variables.
    variables_derives: Option<String>,
    /// Comma-separated list of additional traits we want to derive for responses.
    response_derives: Option<String>,
    /// The deprecation strategy to adopt.
    deprecation_strategy: Option<DeprecationStrategy>,
    /// Target module visibility.
    module_visibility: Option<Visibility>,
    /// A path to a file to include in the module to force Cargo to take into account changes in
    /// the query files when recompiling.
    query_file: Option<PathBuf>,
    /// A path to a file to include in the module to force Cargo to take into account changes in
    /// the schema files when recompiling.
    schema_file: Option<PathBuf>,
    /// Normalization pattern for query types and names.
    normalization: Normalization,
    /// Custom scalar definitions module path
    custom_scalars_module: Option<syn::Path>,
    /// List of externally defined enum types. Type names must match those used in the schema exactly.
    extern_enums: Vec<String>,
    /// Flag to trigger generation of Other variant for fragments Enum
    fragments_other_variant: bool,
    /// Skip Serialization of None values.
    skip_serializing_none: bool,
}

impl GraphQLClientCodegenOptions {
    /// Creates an empty options object with default params. It probably wants to be configured.
    pub fn new(mode: CodegenMode) -> GraphQLClientCodegenOptions {
        GraphQLClientCodegenOptions {
            mode,
            variables_derives: Default::default(),
            response_derives: Default::default(),
            deprecation_strategy: Default::default(),
            module_visibility: Default::default(),
            operation_name: Default::default(),
            struct_ident: Default::default(),
            struct_name: Default::default(),
            query_file: Default::default(),
            schema_file: Default::default(),
            normalization: Normalization::None,
            custom_scalars_module: Default::default(),
            extern_enums: Default::default(),
            fragments_other_variant: Default::default(),
            skip_serializing_none: Default::default(),
        }
    }

    /// The visibility (public/private) to apply to the target module.
    pub(crate) fn module_visibility(&self) -> &Visibility {
        self.module_visibility
            .as_ref()
            .unwrap_or(&Visibility::Inherited)
    }

    /// The deprecation strategy to adopt.
    pub(crate) fn deprecation_strategy(&self) -> DeprecationStrategy {
        self.deprecation_strategy.clone().unwrap_or_default()
    }

    /// A path to a file to include in the module to force Cargo to take into account changes in
    /// the query files when recompiling.
    pub fn set_query_file(&mut self, path: PathBuf) {
        self.query_file = Some(path);
    }

    /// Comma-separated list of additional traits we want to derive for variables.
    pub fn variables_derives(&self) -> Option<&str> {
        self.variables_derives.as_deref()
    }

    /// Comma-separated list of additional traits we want to derive for variables.
    pub fn set_variables_derives(&mut self, variables_derives: String) {
        self.variables_derives = Some(variables_derives);
    }

    /// All the variable derives to be rendered.
    pub fn all_variable_derives(&self) -> impl Iterator<Item = &str> {
        let additional = self
            .variables_derives
            .as_deref()
            .into_iter()
            .flat_map(|s| s.split(','))
            .map(|s| s.trim());

        std::iter::once("Serialize").chain(additional)
    }

    /// Traits we want to derive for responses.
    pub fn all_response_derives(&self) -> impl Iterator<Item = &str> {
        let base_derives = std::iter::once("Deserialize");

        base_derives.chain(
            self.additional_response_derives()
                .filter(|additional| additional != &"Deserialize"),
        )
    }

    /// Additional traits we want to derive for responses.
    pub fn additional_response_derives(&self) -> impl Iterator<Item = &str> {
        self.response_derives
            .as_deref()
            .into_iter()
            .flat_map(|s| s.split(','))
            .map(|s| s.trim())
    }

    /// Comma-separated list of additional traits we want to derive for responses.
    pub fn set_response_derives(&mut self, response_derives: String) {
        self.response_derives = Some(response_derives);
    }

    /// The deprecation strategy to adopt.
    pub fn set_deprecation_strategy(&mut self, deprecation_strategy: DeprecationStrategy) {
        self.deprecation_strategy = Some(deprecation_strategy);
    }

    /// Target module visibility.
    pub fn set_module_visibility(&mut self, visibility: Visibility) {
        self.module_visibility = Some(visibility);
    }

    /// The name of implementation target struct.
    pub fn set_struct_name(&mut self, struct_name: String) {
        self.struct_name = Some(struct_name);
    }

    /// Name of the operation we want to generate code for. If none is selected, it means all
    /// operations.
    pub fn set_operation_name(&mut self, operation_name: String) {
        self.operation_name = Some(operation_name);
    }

    /// A path to a file to include in the module to force Cargo to take into account changes in
    /// the schema files when recompiling.
    pub fn schema_file(&self) -> Option<&Path> {
        self.schema_file.as_deref()
    }

    /// A path to a file to include in the module to force Cargo to take into account changes in
    /// the query files when recompiling.
    pub fn query_file(&self) -> Option<&Path> {
        self.query_file.as_deref()
    }

    /// The identifier to use when referring to the struct implementing GraphQLQuery, if any.
    pub fn set_struct_ident(&mut self, ident: Ident) {
        self.struct_ident = Some(ident);
    }

    /// The identifier to use when referring to the struct implementing GraphQLQuery, if any.
    pub fn struct_ident(&self) -> Option<&proc_macro2::Ident> {
        self.struct_ident.as_ref()
    }

    /// Set the normalization mode for the generated code.
    pub fn set_normalization(&mut self, norm: Normalization) {
        self.normalization = norm;
    }

    /// The normalization mode for the generated code.
    pub fn normalization(&self) -> &Normalization {
        &self.normalization
    }

    /// Get the custom scalar definitions module
    pub fn custom_scalars_module(&self) -> Option<&syn::Path> {
        self.custom_scalars_module.as_ref()
    }

    /// Set the custom scalar definitions module
    pub fn set_custom_scalars_module(&mut self, module: syn::Path) {
        self.custom_scalars_module = Some(module)
    }

    /// Get the externally defined enums type names
    pub fn extern_enums(&self) -> &[String] {
        &self.extern_enums
    }

    /// Set the externally defined enums type names
    pub fn set_extern_enums(&mut self, enums: Vec<String>) {
        self.extern_enums = enums;
    }

    /// Set the graphql client codegen options's fragments other variant.
    pub fn set_fragments_other_variant(&mut self, fragments_other_variant: bool) {
        self.fragments_other_variant = fragments_other_variant;
    }

    /// Get a reference to the graphql client codegen options's fragments other variant.
    pub fn fragments_other_variant(&self) -> &bool {
        &self.fragments_other_variant
    }

    /// Set the graphql client codegen option's skip none value.
    pub fn set_skip_serializing_none(&mut self, skip_serializing_none: bool) {
        self.skip_serializing_none = skip_serializing_none
    }

    /// Get a reference to the graphql client codegen option's skip none value.
    pub fn skip_serializing_none(&self) -> &bool {
        &self.skip_serializing_none
    }
}