Skip to main content

hanzo_client/apis/
todo_api.rs

1/*
2 * Hanzo Cloud API
3 *
4 * The Hanzo Cloud API as a customer calls it: every operation under /v1/ except the operator's admin product, relay routes, legacy spellings and capabilities still reached by flag. Tagged by product: the first path segment after /v1/.
5 *
6 * The version of the OpenAPI document: v1
7 * 
8 * Generated by: https://openapi-generator.tech
9 */
10
11
12use reqwest;
13use serde::{Deserialize, Serialize, de::Error as _};
14use crate::{apis::ResponseContent, models};
15use super::{Error, configuration, ContentType};
16
17
18/// struct for typed errors of method [`delete_todo_projects_by_key`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum DeleteTodoProjectsByKeyError {
22    UnknownValue(serde_json::Value),
23}
24
25/// struct for typed errors of method [`get_todo_board`]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum GetTodoBoardError {
29    UnknownValue(serde_json::Value),
30}
31
32/// struct for typed errors of method [`get_todo_issues`]
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(untagged)]
35pub enum GetTodoIssuesError {
36    UnknownValue(serde_json::Value),
37}
38
39/// struct for typed errors of method [`get_todo_projects`]
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum GetTodoProjectsError {
43    UnknownValue(serde_json::Value),
44}
45
46/// struct for typed errors of method [`get_todo_projects_by_key`]
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum GetTodoProjectsByKeyError {
50    UnknownValue(serde_json::Value),
51}
52
53/// struct for typed errors of method [`get_todo_projects_by_key_issues`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum GetTodoProjectsByKeyIssuesError {
57    UnknownValue(serde_json::Value),
58}
59
60/// struct for typed errors of method [`get_todo_projects_by_key_issues_by_num`]
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(untagged)]
63pub enum GetTodoProjectsByKeyIssuesByNumError {
64    UnknownValue(serde_json::Value),
65}
66
67/// struct for typed errors of method [`get_todo_rooms_by_room`]
68#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(untagged)]
70pub enum GetTodoRoomsByRoomError {
71    UnknownValue(serde_json::Value),
72}
73
74/// struct for typed errors of method [`patch_todo_projects_by_key`]
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(untagged)]
77pub enum PatchTodoProjectsByKeyError {
78    UnknownValue(serde_json::Value),
79}
80
81/// struct for typed errors of method [`patch_todo_projects_by_key_issues_by_num`]
82#[derive(Debug, Clone, Serialize, Deserialize)]
83#[serde(untagged)]
84pub enum PatchTodoProjectsByKeyIssuesByNumError {
85    UnknownValue(serde_json::Value),
86}
87
88/// struct for typed errors of method [`post_todo_projects`]
89#[derive(Debug, Clone, Serialize, Deserialize)]
90#[serde(untagged)]
91pub enum PostTodoProjectsError {
92    UnknownValue(serde_json::Value),
93}
94
95/// struct for typed errors of method [`post_todo_projects_by_key_issues`]
96#[derive(Debug, Clone, Serialize, Deserialize)]
97#[serde(untagged)]
98pub enum PostTodoProjectsByKeyIssuesError {
99    UnknownValue(serde_json::Value),
100}
101
102/// struct for typed errors of method [`post_todo_projects_by_key_issues_by_num_claim`]
103#[derive(Debug, Clone, Serialize, Deserialize)]
104#[serde(untagged)]
105pub enum PostTodoProjectsByKeyIssuesByNumClaimError {
106    UnknownValue(serde_json::Value),
107}
108
109
110/// Answers 405. A todo board IS a repository on this deployment's forge, so creating, renaming and deleting one is a FORGE operation carried out with FORGE permissions.  Offering it here would put a second endpoint on the same object, guarded by this surface instead of by the forge — a weaker guard on the same thing. So the route exists and refuses, rather than 404ing: \"not this service's job\" and \"no such thing\" are different facts, and the body names the forge so a caller knows where the job IS done.  What this surface DOES own is the work on a board: list the boards you can see, read and file their issues, move a card between columns, and read the schedule a milestone is. Those are the routes beside this one.
111pub async fn delete_todo_projects_by_key(configuration: &configuration::Configuration, key: &str) -> Result<(), Error<DeleteTodoProjectsByKeyError>> {
112    // add a prefix to parameters to efficiently prevent name collisions
113    let p_key = key;
114
115    let uri_str = format!("{}/v1/todo/projects/{key}", configuration.base_path, key=crate::apis::urlencode(p_key));
116    let mut req_builder = configuration.client.request(reqwest::Method::DELETE, &uri_str);
117
118    if let Some(ref user_agent) = configuration.user_agent {
119        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
120    }
121    if let Some(ref token) = configuration.bearer_access_token {
122        req_builder = req_builder.bearer_auth(token.to_owned());
123    };
124
125    let req = req_builder.build()?;
126    let resp = configuration.client.execute(req).await?;
127
128    let status = resp.status();
129
130    if !status.is_client_error() && !status.is_server_error() {
131        Ok(())
132    } else {
133        let content = resp.text().await?;
134        let entity: Option<DeleteTodoProjectsByKeyError> = serde_json::from_str(&content).ok();
135        Err(Error::ResponseError(ResponseContent { status, content, entity }))
136    }
137}
138
139/// Returns a board's issues — work items with their column, priority, assignee, labels and schedule.  WHICH board is a filter, not an address. Bound to a repository (the key from the path) it is that project's board; left unbound it is the org's whole board; narrowed by label it is a board smaller than any repository — which is the only way an app that lives as a directory inside a shared repository can have one. Every combination is the same rows through the same projection, so no two boards can disagree about what a column means.  The column is a LABEL on the forge, so the board and the forge web UI are the same object seen twice: relabelling in either moves the card in both. A closed issue reads as done whatever its labels say.
140pub async fn get_todo_board(configuration: &configuration::Configuration, key: Option<&str>, status: Option<&str>, kind: Option<&str>, repo: Option<&str>, label: Option<&str>, source: Option<&str>, scheduled: Option<bool>) -> Result<Vec<models::IssueView>, Error<GetTodoBoardError>> {
141    // add a prefix to parameters to efficiently prevent name collisions
142    let p_key = key;
143    let p_status = status;
144    let p_kind = kind;
145    let p_repo = repo;
146    let p_label = label;
147    let p_source = source;
148    let p_scheduled = scheduled;
149
150    let uri_str = format!("{}/v1/todo/board", configuration.base_path);
151    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
152
153    if let Some(ref param_value) = p_key {
154        req_builder = req_builder.query(&[("key", &param_value.to_string())]);
155    }
156    if let Some(ref param_value) = p_status {
157        req_builder = req_builder.query(&[("status", &param_value.to_string())]);
158    }
159    if let Some(ref param_value) = p_kind {
160        req_builder = req_builder.query(&[("kind", &param_value.to_string())]);
161    }
162    if let Some(ref param_value) = p_repo {
163        req_builder = req_builder.query(&[("repo", &param_value.to_string())]);
164    }
165    if let Some(ref param_value) = p_label {
166        req_builder = req_builder.query(&[("label", &param_value.to_string())]);
167    }
168    if let Some(ref param_value) = p_source {
169        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
170    }
171    if let Some(ref param_value) = p_scheduled {
172        req_builder = req_builder.query(&[("scheduled", &param_value.to_string())]);
173    }
174    if let Some(ref user_agent) = configuration.user_agent {
175        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
176    }
177    if let Some(ref token) = configuration.bearer_access_token {
178        req_builder = req_builder.bearer_auth(token.to_owned());
179    };
180
181    let req = req_builder.build()?;
182    let resp = configuration.client.execute(req).await?;
183
184    let status = resp.status();
185    let content_type = resp
186        .headers()
187        .get("content-type")
188        .and_then(|v| v.to_str().ok())
189        .unwrap_or("application/octet-stream");
190    let content_type = super::ContentType::from(content_type);
191
192    if !status.is_client_error() && !status.is_server_error() {
193        let content = resp.text().await?;
194        match content_type {
195            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
196            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `Vec&lt;models::IssueView&gt;`"))),
197            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `Vec&lt;models::IssueView&gt;`")))),
198        }
199    } else {
200        let content = resp.text().await?;
201        let entity: Option<GetTodoBoardError> = serde_json::from_str(&content).ok();
202        Err(Error::ResponseError(ResponseContent { status, content, entity }))
203    }
204}
205
206/// Answers across every project in the org.  The org comes from the validated principal and never from the request: a caller able to name the org could read another tenant's backlog, and a search is exactly the shape that would quietly return it.
207pub async fn get_todo_issues(configuration: &configuration::Configuration, q: Option<&str>, project: Option<&str>, status: Option<&str>, kind: Option<&str>, repo: Option<&str>, room: Option<&str>, source: Option<&str>, assignee: Option<&str>, limit: Option<i32>) -> Result<models::IssueHits, Error<GetTodoIssuesError>> {
208    // add a prefix to parameters to efficiently prevent name collisions
209    let p_q = q;
210    let p_project = project;
211    let p_status = status;
212    let p_kind = kind;
213    let p_repo = repo;
214    let p_room = room;
215    let p_source = source;
216    let p_assignee = assignee;
217    let p_limit = limit;
218
219    let uri_str = format!("{}/v1/todo/issues", configuration.base_path);
220    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
221
222    if let Some(ref param_value) = p_q {
223        req_builder = req_builder.query(&[("q", &param_value.to_string())]);
224    }
225    if let Some(ref param_value) = p_project {
226        req_builder = req_builder.query(&[("project", &param_value.to_string())]);
227    }
228    if let Some(ref param_value) = p_status {
229        req_builder = req_builder.query(&[("status", &param_value.to_string())]);
230    }
231    if let Some(ref param_value) = p_kind {
232        req_builder = req_builder.query(&[("kind", &param_value.to_string())]);
233    }
234    if let Some(ref param_value) = p_repo {
235        req_builder = req_builder.query(&[("repo", &param_value.to_string())]);
236    }
237    if let Some(ref param_value) = p_room {
238        req_builder = req_builder.query(&[("room", &param_value.to_string())]);
239    }
240    if let Some(ref param_value) = p_source {
241        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
242    }
243    if let Some(ref param_value) = p_assignee {
244        req_builder = req_builder.query(&[("assignee", &param_value.to_string())]);
245    }
246    if let Some(ref param_value) = p_limit {
247        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
248    }
249    if let Some(ref user_agent) = configuration.user_agent {
250        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
251    }
252    if let Some(ref token) = configuration.bearer_access_token {
253        req_builder = req_builder.bearer_auth(token.to_owned());
254    };
255
256    let req = req_builder.build()?;
257    let resp = configuration.client.execute(req).await?;
258
259    let status = resp.status();
260    let content_type = resp
261        .headers()
262        .get("content-type")
263        .and_then(|v| v.to_str().ok())
264        .unwrap_or("application/octet-stream");
265    let content_type = super::ContentType::from(content_type);
266
267    if !status.is_client_error() && !status.is_server_error() {
268        let content = resp.text().await?;
269        match content_type {
270            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
271            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::IssueHits`"))),
272            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::IssueHits`")))),
273        }
274    } else {
275        let content = resp.text().await?;
276        let entity: Option<GetTodoIssuesError> = serde_json::from_str(&content).ok();
277        Err(Error::ResponseError(ResponseContent { status, content, entity }))
278    }
279}
280
281/// Returns the boards of your org — the places your work actually is. The key addresses the board's issues.  A BOARD IS A PLACE WORK IS, not an object somebody provisioned. So the list is assembled from the work itself: the repositories your org has filed issues on, plus the boards the index holds. A repository with nothing on it is not in the list and is still perfectly addressable — GET /projects/<name> reads it and a create files into it — so nothing is lost by leaving it out.  Measured, which is why: reading the forge's whole repository inventory put 745 boards here, of which all but a handful were vendored forks and mirrors (.github, .profile, DOMPurify, BoatAttack) that will never carry this org's work. A list that long is not a list — the estate's real roadmap was in it somewhere and no one could see it.  The forge half is the FORGE's answer for your own account, so two people in one org can legitimately see different boards.
282pub async fn get_todo_projects(configuration: &configuration::Configuration, ) -> Result<Vec<models::TodoProject>, Error<GetTodoProjectsError>> {
283
284    let uri_str = format!("{}/v1/todo/projects", configuration.base_path);
285    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
286
287    if let Some(ref user_agent) = configuration.user_agent {
288        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
289    }
290    if let Some(ref token) = configuration.bearer_access_token {
291        req_builder = req_builder.bearer_auth(token.to_owned());
292    };
293
294    let req = req_builder.build()?;
295    let resp = configuration.client.execute(req).await?;
296
297    let status = resp.status();
298    let content_type = resp
299        .headers()
300        .get("content-type")
301        .and_then(|v| v.to_str().ok())
302        .unwrap_or("application/octet-stream");
303    let content_type = super::ContentType::from(content_type);
304
305    if !status.is_client_error() && !status.is_server_error() {
306        let content = resp.text().await?;
307        match content_type {
308            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
309            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `Vec&lt;models::TodoProject&gt;`"))),
310            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `Vec&lt;models::TodoProject&gt;`")))),
311        }
312    } else {
313        let content = resp.text().await?;
314        let entity: Option<GetTodoProjectsError> = serde_json::from_str(&content).ok();
315        Err(Error::ResponseError(ResponseContent { status, content, entity }))
316    }
317}
318
319/// Returns one board of your org by its key — the repository name. 404 when your org has no repository under that key, or when your own forge account cannot see it.
320pub async fn get_todo_projects_by_key(configuration: &configuration::Configuration, key: &str) -> Result<models::TodoProject, Error<GetTodoProjectsByKeyError>> {
321    // add a prefix to parameters to efficiently prevent name collisions
322    let p_key = key;
323
324    let uri_str = format!("{}/v1/todo/projects/{key}", configuration.base_path, key=crate::apis::urlencode(p_key));
325    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
326
327    if let Some(ref user_agent) = configuration.user_agent {
328        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
329    }
330    if let Some(ref token) = configuration.bearer_access_token {
331        req_builder = req_builder.bearer_auth(token.to_owned());
332    };
333
334    let req = req_builder.build()?;
335    let resp = configuration.client.execute(req).await?;
336
337    let status = resp.status();
338    let content_type = resp
339        .headers()
340        .get("content-type")
341        .and_then(|v| v.to_str().ok())
342        .unwrap_or("application/octet-stream");
343    let content_type = super::ContentType::from(content_type);
344
345    if !status.is_client_error() && !status.is_server_error() {
346        let content = resp.text().await?;
347        match content_type {
348            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
349            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::TodoProject`"))),
350            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::TodoProject`")))),
351        }
352    } else {
353        let content = resp.text().await?;
354        let entity: Option<GetTodoProjectsByKeyError> = serde_json::from_str(&content).ok();
355        Err(Error::ResponseError(ResponseContent { status, content, entity }))
356    }
357}
358
359/// Returns a board's issues — work items with their column, priority, assignee, labels and schedule.  WHICH board is a filter, not an address. Bound to a repository (the key from the path) it is that project's board; left unbound it is the org's whole board; narrowed by label it is a board smaller than any repository — which is the only way an app that lives as a directory inside a shared repository can have one. Every combination is the same rows through the same projection, so no two boards can disagree about what a column means.  The column is a LABEL on the forge, so the board and the forge web UI are the same object seen twice: relabelling in either moves the card in both. A closed issue reads as done whatever its labels say.
360pub async fn get_todo_projects_by_key_issues(configuration: &configuration::Configuration, key: &str, status: Option<&str>, kind: Option<&str>, repo: Option<&str>, label: Option<&str>, source: Option<&str>, scheduled: Option<bool>) -> Result<Vec<models::IssueView>, Error<GetTodoProjectsByKeyIssuesError>> {
361    // add a prefix to parameters to efficiently prevent name collisions
362    let p_key = key;
363    let p_status = status;
364    let p_kind = kind;
365    let p_repo = repo;
366    let p_label = label;
367    let p_source = source;
368    let p_scheduled = scheduled;
369
370    let uri_str = format!("{}/v1/todo/projects/{key}/issues", configuration.base_path, key=crate::apis::urlencode(p_key));
371    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
372
373    if let Some(ref param_value) = p_status {
374        req_builder = req_builder.query(&[("status", &param_value.to_string())]);
375    }
376    if let Some(ref param_value) = p_kind {
377        req_builder = req_builder.query(&[("kind", &param_value.to_string())]);
378    }
379    if let Some(ref param_value) = p_repo {
380        req_builder = req_builder.query(&[("repo", &param_value.to_string())]);
381    }
382    if let Some(ref param_value) = p_label {
383        req_builder = req_builder.query(&[("label", &param_value.to_string())]);
384    }
385    if let Some(ref param_value) = p_source {
386        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
387    }
388    if let Some(ref param_value) = p_scheduled {
389        req_builder = req_builder.query(&[("scheduled", &param_value.to_string())]);
390    }
391    if let Some(ref user_agent) = configuration.user_agent {
392        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
393    }
394    if let Some(ref token) = configuration.bearer_access_token {
395        req_builder = req_builder.bearer_auth(token.to_owned());
396    };
397
398    let req = req_builder.build()?;
399    let resp = configuration.client.execute(req).await?;
400
401    let status = resp.status();
402    let content_type = resp
403        .headers()
404        .get("content-type")
405        .and_then(|v| v.to_str().ok())
406        .unwrap_or("application/octet-stream");
407    let content_type = super::ContentType::from(content_type);
408
409    if !status.is_client_error() && !status.is_server_error() {
410        let content = resp.text().await?;
411        match content_type {
412            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
413            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `Vec&lt;models::IssueView&gt;`"))),
414            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `Vec&lt;models::IssueView&gt;`")))),
415        }
416    } else {
417        let content = resp.text().await?;
418        let entity: Option<GetTodoProjectsByKeyIssuesError> = serde_json::from_str(&content).ok();
419        Err(Error::ResponseError(ResponseContent { status, content, entity }))
420    }
421}
422
423/// Returns ONE work item in full — its description included.  The list reads answer a board, and a board is a summary: the description is where the actual content of a work item lives — what an issue asks for, what an epic's acceptance criteria are — and no read on this surface returned it. The address is the one PATCH already accepts, so an item you can move is now an item you can read.  It reads the forge directly rather than filtering the org fan-out, then falls back to the index for a board the forge has never heard of — the same order, and the same reason, as GetProject: a row is one kind of thing however it came to exist, so a caller does not have to know which store it is in to fetch it.
424pub async fn get_todo_projects_by_key_issues_by_num(configuration: &configuration::Configuration, key: &str, num: i32) -> Result<models::IssueView, Error<GetTodoProjectsByKeyIssuesByNumError>> {
425    // add a prefix to parameters to efficiently prevent name collisions
426    let p_key = key;
427    let p_num = num;
428
429    let uri_str = format!("{}/v1/todo/projects/{key}/issues/{num}", configuration.base_path, key=crate::apis::urlencode(p_key), num=p_num);
430    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
431
432    if let Some(ref user_agent) = configuration.user_agent {
433        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
434    }
435    if let Some(ref token) = configuration.bearer_access_token {
436        req_builder = req_builder.bearer_auth(token.to_owned());
437    };
438
439    let req = req_builder.build()?;
440    let resp = configuration.client.execute(req).await?;
441
442    let status = resp.status();
443    let content_type = resp
444        .headers()
445        .get("content-type")
446        .and_then(|v| v.to_str().ok())
447        .unwrap_or("application/octet-stream");
448    let content_type = super::ContentType::from(content_type);
449
450    if !status.is_client_error() && !status.is_server_error() {
451        let content = resp.text().await?;
452        match content_type {
453            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
454            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::IssueView`"))),
455            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::IssueView`")))),
456        }
457    } else {
458        let content = resp.text().await?;
459        let entity: Option<GetTodoProjectsByKeyIssuesByNumError> = serde_json::from_str(&content).ok();
460        Err(Error::ResponseError(ResponseContent { status, content, entity }))
461    }
462}
463
464/// Summarises one room's work.  The room is opaque here and is deliberately not resolved: this package cannot say whether a room exists — apps/team owns that document — so an unknown room answers an EMPTY board rather than a 404. That is the honest answer and the useful one: a channel that has never had an item filed in it and a channel id that was mistyped both have no work, and inventing a distinction would require this surface to hold a second copy of the room list (HIP-0523 §2 forbids it, and it would drift the first time a room was renamed).  Tenancy is the validated principal's org and nothing else, so a caller cannot read another tenant's channel by naming its room.
465pub async fn get_todo_rooms_by_room(configuration: &configuration::Configuration, room: &str) -> Result<models::RoomWork, Error<GetTodoRoomsByRoomError>> {
466    // add a prefix to parameters to efficiently prevent name collisions
467    let p_room = room;
468
469    let uri_str = format!("{}/v1/todo/rooms/{room}", configuration.base_path, room=crate::apis::urlencode(p_room));
470    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
471
472    if let Some(ref user_agent) = configuration.user_agent {
473        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
474    }
475    if let Some(ref token) = configuration.bearer_access_token {
476        req_builder = req_builder.bearer_auth(token.to_owned());
477    };
478
479    let req = req_builder.build()?;
480    let resp = configuration.client.execute(req).await?;
481
482    let status = resp.status();
483    let content_type = resp
484        .headers()
485        .get("content-type")
486        .and_then(|v| v.to_str().ok())
487        .unwrap_or("application/octet-stream");
488    let content_type = super::ContentType::from(content_type);
489
490    if !status.is_client_error() && !status.is_server_error() {
491        let content = resp.text().await?;
492        match content_type {
493            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
494            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::RoomWork`"))),
495            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::RoomWork`")))),
496        }
497    } else {
498        let content = resp.text().await?;
499        let entity: Option<GetTodoRoomsByRoomError> = serde_json::from_str(&content).ok();
500        Err(Error::ResponseError(ResponseContent { status, content, entity }))
501    }
502}
503
504/// Answers 405. A todo board IS a repository on this deployment's forge, so creating, renaming and deleting one is a FORGE operation carried out with FORGE permissions.  Offering it here would put a second endpoint on the same object, guarded by this surface instead of by the forge — a weaker guard on the same thing. So the route exists and refuses, rather than 404ing: \"not this service's job\" and \"no such thing\" are different facts, and the body names the forge so a caller knows where the job IS done.  What this surface DOES own is the work on a board: list the boards you can see, read and file their issues, move a card between columns, and read the schedule a milestone is. Those are the routes beside this one.
505pub async fn patch_todo_projects_by_key(configuration: &configuration::Configuration, key: &str) -> Result<(), Error<PatchTodoProjectsByKeyError>> {
506    // add a prefix to parameters to efficiently prevent name collisions
507    let p_key = key;
508
509    let uri_str = format!("{}/v1/todo/projects/{key}", configuration.base_path, key=crate::apis::urlencode(p_key));
510    let mut req_builder = configuration.client.request(reqwest::Method::PATCH, &uri_str);
511
512    if let Some(ref user_agent) = configuration.user_agent {
513        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
514    }
515    if let Some(ref token) = configuration.bearer_access_token {
516        req_builder = req_builder.bearer_auth(token.to_owned());
517    };
518
519    let req = req_builder.build()?;
520    let resp = configuration.client.execute(req).await?;
521
522    let status = resp.status();
523
524    if !status.is_client_error() && !status.is_server_error() {
525        Ok(())
526    } else {
527        let content = resp.text().await?;
528        let entity: Option<PatchTodoProjectsByKeyError> = serde_json::from_str(&content).ok();
529        Err(Error::ResponseError(ResponseContent { status, content, entity }))
530    }
531}
532
533/// Edits a work item — rename it, rewrite it, move it to another column, or re-prioritise it. Absent fields are left alone.  MOVING A CARD IS A RELABEL. The column lives in the forge's label set, so the move replaces that set rather than writing a status column here that a forge-side change could contradict. Moving to `done` also CLOSES the issue on the forge, because a done card and an open issue are a contradiction.
534pub async fn patch_todo_projects_by_key_issues_by_num(configuration: &configuration::Configuration, key: &str, num: i32, issue_edit: models::IssueEdit) -> Result<models::IssueView, Error<PatchTodoProjectsByKeyIssuesByNumError>> {
535    // add a prefix to parameters to efficiently prevent name collisions
536    let p_key = key;
537    let p_num = num;
538    let p_issue_edit = issue_edit;
539
540    let uri_str = format!("{}/v1/todo/projects/{key}/issues/{num}", configuration.base_path, key=crate::apis::urlencode(p_key), num=p_num);
541    let mut req_builder = configuration.client.request(reqwest::Method::PATCH, &uri_str);
542
543    if let Some(ref user_agent) = configuration.user_agent {
544        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
545    }
546    if let Some(ref token) = configuration.bearer_access_token {
547        req_builder = req_builder.bearer_auth(token.to_owned());
548    };
549    req_builder = req_builder.json(&p_issue_edit);
550
551    let req = req_builder.build()?;
552    let resp = configuration.client.execute(req).await?;
553
554    let status = resp.status();
555    let content_type = resp
556        .headers()
557        .get("content-type")
558        .and_then(|v| v.to_str().ok())
559        .unwrap_or("application/octet-stream");
560    let content_type = super::ContentType::from(content_type);
561
562    if !status.is_client_error() && !status.is_server_error() {
563        let content = resp.text().await?;
564        match content_type {
565            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
566            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::IssueView`"))),
567            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::IssueView`")))),
568        }
569    } else {
570        let content = resp.text().await?;
571        let entity: Option<PatchTodoProjectsByKeyIssuesByNumError> = serde_json::from_str(&content).ok();
572        Err(Error::ResponseError(ResponseContent { status, content, entity }))
573    }
574}
575
576/// Answers 405. A todo board IS a repository on this deployment's forge, so creating, renaming and deleting one is a FORGE operation carried out with FORGE permissions.  Offering it here would put a second endpoint on the same object, guarded by this surface instead of by the forge — a weaker guard on the same thing. So the route exists and refuses, rather than 404ing: \"not this service's job\" and \"no such thing\" are different facts, and the body names the forge so a caller knows where the job IS done.  What this surface DOES own is the work on a board: list the boards you can see, read and file their issues, move a card between columns, and read the schedule a milestone is. Those are the routes beside this one.
577pub async fn post_todo_projects(configuration: &configuration::Configuration, ) -> Result<(), Error<PostTodoProjectsError>> {
578
579    let uri_str = format!("{}/v1/todo/projects", configuration.base_path);
580    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
581
582    if let Some(ref user_agent) = configuration.user_agent {
583        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
584    }
585    if let Some(ref token) = configuration.bearer_access_token {
586        req_builder = req_builder.bearer_auth(token.to_owned());
587    };
588
589    let req = req_builder.build()?;
590    let resp = configuration.client.execute(req).await?;
591
592    let status = resp.status();
593
594    if !status.is_client_error() && !status.is_server_error() {
595        Ok(())
596    } else {
597        let content = resp.text().await?;
598        let entity: Option<PostTodoProjectsError> = serde_json::from_str(&content).ok();
599        Err(Error::ResponseError(ResponseContent { status, content, entity }))
600    }
601}
602
603/// Opens a work item on the board — an issue on that repository on the deployment's forge, filed as YOU.  The column and priority are written as LABELS, which is what makes the card and the forge issue the same object: someone relabelling in the forge web UI has moved your card.
604pub async fn post_todo_projects_by_key_issues(configuration: &configuration::Configuration, key: &str, new_issue: models::NewIssue) -> Result<models::IssueView, Error<PostTodoProjectsByKeyIssuesError>> {
605    // add a prefix to parameters to efficiently prevent name collisions
606    let p_key = key;
607    let p_new_issue = new_issue;
608
609    let uri_str = format!("{}/v1/todo/projects/{key}/issues", configuration.base_path, key=crate::apis::urlencode(p_key));
610    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
611
612    if let Some(ref user_agent) = configuration.user_agent {
613        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
614    }
615    if let Some(ref token) = configuration.bearer_access_token {
616        req_builder = req_builder.bearer_auth(token.to_owned());
617    };
618    req_builder = req_builder.json(&p_new_issue);
619
620    let req = req_builder.build()?;
621    let resp = configuration.client.execute(req).await?;
622
623    let status = resp.status();
624    let content_type = resp
625        .headers()
626        .get("content-type")
627        .and_then(|v| v.to_str().ok())
628        .unwrap_or("application/octet-stream");
629    let content_type = super::ContentType::from(content_type);
630
631    if !status.is_client_error() && !status.is_server_error() {
632        let content = resp.text().await?;
633        match content_type {
634            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
635            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::IssueView`"))),
636            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::IssueView`")))),
637        }
638    } else {
639        let content = resp.text().await?;
640        let entity: Option<PostTodoProjectsByKeyIssuesError> = serde_json::from_str(&content).ok();
641        Err(Error::ResponseError(ResponseContent { status, content, entity }))
642    }
643}
644
645/// Takes an issue: it becomes yours and it moves to in_progress.  The holder is the CALLER, never an argument. \"Assign this to someone else\" is a different act with different authority, and it already exists as a PATCH; conflating them would let anyone hand work to anyone by naming them.  Claiming something already held by someone else is refused rather than silently taken — two agents on one issue is the failure this prevents, and a claim that quietly wins a race is worse than one that says no.
646pub async fn post_todo_projects_by_key_issues_by_num_claim(configuration: &configuration::Configuration, key: &str, num: i32) -> Result<models::IssueHit, Error<PostTodoProjectsByKeyIssuesByNumClaimError>> {
647    // add a prefix to parameters to efficiently prevent name collisions
648    let p_key = key;
649    let p_num = num;
650
651    let uri_str = format!("{}/v1/todo/projects/{key}/issues/{num}/claim", configuration.base_path, key=crate::apis::urlencode(p_key), num=p_num);
652    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
653
654    if let Some(ref user_agent) = configuration.user_agent {
655        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
656    }
657    if let Some(ref token) = configuration.bearer_access_token {
658        req_builder = req_builder.bearer_auth(token.to_owned());
659    };
660
661    let req = req_builder.build()?;
662    let resp = configuration.client.execute(req).await?;
663
664    let status = resp.status();
665    let content_type = resp
666        .headers()
667        .get("content-type")
668        .and_then(|v| v.to_str().ok())
669        .unwrap_or("application/octet-stream");
670    let content_type = super::ContentType::from(content_type);
671
672    if !status.is_client_error() && !status.is_server_error() {
673        let content = resp.text().await?;
674        match content_type {
675            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
676            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::IssueHit`"))),
677            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::IssueHit`")))),
678        }
679    } else {
680        let content = resp.text().await?;
681        let entity: Option<PostTodoProjectsByKeyIssuesByNumClaimError> = serde_json::from_str(&content).ok();
682        Err(Error::ResponseError(ResponseContent { status, content, entity }))
683    }
684}
685