1#![allow(unused_imports, clippy::too_many_arguments)]
6
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9use futures_core::Stream;
10
11use crate::client::{Client, Request, NO_BODY, NO_QUERY};
12use crate::error::Result;
13use crate::generated::models;
14use crate::multipart::{field_text, FilePart};
15use crate::pagination::CursorGuard;
16use crate::util::encode_path;
17
18#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
20pub struct GetListingReviewsParams {
21 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub limit: Option<i64>,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub cursor: Option<String>,
25}
26
27#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
29pub struct SearchMarketplaceParams {
30 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub q: Option<String>,
32 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub category: Option<models::MarketplaceListingCategory>,
34 #[serde(default, skip_serializing_if = "Option::is_none")]
35 pub sort: Option<models::SearchMarketplaceSort>,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 pub limit: Option<i64>,
38}
39
40#[derive(Debug, Clone)]
42pub struct MarketplaceApi {
43 pub(crate) client: Client,
44}
45
46impl Client {
47 pub fn marketplace(&self) -> MarketplaceApi {
49 MarketplaceApi { client: self.clone() }
50 }
51}
52
53impl MarketplaceApi {
54 pub async fn get_listing(&self, listing_id: &str) -> Result<models::MarketplaceListing> {
60 self.client
61 .request_json(Request {
62 method: Method::GET,
63 path: format!("/api/v1/marketplace/listings/{}", encode_path(listing_id)),
64 query: NO_QUERY,
65 body: NO_BODY,
66 headers: Vec::new(),
67 idempotent: false,
68 })
69 .await
70 }
71
72 pub async fn get_listing_reviews(&self, listing_id: &str, params: &GetListingReviewsParams) -> Result<models::GetListingReviewsResponse> {
76 self.client
77 .request_json(Request {
78 method: Method::GET,
79 path: format!("/api/v1/marketplace/listings/{}/reviews", encode_path(listing_id)),
80 query: Some(params),
81 body: NO_BODY,
82 headers: Vec::new(),
83 idempotent: false,
84 })
85 .await
86 }
87
88 pub fn get_listing_reviews_all<'a>(&'a self, listing_id: &'a str, params: &'a GetListingReviewsParams) -> impl Stream<Item = Result<serde_json::Map<String, serde_json::Value>>> + 'a {
91 async_stream::try_stream! {
92 let mut guard = CursorGuard::new();
93 let mut cursor = params.cursor.clone();
94 loop {
95 let mut page_params = params.clone();
96 page_params.cursor = cursor.clone();
97 let page = self.get_listing_reviews(listing_id, &page_params).await?;
98 let items = page.reviews.unwrap_or_default();
99 let was_empty = items.is_empty();
100 for item in items {
101 yield item;
102 }
103 match guard.advance(page.cursor, None, was_empty) {
104 Some(next) => cursor = Some(next),
105 None => break,
106 }
107 }
108 }
109 }
110
111 pub async fn get_marketplace_categories(&self) -> Result<models::GetMarketplaceCategoriesResponse> {
117 self.client
118 .request_json(Request {
119 method: Method::GET,
120 path: "/api/v1/marketplace/categories".to_string(),
121 query: NO_QUERY,
122 body: NO_BODY,
123 headers: Vec::new(),
124 idempotent: false,
125 })
126 .await
127 }
128
129 pub async fn get_marketplace_invocation(&self, invocation_id: &str) -> Result<models::MarketplaceInvocation> {
135 self.client
136 .request_json(Request {
137 method: Method::GET,
138 path: format!("/api/v1/marketplace/invocations/{}", encode_path(invocation_id)),
139 query: NO_QUERY,
140 body: NO_BODY,
141 headers: Vec::new(),
142 idempotent: false,
143 })
144 .await
145 }
146
147 pub async fn invoke_listing_agent(&self, listing_id: &str, body: &models::InvokeListingAgentRequest) -> Result<models::MarketplaceInvocation> {
153 self.client
154 .request_json(Request {
155 method: Method::POST,
156 path: format!("/api/v1/marketplace/listings/{}/invoke", encode_path(listing_id)),
157 query: NO_QUERY,
158 body: Some(body),
159 headers: Vec::new(),
160 idempotent: true,
161 })
162 .await
163 }
164
165 pub async fn list_featured_specs(&self) -> Result<models::ListFeaturedSpecsResponse> {
172 self.client
173 .request_json(Request {
174 method: Method::GET,
175 path: "/api/v1/marketplace/featured-specs".to_string(),
176 query: NO_QUERY,
177 body: NO_BODY,
178 headers: Vec::new(),
179 idempotent: false,
180 })
181 .await
182 }
183
184 pub async fn list_subscriptions(&self) -> Result<models::ListSubscriptionsResponse> {
190 self.client
191 .request_json(Request {
192 method: Method::GET,
193 path: "/api/v1/marketplace/subscriptions".to_string(),
194 query: NO_QUERY,
195 body: NO_BODY,
196 headers: Vec::new(),
197 idempotent: false,
198 })
199 .await
200 }
201
202 pub async fn publish_listing(&self, body: &models::PublishListingRequest) -> Result<models::MarketplaceListing> {
208 self.client
209 .request_json(Request {
210 method: Method::POST,
211 path: "/api/v1/marketplace/listings".to_string(),
212 query: NO_QUERY,
213 body: Some(body),
214 headers: Vec::new(),
215 idempotent: true,
216 })
217 .await
218 }
219
220 pub async fn rate_listing(&self, listing_id: &str, body: &models::RateListingRequest) -> Result<models::MarketplaceListingRating> {
226 self.client
227 .request_json(Request {
228 method: Method::POST,
229 path: format!("/api/v1/marketplace/listings/{}/rate", encode_path(listing_id)),
230 query: NO_QUERY,
231 body: Some(body),
232 headers: Vec::new(),
233 idempotent: true,
234 })
235 .await
236 }
237
238 pub async fn search(&self, params: &SearchMarketplaceParams) -> Result<models::SearchMarketplaceResponse> {
244 self.client
245 .request_json(Request {
246 method: Method::GET,
247 path: "/api/v1/marketplace/search".to_string(),
248 query: Some(params),
249 body: NO_BODY,
250 headers: Vec::new(),
251 idempotent: false,
252 })
253 .await
254 }
255
256 pub async fn subscribe_to_listing(&self, listing_id: &str, body: &models::SubscribeToListingRequest) -> Result<serde_json::Map<String, serde_json::Value>> {
262 self.client
263 .request_json(Request {
264 method: Method::POST,
265 path: format!("/api/v1/marketplace/listings/{}/subscribe", encode_path(listing_id)),
266 query: NO_QUERY,
267 body: Some(body),
268 headers: Vec::new(),
269 idempotent: true,
270 })
271 .await
272 }
273
274 pub async fn unpublish_listing(&self, listing_id: &str) -> Result<models::UnpublishListingResponse> {
280 self.client
281 .request_json(Request {
282 method: Method::DELETE,
283 path: format!("/api/v1/marketplace/listings/{}", encode_path(listing_id)),
284 query: NO_QUERY,
285 body: NO_BODY,
286 headers: Vec::new(),
287 idempotent: true,
288 })
289 .await
290 }
291
292 pub async fn unsubscribe_from_listing(&self, listing_id: &str) -> Result<models::UnsubscribeFromListingResponse> {
298 self.client
299 .request_json(Request {
300 method: Method::DELETE,
301 path: format!("/api/v1/marketplace/listings/{}/subscribe", encode_path(listing_id)),
302 query: NO_QUERY,
303 body: NO_BODY,
304 headers: Vec::new(),
305 idempotent: true,
306 })
307 .await
308 }
309}