Skip to main content

systemprompt_models/api/responses/
specialized.rs

1//! Specialized response envelopes for `201 Created`, `202 Accepted`,
2//! plain success messages, and HATEOAS-style discovery payloads.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use indexmap::IndexMap;
8use serde::{Deserialize, Serialize};
9
10use super::envelopes::ResponseMeta;
11
12#[derive(Debug, Serialize, Deserialize)]
13pub struct SuccessResponse {
14    pub message: String,
15
16    pub meta: ResponseMeta,
17}
18
19impl SuccessResponse {
20    pub fn new(message: impl Into<String>) -> Self {
21        Self {
22            message: message.into(),
23            meta: ResponseMeta::new(),
24        }
25    }
26}
27
28#[derive(Debug, Serialize, Deserialize)]
29pub struct CreatedResponse<T>
30where
31    T: 'static,
32{
33    pub data: T,
34
35    pub meta: ResponseMeta,
36
37    pub location: String,
38}
39
40impl<T: Serialize + 'static> CreatedResponse<T> {
41    pub fn new(data: T, location: impl Into<String>) -> Self {
42        Self {
43            data,
44            meta: ResponseMeta::new(),
45            location: location.into(),
46        }
47    }
48}
49
50#[derive(Debug, Serialize, Deserialize)]
51pub struct AcceptedResponse {
52    pub message: String,
53
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub job_id: Option<String>,
56
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub status_url: Option<String>,
59
60    pub meta: ResponseMeta,
61}
62
63impl AcceptedResponse {
64    pub fn new(message: impl Into<String>) -> Self {
65        Self {
66            message: message.into(),
67            job_id: None,
68            status_url: None,
69            meta: ResponseMeta::new(),
70        }
71    }
72
73    #[must_use]
74    pub fn with_job(mut self, job_id: impl Into<String>, status_url: impl Into<String>) -> Self {
75        self.job_id = Some(job_id.into());
76        self.status_url = Some(status_url.into());
77        self
78    }
79}
80
81#[derive(Debug, Serialize, Deserialize)]
82pub struct Link {
83    pub href: String,
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub title: Option<String>,
86}
87
88impl Link {
89    pub fn new(href: impl Into<String>, title: Option<String>) -> Self {
90        Self {
91            href: href.into(),
92            title,
93        }
94    }
95}
96
97#[derive(Debug, Serialize, Deserialize)]
98pub struct DiscoveryResponse<T>
99where
100    T: 'static,
101{
102    pub data: T,
103    pub meta: ResponseMeta,
104    #[serde(rename = "_links")]
105    pub links: IndexMap<String, Link>,
106}
107
108impl<T: Serialize + 'static> DiscoveryResponse<T> {
109    pub fn new(data: T, links: IndexMap<String, Link>) -> Self {
110        Self {
111            data,
112            meta: ResponseMeta::new(),
113            links,
114        }
115    }
116
117    #[must_use]
118    pub fn with_meta(mut self, meta: ResponseMeta) -> Self {
119        self.meta = meta;
120        self
121    }
122}