use std::sync::Arc;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use crate::config::Config;
#[derive(Clone, Debug)]
pub struct TemplatesSvc(pub(crate) Arc<Config>);
impl TemplatesSvc {
#[maybe_async::maybe_async]
pub async fn list(
&self,
options: ListTemplatesOptions,
) -> crate::Result<ListTemplatesResponse> {
let mut request = self.0.build(Method::GET, "/templates");
if let Some(project_id) = options.project_id {
request = request.query(&[("project_id", project_id.to_string())]);
}
if let Some(per_page) = options.per_page {
request = request.query(&[("per_page", per_page.to_string())]);
}
if let Some(page) = options.page {
request = request.query(&[("page", page.to_string())]);
}
let response = self.0.send(request).await?;
let wrapper = response.json::<ListTemplatesResponseWrapper>().await?;
Ok(wrapper.data)
}
#[maybe_async::maybe_async]
pub async fn create(
&self,
options: CreateTemplateOptions,
) -> crate::Result<CreateTemplateResponse> {
let request = self.0.build(Method::POST, "/templates").json(&options);
let response = self.0.send(request).await?;
let wrapper = response.json::<CreateTemplateResponseWrapper>().await?;
Ok(wrapper.data)
}
#[maybe_async::maybe_async]
pub async fn get(&self, slug: &str, project_id: Option<u64>) -> crate::Result<TemplateDetail> {
let path = format!("/templates/{slug}");
let mut request = self.0.build(Method::GET, &path);
if let Some(project_id) = project_id {
request = request.query(&[("project_id", project_id.to_string())]);
}
let response = self.0.send(request).await?;
let wrapper = response.json::<ShowTemplateResponseWrapper>().await?;
Ok(wrapper.data)
}
#[maybe_async::maybe_async]
pub async fn update(
&self,
slug: &str,
options: UpdateTemplateOptions,
) -> crate::Result<UpdateTemplateResponse> {
let path = format!("/templates/{slug}");
let request = self.0.build(Method::PUT, &path).json(&options);
let response = self.0.send(request).await?;
let wrapper = response.json::<UpdateTemplateResponseWrapper>().await?;
Ok(wrapper.data)
}
#[maybe_async::maybe_async]
pub async fn delete(&self, slug: &str, project_id: Option<u64>) -> crate::Result<()> {
let path = format!("/templates/{slug}");
let mut request = self.0.build(Method::DELETE, &path);
if let Some(project_id) = project_id {
request = request.query(&[("project_id", project_id.to_string())]);
}
self.0.send(request).await?;
Ok(())
}
#[maybe_async::maybe_async]
pub async fn get_merge_tags(
&self,
slug: &str,
project_id: Option<u64>,
version: Option<u32>,
) -> crate::Result<MergeTagsList> {
let path = format!("/templates/{slug}/merge-tags");
let mut request = self.0.build(Method::GET, &path);
if let Some(project_id) = project_id {
request = request.query(&[("project_id", project_id.to_string())]);
}
if let Some(version) = version {
request = request.query(&[("version", version.to_string())]);
}
let response = self.0.send(request).await?;
let wrapper = response.json::<GetMergeTagsResponseWrapper>().await?;
Ok(wrapper.data)
}
#[maybe_async::maybe_async]
pub async fn get_html(
&self,
project_id: u64,
slug: &str,
) -> crate::Result<GetTemplateHtmlResponse> {
let mut request = self.0.build(Method::GET, "/templates/html");
request = request.query(&[
("project_id", project_id.to_string()),
("slug", slug.to_string()),
]);
let response = self.0.send(request).await?;
let wrapper = response.json::<GetTemplateHtmlResponseWrapper>().await?;
Ok(wrapper.data)
}
}
#[must_use]
#[derive(Debug, Default, Clone)]
pub struct ListTemplatesOptions {
project_id: Option<u64>,
per_page: Option<u32>,
page: Option<u32>,
}
impl ListTemplatesOptions {
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn project_id(mut self, project_id: u64) -> Self {
self.project_id = Some(project_id);
self
}
#[inline]
pub fn per_page(mut self, per_page: u32) -> Self {
self.per_page = Some(per_page);
self
}
#[inline]
pub fn page(mut self, page: u32) -> Self {
self.page = Some(page);
self
}
}
#[must_use]
#[derive(Debug, Clone, Serialize)]
pub struct CreateTemplateOptions {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
html: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
json: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
project_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
folder_id: Option<u64>,
}
impl CreateTemplateOptions {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
html: None,
json: None,
project_id: None,
folder_id: None,
}
}
#[inline]
pub fn with_html(mut self, html: impl Into<String>) -> Self {
self.html = Some(html.into());
self
}
#[inline]
pub fn with_json(mut self, json: impl Into<String>) -> Self {
self.json = Some(json.into());
self
}
#[inline]
pub fn with_project_id(mut self, project_id: u64) -> Self {
self.project_id = Some(project_id);
self
}
#[inline]
pub fn with_folder_id(mut self, folder_id: u64) -> Self {
self.folder_id = Some(folder_id);
self
}
}
#[must_use]
#[derive(Debug, Default, Clone, Serialize)]
pub struct UpdateTemplateOptions {
#[serde(skip_serializing_if = "Option::is_none")]
project_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
html: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
json: Option<String>,
}
impl UpdateTemplateOptions {
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn with_project_id(mut self, project_id: u64) -> Self {
self.project_id = Some(project_id);
self
}
#[inline]
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
#[inline]
pub fn with_html(mut self, html: impl Into<String>) -> Self {
self.html = Some(html.into());
self
}
#[inline]
pub fn with_json(mut self, json: impl Into<String>) -> Self {
self.json = Some(json.into());
self
}
}
#[derive(Debug, Deserialize)]
struct ListTemplatesResponseWrapper {
#[allow(dead_code)]
message: String,
data: ListTemplatesResponse,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ListTemplatesResponse {
pub templates: Vec<Template>,
pub pagination: TemplatePagination,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Template {
pub id: u64,
pub name: String,
pub slug: String,
pub project_id: u64,
pub folder_id: u64,
pub created_at: String,
pub updated_at: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct TemplatePagination {
pub total: u64,
pub per_page: u32,
pub current_page: u32,
pub last_page: u32,
}
#[derive(Debug, Deserialize)]
struct CreateTemplateResponseWrapper {
#[allow(dead_code)]
message: String,
data: CreateTemplateResponse,
}
#[derive(Debug, Clone, Deserialize)]
pub struct CreateTemplateResponse {
pub id: u64,
pub name: String,
pub slug: String,
pub project_id: u64,
pub folder_id: u64,
pub active_version: u32,
#[serde(default)]
pub merge_tags: Vec<MergeTag>,
pub created_at: String,
}
#[derive(Debug, Deserialize)]
struct ShowTemplateResponseWrapper {
#[allow(dead_code)]
message: String,
data: TemplateDetail,
}
#[derive(Debug, Clone, Deserialize)]
pub struct TemplateDetail {
pub id: u64,
pub name: String,
pub slug: String,
pub project_id: u64,
pub folder_id: u64,
pub active_version: Option<u32>,
pub versions_count: u32,
#[serde(default)]
pub html: Option<String>,
#[serde(default)]
pub json: Option<String>,
pub created_at: String,
pub updated_at: String,
}
#[derive(Debug, Deserialize)]
struct UpdateTemplateResponseWrapper {
#[allow(dead_code)]
message: String,
data: UpdateTemplateResponse,
}
#[derive(Debug, Clone, Deserialize)]
pub struct UpdateTemplateResponse {
pub id: u64,
pub name: String,
pub slug: String,
pub project_id: u64,
pub folder_id: u64,
pub active_version: u32,
#[serde(default)]
pub merge_tags: Vec<MergeTag>,
pub created_at: String,
pub updated_at: String,
}
#[derive(Debug, Deserialize)]
struct GetMergeTagsResponseWrapper {
#[allow(dead_code)]
message: String,
data: MergeTagsList,
}
#[derive(Debug, Clone, Deserialize)]
pub struct MergeTagsList {
pub project_id: u64,
pub template_slug: String,
pub version: u32,
pub merge_tags: Vec<MergeTag>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct MergeTag {
pub key: String,
pub required: bool,
#[serde(rename = "type", default)]
pub merge_tag_type: Option<String>,
#[serde(default)]
pub children: Option<Vec<MergeTagChild>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct MergeTagChild {
pub key: String,
#[serde(rename = "type", default)]
pub merge_tag_type: Option<String>,
}
#[derive(Debug, Deserialize)]
struct GetTemplateHtmlResponseWrapper {
data: GetTemplateHtmlResponse,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GetTemplateHtmlResponse {
pub html: String,
pub merge_tags: Vec<TemplateHtmlMergeTag>,
#[serde(default)]
pub subject: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct TemplateHtmlMergeTag {
pub key: String,
pub name: String,
pub required: bool,
}