use anyhow::{anyhow, Result};
use serde::Deserialize;
use serde_json::json;
use crate::client::{AppStoreConnectClient, AscResponse, BASE_URL};
#[derive(Debug, Deserialize, Clone)]
pub struct AppStoreVersionData {
pub id: String,
#[serde(rename = "type")]
pub data_type: String,
pub attributes: AppStoreVersionAttributes,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AppStoreVersionAttributes {
pub version_string: Option<String>,
pub app_store_state: Option<String>,
pub platform: Option<String>,
pub release_type: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct AppStoreVersionSubmissionData {
pub id: String,
#[serde(rename = "type")]
pub data_type: String,
}
impl AppStoreConnectClient {
pub async fn create_app_store_version(
&self,
app_id: &str,
version_string: &str,
platform: &str,
) -> Result<AppStoreVersionData> {
let token = self.generate_token()?;
let body = json!({
"data": {
"type": "appStoreVersions",
"attributes": {
"versionString": version_string,
"platform": platform,
"releaseType": "MANUAL"
},
"relationships": {
"app": {
"data": {
"type": "apps",
"id": app_id
}
}
}
}
});
let response = self.client
.post(format!("{}/appStoreVersions", BASE_URL))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.json(&body)
.send()
.await
.map_err(|e| anyhow!("Failed to create App Store version: {}", e))?;
let status = response.status();
if status.is_success() {
let result: AscResponse<AppStoreVersionData> = response.json().await
.map_err(|e| anyhow!("Failed to parse version response: {}", e))?;
log::info!("Created App Store version {} for app {}", version_string, app_id);
Ok(result.data)
} else {
let error_body = response.text().await.unwrap_or_default();
Err(anyhow!("{}", Self::parse_error(status, &error_body)))
}
}
pub async fn submit_for_review(&self, version_id: &str) -> Result<AppStoreVersionSubmissionData> {
let token = self.generate_token()?;
let body = json!({
"data": {
"type": "appStoreVersionSubmissions",
"relationships": {
"appStoreVersion": {
"data": {
"type": "appStoreVersions",
"id": version_id
}
}
}
}
});
let response = self.client
.post(format!("{}/appStoreVersionSubmissions", BASE_URL))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.json(&body)
.send()
.await
.map_err(|e| anyhow!("Failed to submit for review: {}", e))?;
let status = response.status();
if status.is_success() {
let result: AscResponse<AppStoreVersionSubmissionData> = response.json().await
.map_err(|e| anyhow!("Failed to parse submission response: {}", e))?;
log::info!("Submitted version {} for review", version_id);
Ok(result.data)
} else {
let error_body = response.text().await.unwrap_or_default();
Err(anyhow!("{}", Self::parse_error(status, &error_body)))
}
}
}