Skip to main content

zai_rs/file/
list.rs

1use std::sync::Arc;
2
3use super::request::FileListQuery;
4use crate::{
5    ZaiResult,
6    client::{
7        endpoints::{ApiBase, EndpointConfig, build_query, paths},
8        http::{HttpClient, HttpClientConfig, parse_typed_response},
9    },
10};
11
12/// Files list request (GET /paas/v4/files)
13///
14/// Builds query parameters from `FileListQuery` and performs an authenticated
15/// GET.
16pub struct FileListRequest {
17    pub key: String,
18    url: String,
19    endpoint_config: EndpointConfig,
20    api_base: ApiBase,
21    query: FileListQuery,
22    _body: (),
23    http_config: Arc<HttpClientConfig>,
24}
25
26impl FileListRequest {
27    pub fn new(key: String) -> Self {
28        let endpoint_config = EndpointConfig::default();
29        let api_base = ApiBase::PaasV4;
30        let url = endpoint_config.url(&api_base, paths::FILES);
31        Self {
32            key,
33            url,
34            endpoint_config,
35            api_base,
36            query: FileListQuery::new(),
37            _body: (),
38            http_config: Arc::new(HttpClientConfig::default()),
39        }
40    }
41
42    fn rebuild_url(&mut self) {
43        let endpoint = self.endpoint_config.url(&self.api_base, paths::FILES);
44        let mut params: Vec<(&str, String)> = Vec::new();
45        if let Some(after) = self.query.after.as_ref() {
46            params.push(("after", after.clone()));
47        }
48        if let Some(purpose) = self.query.purpose.as_ref() {
49            params.push(("purpose", purpose.as_str().to_string()));
50        }
51        if let Some(order) = self.query.order.as_ref() {
52            params.push(("order", order.as_str().to_string()));
53        }
54        if let Some(limit) = self.query.limit.as_ref() {
55            params.push(("limit", limit.to_string()));
56        }
57        self.url = build_query(&endpoint, params);
58    }
59
60    pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
61        self.api_base = ApiBase::Custom(base_url.into());
62        self.rebuild_url();
63        self
64    }
65
66    pub fn with_endpoint_config(mut self, endpoint_config: EndpointConfig) -> Self {
67        self.endpoint_config = endpoint_config;
68        self.rebuild_url();
69        self
70    }
71
72    pub fn with_http_config(mut self, config: HttpClientConfig) -> Self {
73        self.http_config = Arc::new(config);
74        self
75    }
76
77    pub fn with_query(mut self, q: FileListQuery) -> Self {
78        self.query = q;
79        self.rebuild_url();
80        self
81    }
82    /// Send request and parse typed response.
83    pub async fn send(&self) -> ZaiResult<super::response::FileListResponse> {
84        let resp = self.get().await?;
85        parse_typed_response::<super::response::FileListResponse>(resp).await
86    }
87
88    /// Validate query, rebuild URL and send in one call.
89    pub async fn send_with_query(
90        mut self,
91        q: &super::request::FileListQuery,
92    ) -> ZaiResult<super::response::FileListResponse> {
93        use validator::Validate;
94        q.validate()?;
95        self.query = q.clone();
96        self.rebuild_url();
97        self.send().await
98    }
99}
100
101impl HttpClient for FileListRequest {
102    type Body = ();
103    type ApiUrl = String;
104    type ApiKey = String;
105
106    fn api_url(&self) -> &Self::ApiUrl {
107        &self.url
108    }
109    fn api_key(&self) -> &Self::ApiKey {
110        &self.key
111    }
112    fn body(&self) -> &Self::Body {
113        &self._body
114    }
115
116    fn http_config(&self) -> Arc<HttpClientConfig> {
117        self.http_config.clone()
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124    use crate::client::http::HttpClient;
125
126    #[test]
127    fn query_survives_base_rebuild() {
128        let request = FileListRequest::new("test.12345678901234567890".to_string())
129            .with_query(
130                FileListQuery::new()
131                    .with_purpose(crate::file::request::FilePurpose::Batch)
132                    .with_limit(2),
133            )
134            .with_base_url("http://127.0.0.1:12345/api/paas/v4");
135
136        assert_eq!(
137            request.api_url(),
138            "http://127.0.0.1:12345/api/paas/v4/files?purpose=batch&limit=2"
139        );
140    }
141
142    #[test]
143    fn query_survives_endpoint_config_rebuild() {
144        let endpoint_config =
145            EndpointConfig::default().with_paas_v4_base("http://127.0.0.1:12345/api/paas/v4");
146        let request = FileListRequest::new("test.12345678901234567890".to_string())
147            .with_query(FileListQuery::new().with_after("cursor").with_limit(10))
148            .with_endpoint_config(endpoint_config);
149
150        assert_eq!(
151            request.api_url(),
152            "http://127.0.0.1:12345/api/paas/v4/files?after=cursor&limit=10"
153        );
154    }
155}