Skip to main content

apify_client/clients/
store_collection.rs

1//! Client for browsing the Apify Store (`/v2/store`).
2
3use crate::clients::base::{list_resource, ResourceContext};
4use crate::clients::pagination::{list_iterator, ListIterator};
5use crate::common::{PaginationList, QueryParams};
6use crate::error::ApifyClientResult;
7use crate::http_client::HttpClient;
8use crate::models::ActorStoreListItem;
9
10/// A lazy, page-fetching iterator over Apify Store Actors.
11///
12/// Returned by [`StoreCollectionClient::iterate`]. This is an alias for the shared
13/// [`ListIterator`]; call its `next()` to yield one Actor at a time, fetching further pages
14/// from the API transparently until the listing is exhausted.
15pub type StoreActorIterator = ListIterator<ActorStoreListItem>;
16
17/// Options for searching the Apify Store.
18#[derive(Debug, Default, Clone)]
19pub struct StoreListOptions {
20    /// Number of items to skip.
21    pub offset: Option<i64>,
22    /// Item limit. Its meaning depends on the method: for [`StoreCollectionClient::list`] it is a
23    /// single page's size (the maximum items that one call returns); for
24    /// [`StoreCollectionClient::iterate`] it is a cap on the *total* number of items yielded across
25    /// all pages. See each method's docs.
26    pub limit: Option<i64>,
27    /// Full-text search query.
28    pub search: Option<String>,
29    /// Sort key (e.g. `popularity`, `newest`).
30    pub sort_by: Option<String>,
31    /// Filter by category.
32    pub category: Option<String>,
33    /// Filter by owner username.
34    pub username: Option<String>,
35    /// Filter by pricing model.
36    pub pricing_model: Option<String>,
37    /// Include Actors that the current user cannot run (e.g. needing a missing integration).
38    pub include_unrunnable_actors: Option<bool>,
39    /// Filter to Actors that allow agentic (x402/Skyfire) users.
40    pub allows_agentic_users: Option<bool>,
41    /// Response format requested from the API (e.g. `json`).
42    pub response_format: Option<String>,
43}
44
45/// Client for the Apify Store.
46#[derive(Debug, Clone)]
47pub struct StoreCollectionClient {
48    ctx: ResourceContext,
49}
50
51impl StoreCollectionClient {
52    pub(crate) fn new(http: HttpClient, base_url: &str) -> Self {
53        Self {
54            ctx: ResourceContext::collection(http, base_url, "store"),
55        }
56    }
57
58    /// Lists Actors from the Apify Store matching the given options.
59    ///
60    /// Awaiting once returns a single page; use [`StoreCollectionClient::iterate`] to lazily
61    /// iterate across pages.
62    pub async fn list(
63        &self,
64        options: StoreListOptions,
65    ) -> ApifyClientResult<PaginationList<ActorStoreListItem>> {
66        let params = self.build_params(&options);
67        list_resource(&self.ctx, None, &params).await
68    }
69
70    /// Lazily iterates all Store Actors matching `options`, fetching pages on demand.
71    ///
72    /// Returns a [`StoreActorIterator`] whose `next()` method yields one Actor at a time,
73    /// transparently fetching subsequent pages.
74    ///
75    /// `options.limit` caps the *total* number of items yielded across all pages, unlike
76    /// [`list`](Self::list) where `limit` is a single page's size. Set the per-page fetch size
77    /// with [`with_chunk_size`](crate::ListIterator::with_chunk_size); see
78    /// [`ListIterator`] for details.
79    pub fn iterate(&self, options: StoreListOptions) -> StoreActorIterator {
80        list_iterator!(self, options, list)
81    }
82
83    fn build_params(&self, options: &StoreListOptions) -> QueryParams {
84        let mut params = QueryParams::new();
85        params
86            .add_int("offset", options.offset)
87            .add_int("limit", options.limit)
88            .add_str("search", options.search.clone())
89            .add_str("sortBy", options.sort_by.clone())
90            .add_str("category", options.category.clone())
91            .add_str("username", options.username.clone())
92            .add_str("pricingModel", options.pricing_model.clone())
93            .add_bool("includeUnrunnableActors", options.include_unrunnable_actors)
94            .add_bool("allowsAgenticUsers", options.allows_agentic_users)
95            .add_str("responseFormat", options.response_format.clone());
96        params
97    }
98}