1use crate::query::{request::QueryRequest, response::QueryResponse};
2use ureq::Request;
3
4pub struct Client {
5 host: String,
6 token: String,
7}
8
9pub enum ContentType {
10 Json(serde_json::Value),
11 None,
12}
13
14impl Client {
15 pub fn bq_client(token: String, project_id: &str) -> Self {
16 Self {
17 token,
18 host: format!(
19 "https://bigquery.googleapis.com/bigquery/v2/projects/{}",
20 project_id
21 ),
22 }
23 }
24
25 pub fn endpoint(&self, request: Request, body: ContentType) -> ureq::Response {
26 let request = request.set("AUTHORIZATION", &format!("Bearer {}", &self.token));
27
28 let response = match body {
29 ContentType::Json(data) => request.send_json(data),
30 ContentType::None => request.call(),
31 };
32
33 Self::handle_error(response)
34 }
35
36 pub fn jobs_query_results(&self, job_id: &str, location: &str) -> QueryResponse {
38 let response = self.endpoint(
39 ureq::get(&format!("{}/queries/{}", &self.host, job_id)).query("location", location),
40 ContentType::None,
41 );
42
43 response.into_json().unwrap()
44 }
45
46 pub fn jobs_query(&self, request: QueryRequest) -> QueryResponse {
49 let response = self.endpoint(
50 ureq::post(&format!("{}/queries", &self.host)),
51 ContentType::Json(serde_json::to_value(request).unwrap()),
52 );
53
54 let response: QueryResponse = response.into_json().unwrap();
55
56 response.retry(self)
57 }
58
59 pub fn tables_list(&self, dataset_id: &str) -> ureq::Response {
60 self.endpoint(
61 ureq::get(&format!("{}/datasets/{}/tables", &self.host, dataset_id)),
62 ContentType::None,
63 )
64 }
65
66 fn handle_error(result: Result<ureq::Response, ureq::Error>) -> ureq::Response {
67 match result {
68 Ok(r) => r,
69 Err(e) => {
70 let header = e.to_string();
71 let Some(response) = e.into_response() else {
72 panic!("{:#?}", &header);
73 };
74
75 panic!("{}\n{}", header, response.into_string().unwrap());
76 }
77 }
78 }
79}