faucet_source_graphql/
config.rs1use reqwest::header::HeaderMap;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
10#[serde(tag = "type")]
11pub enum GraphqlAuth {
12 None,
14 Bearer(String),
16 #[serde(skip)]
18 Custom(HeaderMap),
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26pub struct GraphqlPagination {
27 pub has_next_page_path: String,
29 pub cursor_path: String,
31 pub cursor_variable: String,
33 pub page_size: Option<usize>,
35 pub page_size_variable: String,
37}
38
39impl Default for GraphqlPagination {
40 fn default() -> Self {
41 Self {
42 has_next_page_path: "$.data.*.pageInfo.hasNextPage".into(),
43 cursor_path: "$.data.*.pageInfo.endCursor".into(),
44 cursor_variable: "after".into(),
45 page_size: None,
46 page_size_variable: "first".into(),
47 }
48 }
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
53pub struct GraphqlStreamConfig {
54 pub endpoint: String,
56 pub query: String,
58 pub variables: Value,
60 pub auth: GraphqlAuth,
62 #[serde(skip, default)]
64 pub headers: HeaderMap,
65 pub records_path: Option<String>,
67 pub pagination: Option<GraphqlPagination>,
69 pub max_pages: Option<usize>,
71}
72
73impl GraphqlStreamConfig {
74 pub fn new(endpoint: impl Into<String>, query: impl Into<String>) -> Self {
76 Self {
77 endpoint: endpoint.into(),
78 query: query.into(),
79 variables: Value::Object(Default::default()),
80 auth: GraphqlAuth::None,
81 headers: HeaderMap::new(),
82 records_path: None,
83 pagination: None,
84 max_pages: None,
85 }
86 }
87
88 pub fn variables(mut self, vars: Value) -> Self {
90 self.variables = vars;
91 self
92 }
93
94 pub fn auth(mut self, auth: GraphqlAuth) -> Self {
96 self.auth = auth;
97 self
98 }
99
100 pub fn headers(mut self, headers: HeaderMap) -> Self {
102 self.headers = headers;
103 self
104 }
105
106 pub fn records_path(mut self, path: impl Into<String>) -> Self {
108 self.records_path = Some(path.into());
109 self
110 }
111
112 pub fn pagination(mut self, pagination: GraphqlPagination) -> Self {
114 self.pagination = Some(pagination);
115 self
116 }
117
118 pub fn max_pages(mut self, max: usize) -> Self {
120 self.max_pages = Some(max);
121 self
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use serde_json::json;
129
130 #[test]
131 fn default_config() {
132 let config = GraphqlStreamConfig::new(
133 "https://api.example.com/graphql",
134 "query { users { id name } }",
135 );
136 assert_eq!(config.endpoint, "https://api.example.com/graphql");
137 assert!(config.records_path.is_none());
138 assert!(config.pagination.is_none());
139 assert!(config.max_pages.is_none());
140 }
141
142 #[test]
143 fn builder_methods() {
144 let config =
145 GraphqlStreamConfig::new("https://api.example.com/graphql", "query { users { id } }")
146 .variables(json!({"org": "acme"}))
147 .records_path("$.data.users.edges[*].node")
148 .max_pages(10)
149 .auth(GraphqlAuth::Bearer("token".into()));
150 assert_eq!(config.variables["org"], "acme");
151 assert_eq!(config.records_path.unwrap(), "$.data.users.edges[*].node");
152 assert_eq!(config.max_pages, Some(10));
153 }
154
155 #[test]
156 fn default_pagination() {
157 let pag = GraphqlPagination::default();
158 assert_eq!(pag.cursor_variable, "after");
159 assert_eq!(pag.page_size_variable, "first");
160 assert!(pag.page_size.is_none());
161 }
162}