Skip to main content

uarp_sdk/generated/api/
registry.rs

1// Code generated by @uarp/codegen from spec/openapi.json. DO NOT EDIT.
2//!
3//! Spec registry — publish, search, yank, share spec artifacts
4
5#![allow(unused_imports, clippy::too_many_arguments)]
6
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9
10use crate::client::{Client, Request, NO_BODY, NO_QUERY};
11use crate::error::Result;
12use crate::generated::models;
13use crate::multipart::{field_text, FilePart};
14use crate::util::encode_path;
15
16/// Query and header parameters for `registryAdminListSpecs`.
17#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
18pub struct RegistryAdminListSpecsParams {
19    #[serde(default, skip_serializing_if = "Option::is_none")]
20    pub limit: Option<i64>,
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub cursor: Option<String>,
23}
24
25/// Query and header parameters for `registryGetFile`.
26#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27pub struct RegistryGetFileParams {
28    /// Relative path within the artifact.
29    pub path: String,
30}
31
32/// Query and header parameters for `registrySearch`.
33#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
34pub struct RegistrySearchParams {
35    #[serde(default, skip_serializing_if = "Option::is_none")]
36    pub q: Option<String>,
37    #[serde(default, skip_serializing_if = "Option::is_none")]
38    pub scope: Option<String>,
39    #[serde(default, skip_serializing_if = "Option::is_none")]
40    pub category: Option<String>,
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub keyword: Option<String>,
43    #[serde(default, skip_serializing_if = "Option::is_none")]
44    pub limit: Option<i64>,
45    #[serde(default, skip_serializing_if = "Option::is_none")]
46    pub cursor: Option<String>,
47}
48
49/// Spec registry — publish, search, yank, share spec artifacts
50#[derive(Debug, Clone)]
51pub struct RegistryApi {
52    pub(crate) client: Client,
53}
54
55impl Client {
56    /// Spec registry — publish, search, yank, share spec artifacts
57    pub fn registry(&self) -> RegistryApi {
58        RegistryApi { client: self.clone() }
59    }
60}
61
62impl RegistryApi {
63    /// Add a SPEC to the featured set (super-admin)
64    ///
65    /// The SPEC's existence is confirmed BEFORE the featured set is touched, so a typo cannot leave
66    /// a dangling id in a shared list — that is what the 404 protects. The set itself is mutated
67    /// under a compare-and-set retry, because it is one shared record and a plain read-modify-write
68    /// was last-writer-wins.
69    ///
70    /// Idempotent: featuring an already-featured SPEC is 200, not a conflict.
71    ///
72    /// `POST /api/v1/registry/admin/specs/{scope}/{name}/feature`
73    pub async fn feature_registry_spec(&self, scope: &str, name: &str) -> Result<models::RegistrySpecFeatureState> {
74        self.client
75            .request_json(Request {
76                method: Method::POST,
77                path: format!("/api/v1/registry/admin/specs/{}/{}/feature", encode_path(scope), encode_path(name)),
78                query: NO_QUERY,
79                body: NO_BODY,
80                headers: Vec::new(),
81                idempotent: true,
82            })
83            .await
84    }
85
86    /// Admin: list all specs (regardless of visibility)
87    ///
88    /// `GET /api/v1/registry/admin/specs`
89    pub async fn registry_admin_list_specs(&self, params: &RegistryAdminListSpecsParams) -> Result<models::RegistryAdminListSpecsResponse> {
90        self.client
91            .request_json(Request {
92                method: Method::GET,
93                path: "/api/v1/registry/admin/specs".to_string(),
94                query: Some(params),
95                body: NO_BODY,
96                headers: Vec::new(),
97                idempotent: false,
98            })
99            .await
100    }
101
102    /// Download tarball/artifact bundle for a spec version
103    ///
104    /// `GET /api/v1/registry/spec/{scope}/{name}/{version}/artifact`
105    pub async fn registry_get_artifact(&self, scope: &str, name: &str, version: &str) -> Result<bytes::Bytes> {
106        self.client
107            .request_bytes(Request {
108                method: Method::GET,
109                path: format!("/api/v1/registry/spec/{}/{}/{}/artifact", encode_path(scope), encode_path(name), encode_path(version)),
110                query: NO_QUERY,
111                body: NO_BODY,
112                headers: Vec::new(),
113                idempotent: false,
114            })
115            .await
116    }
117
118    /// Get a single file from inside a spec version artifact
119    ///
120    /// `GET /api/v1/registry/spec/{scope}/{name}/{version}/file`
121    pub async fn registry_get_file(&self, scope: &str, name: &str, version: &str, params: &RegistryGetFileParams) -> Result<models::RegistryGetFileResponse> {
122        self.client
123            .request_json(Request {
124                method: Method::GET,
125                path: format!("/api/v1/registry/spec/{}/{}/{}/file", encode_path(scope), encode_path(name), encode_path(version)),
126                query: Some(params),
127                body: NO_BODY,
128                headers: Vec::new(),
129                idempotent: false,
130            })
131            .await
132    }
133
134    /// Get README for a spec version
135    ///
136    /// `GET /api/v1/registry/spec/{scope}/{name}/{version}/readme`
137    pub async fn registry_get_readme(&self, scope: &str, name: &str, version: &str) -> Result<models::RegistryGetReadmeResponse> {
138        self.client
139            .request_json(Request {
140                method: Method::GET,
141                path: format!("/api/v1/registry/spec/{}/{}/{}/readme", encode_path(scope), encode_path(name), encode_path(version)),
142                query: NO_QUERY,
143                body: NO_BODY,
144                headers: Vec::new(),
145                idempotent: false,
146            })
147            .await
148    }
149
150    /// Get share/visibility settings for a spec
151    ///
152    /// `GET /api/v1/registry/spec/{scope}/{name}/share`
153    pub async fn registry_get_share(&self, scope: &str, name: &str) -> Result<models::RegistryGetShareResponse> {
154        self.client
155            .request_json(Request {
156                method: Method::GET,
157                path: format!("/api/v1/registry/spec/{}/{}/share", encode_path(scope), encode_path(name)),
158                query: NO_QUERY,
159                body: NO_BODY,
160                headers: Vec::new(),
161                idempotent: false,
162            })
163            .await
164    }
165
166    /// Get sparse-index entry for a spec
167    ///
168    /// `GET /api/v1/registry/index/{shard}/{scope}/{name}`
169    pub async fn registry_get_sparse_index(&self, shard: &str, scope: &str, name: &str) -> Result<models::RegistryGetSparseIndexResponse> {
170        self.client
171            .request_json(Request {
172                method: Method::GET,
173                path: format!("/api/v1/registry/index/{}/{}/{}", encode_path(shard), encode_path(scope), encode_path(name)),
174                query: NO_QUERY,
175                body: NO_BODY,
176                headers: Vec::new(),
177                idempotent: false,
178            })
179            .await
180    }
181
182    /// Get spec metadata (latest version pointers, owners)
183    ///
184    /// `GET /api/v1/registry/spec/{scope}/{name}`
185    pub async fn registry_get_spec_metadata(&self, scope: &str, name: &str) -> Result<models::RegistryGetSpecMetadataResponse> {
186        self.client
187            .request_json(Request {
188                method: Method::GET,
189                path: format!("/api/v1/registry/spec/{}/{}", encode_path(scope), encode_path(name)),
190                query: NO_QUERY,
191                body: NO_BODY,
192                headers: Vec::new(),
193                idempotent: false,
194            })
195            .await
196    }
197
198    /// Get a specific version of a spec
199    ///
200    /// Returns the full PublishedSpec record plus a `download_url` pointing at the artifact
201    /// endpoint.
202    ///
203    /// `GET /api/v1/registry/spec/{scope}/{name}/{version}`
204    pub async fn registry_get_spec_version(&self, scope: &str, name: &str, version: &str) -> Result<models::RegistryGetSpecVersionResponse> {
205        self.client
206            .request_json(Request {
207                method: Method::GET,
208                path: format!("/api/v1/registry/spec/{}/{}/{}", encode_path(scope), encode_path(name), encode_path(version)),
209                query: NO_QUERY,
210                body: NO_BODY,
211                headers: Vec::new(),
212                idempotent: false,
213            })
214            .await
215    }
216
217    /// List files inside a spec version artifact
218    ///
219    /// `GET /api/v1/registry/spec/{scope}/{name}/{version}/files`
220    pub async fn registry_list_files(&self, scope: &str, name: &str, version: &str) -> Result<models::RegistryListFilesResponse> {
221        self.client
222            .request_json(Request {
223                method: Method::GET,
224                path: format!("/api/v1/registry/spec/{}/{}/{}/files", encode_path(scope), encode_path(name), encode_path(version)),
225                query: NO_QUERY,
226                body: NO_BODY,
227                headers: Vec::new(),
228                idempotent: false,
229            })
230            .await
231    }
232
233    /// Publish a new spec version to the registry
234    ///
235    /// Multipart upload of a tarball + manifest. Server validates manifest, verifies optional
236    /// sha256, and persists the artifact. Returns the full PublishedSpec record. `Location` header
237    /// points at the version's metadata endpoint.
238    ///
239    /// `POST /api/v1/registry/publish`
240    pub async fn registry_publish(&self, body: &models::RegistryPublishRequest) -> Result<models::RegistryPublishResponse> {
241        self.client
242            .request_multipart(
243                Request {
244                    method: Method::POST,
245                    path: "/api/v1/registry/publish".to_string(),
246                    query: NO_QUERY,
247                    body: NO_BODY,
248                    headers: Vec::new(),
249                    idempotent: true,
250                },
251                || {
252                    let mut form = reqwest::multipart::Form::new();
253                    form = form.text("manifest", field_text(&body.manifest)?);
254                    form = form.part("artifact", body.artifact.clone().into_part()?);
255                    if let Some(value) = &body.sha256 {
256                        form = form.text("sha256", field_text(value)?);
257                    }
258                    if let Some(value) = &body.attestation {
259                        form = form.text("attestation", field_text(value)?);
260                    }
261                    Ok(form)
262                },
263            )
264            .await
265    }
266
267    /// Search the registry for specs
268    ///
269    /// `GET /api/v1/registry/search`
270    pub async fn registry_search(&self, params: &RegistrySearchParams) -> Result<models::RegistrySearchResponse> {
271        self.client
272            .request_json(Request {
273                method: Method::GET,
274                path: "/api/v1/registry/search".to_string(),
275                query: Some(params),
276                body: NO_BODY,
277                headers: Vec::new(),
278                idempotent: false,
279            })
280            .await
281    }
282
283    /// Set share/visibility settings for a spec
284    ///
285    /// `POST /api/v1/registry/spec/{scope}/{name}/share`
286    pub async fn registry_set_share(&self, scope: &str, name: &str, body: &models::RegistrySetShareRequest) -> Result<models::RegistrySetShareResponse> {
287        self.client
288            .request_json(Request {
289                method: Method::POST,
290                path: format!("/api/v1/registry/spec/{}/{}/share", encode_path(scope), encode_path(name)),
291                query: NO_QUERY,
292                body: Some(body),
293                headers: Vec::new(),
294                idempotent: true,
295            })
296            .await
297    }
298
299    /// Reverse a yank on a published spec version
300    ///
301    /// `POST /api/v1/registry/spec/{scope}/{name}/{version}/unyank`
302    pub async fn registry_unyank_version(&self, scope: &str, name: &str, version: &str) -> Result<models::RegistryUnyankVersionResponse> {
303        self.client
304            .request_json(Request {
305                method: Method::POST,
306                path: format!("/api/v1/registry/spec/{}/{}/{}/unyank", encode_path(scope), encode_path(name), encode_path(version)),
307                query: NO_QUERY,
308                body: NO_BODY,
309                headers: Vec::new(),
310                idempotent: true,
311            })
312            .await
313    }
314
315    /// Yank (mark unsafe) a published spec version
316    ///
317    /// `POST /api/v1/registry/spec/{scope}/{name}/{version}/yank`
318    pub async fn registry_yank_version(&self, scope: &str, name: &str, version: &str, body: &models::RegistryYankVersionRequest) -> Result<models::RegistryYankVersionResponse> {
319        self.client
320            .request_json(Request {
321                method: Method::POST,
322                path: format!("/api/v1/registry/spec/{}/{}/{}/yank", encode_path(scope), encode_path(name), encode_path(version)),
323                query: NO_QUERY,
324                body: Some(body),
325                headers: Vec::new(),
326                idempotent: true,
327            })
328            .await
329    }
330
331    /// Bulk-publish the bundled starter SPECs (super-admin)
332    ///
333    /// Idempotent: a starter SPEC already present is counted in `skipped`, not republished, so
334    /// re-running is safe and is how a partially-failed seed is completed.
335    ///
336    /// `errors` is present ONLY when at least one SPEC failed. Its absence means no failures — not
337    /// that the field is unavailable — so a client should treat missing as empty rather than
338    /// unknown. A run can be partially successful: `added` and `errors` are both meaningful in the
339    /// same response, and the status is still 200.
340    ///
341    /// `POST /api/v1/registry/admin/specs/seed`
342    pub async fn seed_starter_specs(&self) -> Result<models::SeedStarterSpecsResponse> {
343        self.client
344            .request_json(Request {
345                method: Method::POST,
346                path: "/api/v1/registry/admin/specs/seed".to_string(),
347                query: NO_QUERY,
348                body: NO_BODY,
349                headers: Vec::new(),
350                idempotent: true,
351            })
352            .await
353    }
354
355    /// Make a SPEC public or private (super-admin)
356    ///
357    /// PATCH and only PATCH — a PUT is 405 with the allowed methods named.
358    ///
359    /// WRITE SEMANTICS: replaces the visibility, which is the only field this route touches.
360    /// `visibility` is required and must be exactly `public` or `private`; anything else, including
361    /// a missing body or a near-miss like `unlisted`, is 400 rather than being coerced or ignored.
362    ///
363    /// `PATCH /api/v1/registry/admin/specs/{scope}/{name}/visibility`
364    pub async fn set_registry_spec_visibility(&self, scope: &str, name: &str, body: &models::SetRegistrySpecVisibilityRequest) -> Result<models::SetRegistrySpecVisibilityResponse> {
365        self.client
366            .request_json(Request {
367                method: Method::PATCH,
368                path: format!("/api/v1/registry/admin/specs/{}/{}/visibility", encode_path(scope), encode_path(name)),
369                query: NO_QUERY,
370                body: Some(body),
371                headers: Vec::new(),
372                idempotent: true,
373            })
374            .await
375    }
376
377    /// Remove a SPEC from the featured set (super-admin)
378    ///
379    /// Same shape and same guards as the POST; the response's `featured` is simply `false`.
380    /// Idempotent — un-featuring something that was not featured is 200.
381    ///
382    /// `DELETE /api/v1/registry/admin/specs/{scope}/{name}/feature`
383    pub async fn unfeature_registry_spec(&self, scope: &str, name: &str) -> Result<models::RegistrySpecFeatureState> {
384        self.client
385            .request_json(Request {
386                method: Method::DELETE,
387                path: format!("/api/v1/registry/admin/specs/{}/{}/feature", encode_path(scope), encode_path(name)),
388                query: NO_QUERY,
389                body: NO_BODY,
390                headers: Vec::new(),
391                idempotent: true,
392            })
393            .await
394    }
395}