amazon_spapi/client/
config.rs

1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3use std::fs;
4
5/// Configuration for the Selling Partner API client.
6#[derive(Debug, Default, Serialize, Deserialize, Clone)]
7pub struct SpapiConfig {
8    /// The client ID provided by Amazon.
9    pub client_id: String,
10    /// The client secret provided by Amazon.
11    pub client_secret: String,
12    /// The refresh token for obtaining access tokens.
13    pub refresh_token: String,
14    /// The AWS region for the Selling Partner API.
15    pub region: Region,
16    /// Whether to use the sandbox environment.
17    pub sandbox: bool,
18    /// Custom user agent string. If not set, a default user agent will be used.
19    pub user_agent: Option<String>,
20    /// Request timeout in seconds. Defaults to 30 seconds if not set.
21    pub timeout_sec: Option<u64>,
22    /// Rate limit safety factor. Defaults to 1.1 if not set.
23    pub rate_limit_factor: Option<f64>,
24    /// Optional proxy URL for routing requests through a proxy server. 
25    pub proxy: Option<String>,
26    /// Number of retry attempts for requests that receive a 429 status code. None or 0 means no retries.
27    pub retry_count: Option<usize>,
28}
29
30/// AWS Region for the Selling Partner API.
31#[derive(Debug, Serialize, Deserialize, Clone)]
32pub enum Region {
33    #[serde(rename = "us-east-1")]
34    NorthAmerica,
35    #[serde(rename = "eu-west-1")]
36    Europe,
37    #[serde(rename = "us-west-2")]
38    FarEast,
39}
40
41impl Default for Region {
42    fn default() -> Self {
43        Region::NorthAmerica
44    }
45}
46
47impl Region {
48    pub fn from_str(s: &str) -> Result<Self> {
49        match s {
50            "na" | "us-east-1" => Ok(Region::NorthAmerica),
51            "eu" | "eu-west-1" => Ok(Region::Europe),
52            "fe" | "us-west-2" => Ok(Region::FarEast),
53            _ => Err(anyhow::anyhow!("Invalid region string: {}", s)),
54        }
55    }
56
57    pub fn to_str(&self) -> &str {
58        match self {
59            Region::NorthAmerica => "us-east-1",
60            Region::Europe => "eu-west-1",
61            Region::FarEast => "us-west-2",
62        }
63    }
64}
65
66impl SpapiConfig {
67    pub fn from_env() -> Result<Self> {
68        let client_id = std::env::var("SPAPI_CLIENT_ID")
69            .map_err(|_| anyhow::anyhow!("SPAPI_CLIENT_ID environment variable is not set"))?;
70        let client_secret = std::env::var("SPAPI_CLIENT_SECRET")
71            .map_err(|_| anyhow::anyhow!("SPAPI_CLIENT_SECRET environment variable is not set"))?;
72        let refresh_token = std::env::var("SPAPI_REFRESH_TOKEN")
73            .map_err(|_| anyhow::anyhow!("SPAPI_REFRESH_TOKEN environment variable is not set"))?;
74        let region = std::env::var("SPAPI_REGION")
75            .map_err(|_| anyhow::anyhow!("SPAPI_REGION environment variable is not set"))?;
76        let sandbox = std::env::var("SPAPI_SANDBOX").map_err(|_| {
77            anyhow::anyhow!("SPAPI_SANDBOX environment variable is not set or invalid")
78        })?;
79        let sandbox = sandbox == "true" || sandbox == "1";
80        Ok(Self {
81            client_id,
82            client_secret,
83            refresh_token,
84            region: Region::from_str(&region)?,
85            sandbox,
86            user_agent: None,
87            timeout_sec: Some(30),
88            rate_limit_factor: None,
89            proxy: None,
90            retry_count: None,
91        })
92    }
93
94    pub fn from_file(path: &str) -> Result<Self> {
95        let content = fs::read_to_string(path)?;
96        let config: Self = toml::from_str(&content)?;
97        Ok(config)
98    }
99
100    pub fn from_default_file() -> Result<Self> {
101        Self::from_file("config.toml")
102    }
103}