11use crate :: constants:: {
2+ ENV_ACCESS_TOKEN , ENV_CLIENT_ID , ENV_CLIENT_SECRET , ENV_REDIRECT_URI , ENV_REFRESH_TOKEN ,
23 TOML_ACCESS_TOKEN , TOML_CLIENT_ID , TOML_CLIENT_SECRET , TOML_REDIRECT_URI , TOML_REFRESH_TOKEN ,
34} ;
45use std:: env;
@@ -7,6 +8,7 @@ use std::io;
78use std:: path:: { Path , PathBuf } ;
89use toml:: Value ;
910
11+ #[ derive( Debug ) ]
1012pub struct Config {
1113 pub client_id : String ,
1214 pub client_secret : String ,
@@ -16,6 +18,15 @@ pub struct Config {
1618}
1719
1820impl Config {
21+ pub fn load ( ) -> io:: Result < Self > {
22+ if let Some ( config) = Self :: from_env ( ) ? {
23+ return Ok ( config) ;
24+ }
25+
26+ let config_path = global_config_path ( ) ?;
27+ Self :: from_path ( & config_path)
28+ }
29+
1930 pub fn from_path ( path : impl AsRef < Path > ) -> io:: Result < Self > {
2031 let path = path. as_ref ( ) ;
2132 let content = fs:: read_to_string ( path) . map_err ( |err| {
@@ -73,6 +84,57 @@ impl Config {
7384 Ok ( ( ) )
7485 }
7586
87+ fn from_env ( ) -> io:: Result < Option < Self > > {
88+ let entries = [
89+ ENV_CLIENT_ID ,
90+ ENV_CLIENT_SECRET ,
91+ ENV_REDIRECT_URI ,
92+ ENV_ACCESS_TOKEN ,
93+ ENV_REFRESH_TOKEN ,
94+ ]
95+ . map ( |key| {
96+ (
97+ key,
98+ env:: var ( key) . ok ( ) . filter ( |value| !value. trim ( ) . is_empty ( ) ) ,
99+ )
100+ } ) ;
101+
102+ if entries. iter ( ) . all ( |( _, value) | value. is_none ( ) ) {
103+ return Ok ( None ) ;
104+ }
105+
106+ let [
107+ ( _, Some ( client_id) ) ,
108+ ( _, Some ( client_secret) ) ,
109+ ( _, Some ( redirect_uri) ) ,
110+ ( _, Some ( access_token) ) ,
111+ ( _, Some ( refresh_token) ) ,
112+ ] = entries
113+ else {
114+ let missing = entries
115+ . iter ( )
116+ . filter ( |( _, value) | value. is_none ( ) )
117+ . map ( |( env_key, _) | * env_key)
118+ . collect :: < Vec < _ > > ( )
119+ . join ( ", " ) ;
120+
121+ return Err ( io:: Error :: new (
122+ io:: ErrorKind :: InvalidInput ,
123+ format ! (
124+ "partial PUDDLE_* environment configuration detected. Missing or empty: {missing}"
125+ ) ,
126+ ) ) ;
127+ } ;
128+
129+ Ok ( Some ( Self {
130+ client_id,
131+ client_secret,
132+ redirect_uri,
133+ access_token,
134+ refresh_token,
135+ } ) )
136+ }
137+
76138 fn required_toml_string ( table : & toml:: Table , key : & str , path : & Path ) -> io:: Result < String > {
77139 let value = table. get ( key) . ok_or_else ( || {
78140 io:: Error :: new (
0 commit comments