app_store_connect/
bundle_api.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7use crate::{profile_api::ProfilesResponse, AppStoreConnectClient, Result};
8use serde::{Deserialize, Serialize};
9
10const APPLE_BUNDLE_IDS_URL: &str = "https://api.appstoreconnect.apple.com/v1/bundleIds";
11const APPLE_BUNDLE_CAPABILITIES_URL: &str =
12    "https://api.appstoreconnect.apple.com/v1/bundleIdCapabilities";
13
14impl AppStoreConnectClient {
15    pub fn register_bundle_id(&self, identifier: &str, name: &str) -> Result<BundleIdResponse> {
16        let token = self.get_token()?;
17        let body = BundleIdCreateRequest {
18            data: BundleIdCreateRequestData {
19                attributes: BundleIdCreateRequestAttributes {
20                    identifier: identifier.into(),
21                    name: name.into(),
22                    platform: "UNIVERSAL".into(),
23                },
24                r#type: "bundleIds".into(),
25            },
26        };
27        let req = self
28            .client
29            .post(APPLE_BUNDLE_IDS_URL)
30            .bearer_auth(token)
31            .header("Accept", "application/json")
32            .header("Content-Type", "application/json")
33            .json(&body);
34        Ok(self.send_request(req)?.json()?)
35    }
36
37    pub fn list_bundle_ids(&self) -> Result<BundleIdsResponse> {
38        let token = self.get_token()?;
39        let req = self
40            .client
41            .get(APPLE_BUNDLE_IDS_URL)
42            .bearer_auth(token)
43            .header("Accept", "application/json");
44        Ok(self.send_request(req)?.json()?)
45    }
46
47    pub fn get_bundle_id(&self, id: &str) -> Result<BundleIdResponse> {
48        let token = self.get_token()?;
49        let req = self
50            .client
51            .get(format!("{APPLE_BUNDLE_IDS_URL}/{id}"))
52            .bearer_auth(token)
53            .header("Accept", "application/json");
54        Ok(self.send_request(req)?.json()?)
55    }
56
57    pub fn list_bundle_profiles(&self, id: &str) -> Result<ProfilesResponse> {
58        let token = self.get_token()?;
59        let req = self
60            .client
61            .get(format!("{APPLE_BUNDLE_IDS_URL}/{id}/profiles"))
62            .bearer_auth(token)
63            .header("Accept", "application/json");
64        Ok(self.send_request(req)?.json()?)
65    }
66
67    pub fn list_bundle_capabilities(&self, id: &str) -> Result<BundleCapabilitiesResponse> {
68        let token = self.get_token()?;
69        let req = self
70            .client
71            .get(format!("{APPLE_BUNDLE_IDS_URL}/{id}/bundleIdCapabilities"))
72            .bearer_auth(token)
73            .header("Accept", "application/json");
74        Ok(self.send_request(req)?.json()?)
75    }
76
77    pub fn enable_bundle_id_capability(
78        &self,
79        id: &str,
80        capability: BundleIdCapabilityCreateRequestDataAttributes,
81    ) -> Result<()> {
82        let token = self.get_token()?;
83
84        let body = BundleIdCapabilityCreateRequest {
85            data: BundleIdCapabilityCreateRequestData {
86                attributes: capability,
87                relationships: BundleIdCapabilityCreateRequestDataRelationships {
88                    bundle_id: BundleIdCapabilityCreateRequestDataRelationshipBundleId {
89                        data: BundleIdCapabilityCreateRequestDataRelationshipBundleIdData {
90                            id: id.to_string(),
91                            r#type: "bundleIds".to_string(),
92                        },
93                    },
94                },
95                r#type: "bundleIdCapabilities".to_string(),
96            },
97        };
98
99        let req = self
100            .client
101            .post(APPLE_BUNDLE_CAPABILITIES_URL)
102            .bearer_auth(token)
103            .header("Accept", "application/json")
104            .json(&body);
105        self.send_request(req)?;
106        Ok(())
107    }
108
109    pub fn delete_bundle_id(&self, id: &str) -> Result<()> {
110        let token = self.get_token()?;
111        let req = self
112            .client
113            .delete(format!("{APPLE_BUNDLE_IDS_URL}/{id}"))
114            .bearer_auth(token);
115        self.send_request(req)?;
116        Ok(())
117    }
118}
119
120#[derive(Debug, Serialize)]
121#[serde(rename_all = "camelCase")]
122pub struct BundleIdCreateRequest {
123    pub data: BundleIdCreateRequestData,
124}
125
126#[derive(Debug, Serialize)]
127#[serde(rename_all = "camelCase")]
128pub struct BundleIdCreateRequestData {
129    pub attributes: BundleIdCreateRequestAttributes,
130    pub r#type: String,
131}
132
133#[derive(Debug, Serialize)]
134#[serde(rename_all = "camelCase")]
135pub struct BundleIdCreateRequestAttributes {
136    pub identifier: String,
137    pub name: String,
138    pub platform: String,
139}
140
141#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
142pub enum BundleIdPlatform {
143    Ios,
144    MacOs,
145}
146
147impl std::fmt::Display for BundleIdPlatform {
148    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
149        let s = match self {
150            Self::Ios => "IOS",
151            Self::MacOs => "MAC_OS",
152        };
153        write!(f, "{s}")
154    }
155}
156
157#[derive(Debug, Deserialize)]
158#[serde(rename_all = "camelCase")]
159pub struct BundleIdResponse {
160    pub data: BundleId,
161}
162
163#[derive(Debug, Deserialize)]
164#[serde(rename_all = "camelCase")]
165pub struct BundleIdsResponse {
166    pub data: Vec<BundleId>,
167}
168
169#[derive(Debug, Deserialize)]
170#[serde(rename_all = "camelCase")]
171pub struct BundleId {
172    pub attributes: BundleIdAttributes,
173    pub id: String,
174}
175
176#[derive(Debug, Deserialize)]
177#[serde(rename_all = "camelCase")]
178pub struct BundleIdAttributes {
179    pub identifier: String,
180    pub name: String,
181    pub platform: String,
182    pub seed_id: String,
183}
184
185#[derive(Debug, Deserialize)]
186pub struct BundleCapabilitiesResponse {
187    pub data: Vec<BundleCapability>,
188}
189
190#[derive(Debug, Deserialize)]
191pub struct BundleCapability {
192    pub attributes: BundleCapabilityAttributes,
193    pub id: String,
194}
195
196#[derive(Debug, Deserialize, Serialize)]
197#[serde(rename_all = "camelCase")]
198pub struct BundleCapabilityAttributes {
199    pub capability_type: String,
200}
201
202#[derive(Debug, Serialize)]
203#[serde(rename_all = "camelCase")]
204pub struct BundleIdCapabilityCreateRequest {
205    data: BundleIdCapabilityCreateRequestData,
206}
207
208#[derive(Debug, Serialize)]
209#[serde(rename_all = "camelCase")]
210pub struct BundleIdCapabilityCreateRequestData {
211    attributes: BundleIdCapabilityCreateRequestDataAttributes,
212    relationships: BundleIdCapabilityCreateRequestDataRelationships,
213    r#type: String,
214}
215
216#[derive(Debug, Serialize)]
217#[serde(rename_all = "camelCase")]
218pub struct BundleIdCapabilityCreateRequestDataAttributes {
219    pub capability_type: String,
220}
221
222#[derive(Debug, Serialize)]
223#[serde(rename_all = "camelCase")]
224pub struct BundleIdCapabilityCreateRequestDataRelationships {
225    bundle_id: BundleIdCapabilityCreateRequestDataRelationshipBundleId,
226}
227
228#[derive(Debug, Serialize)]
229#[serde(rename_all = "camelCase")]
230pub struct BundleIdCapabilityCreateRequestDataRelationshipBundleId {
231    data: BundleIdCapabilityCreateRequestDataRelationshipBundleIdData,
232}
233
234#[derive(Debug, Serialize)]
235#[serde(rename_all = "camelCase")]
236pub struct BundleIdCapabilityCreateRequestDataRelationshipBundleIdData {
237    id: String,
238    r#type: String,
239}