claude_wrapper/command/
auth.rs1use crate::Claude;
2use crate::command::ClaudeCommand;
3use crate::error::Result;
4use crate::exec::{self, CommandOutput};
5
6#[derive(Debug, Clone, Default)]
21pub struct AuthStatusCommand {
22 json: bool,
23}
24
25impl AuthStatusCommand {
26 #[must_use]
28 pub fn new() -> Self {
29 Self { json: true }
30 }
31
32 #[must_use]
34 pub fn text(mut self) -> Self {
35 self.json = false;
36 self
37 }
38
39 #[cfg(all(feature = "json", feature = "async"))]
41 pub async fn execute_json(&self, claude: &Claude) -> Result<crate::types::AuthStatus> {
42 let mut cmd = self.clone();
43 cmd.json = true;
44
45 let output = exec::run_claude(claude, cmd.args()).await?;
46
47 serde_json::from_str(&output.stdout).map_err(|e| crate::error::Error::Json {
48 message: format!("failed to parse auth status: {e}"),
49 source: e,
50 })
51 }
52
53 #[cfg(all(feature = "sync", feature = "json"))]
55 pub fn execute_json_sync(&self, claude: &Claude) -> Result<crate::types::AuthStatus> {
56 let mut cmd = self.clone();
57 cmd.json = true;
58
59 let output = exec::run_claude_sync(claude, cmd.args())?;
60
61 serde_json::from_str(&output.stdout).map_err(|e| crate::error::Error::Json {
62 message: format!("failed to parse auth status: {e}"),
63 source: e,
64 })
65 }
66}
67
68impl ClaudeCommand for AuthStatusCommand {
69 type Output = CommandOutput;
70
71 fn args(&self) -> Vec<String> {
72 let mut args = vec!["auth".to_string(), "status".to_string()];
73 if self.json {
74 args.push("--json".to_string());
75 } else {
76 args.push("--text".to_string());
77 }
78 args
79 }
80
81 #[cfg(feature = "async")]
82 async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
83 exec::run_claude(claude, self.args()).await
84 }
85}
86
87#[derive(Debug, Clone, Default)]
104pub struct AuthLoginCommand {
105 email: Option<String>,
106 sso: Option<String>,
107}
108
109impl AuthLoginCommand {
110 #[must_use]
112 pub fn new() -> Self {
113 Self::default()
114 }
115
116 #[must_use]
118 pub fn email(mut self, email: impl Into<String>) -> Self {
119 self.email = Some(email.into());
120 self
121 }
122
123 #[must_use]
125 pub fn sso(mut self, provider: impl Into<String>) -> Self {
126 self.sso = Some(provider.into());
127 self
128 }
129}
130
131impl ClaudeCommand for AuthLoginCommand {
132 type Output = CommandOutput;
133
134 fn args(&self) -> Vec<String> {
135 let mut args = vec!["auth".to_string(), "login".to_string()];
136 if let Some(ref email) = self.email {
137 args.push("--email".to_string());
138 args.push(email.clone());
139 }
140 if let Some(ref sso) = self.sso {
141 args.push("--sso".to_string());
142 args.push(sso.clone());
143 }
144 args
145 }
146
147 #[cfg(feature = "async")]
148 async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
149 exec::run_claude(claude, self.args()).await
150 }
151}
152
153#[derive(Debug, Clone, Default)]
167pub struct AuthLogoutCommand;
168
169impl AuthLogoutCommand {
170 #[must_use]
172 pub fn new() -> Self {
173 Self
174 }
175}
176
177impl ClaudeCommand for AuthLogoutCommand {
178 type Output = CommandOutput;
179
180 fn args(&self) -> Vec<String> {
181 vec!["auth".to_string(), "logout".to_string()]
182 }
183
184 #[cfg(feature = "async")]
185 async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
186 exec::run_claude(claude, self.args()).await
187 }
188}
189
190#[derive(Debug, Clone, Default)]
204pub struct SetupTokenCommand;
205
206impl SetupTokenCommand {
207 #[must_use]
209 pub fn new() -> Self {
210 Self
211 }
212}
213
214impl ClaudeCommand for SetupTokenCommand {
215 type Output = CommandOutput;
216
217 fn args(&self) -> Vec<String> {
218 vec!["setup-token".to_string()]
219 }
220
221 #[cfg(feature = "async")]
222 async fn execute(&self, claude: &Claude) -> Result<CommandOutput> {
223 exec::run_claude(claude, self.args()).await
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230
231 #[test]
232 fn test_auth_status_args() {
233 let cmd = AuthStatusCommand::new();
234 assert_eq!(cmd.args(), vec!["auth", "status", "--json"]);
235 }
236
237 #[test]
238 fn test_auth_status_text() {
239 let cmd = AuthStatusCommand::new().text();
240 assert_eq!(cmd.args(), vec!["auth", "status", "--text"]);
241 }
242
243 #[test]
244 fn test_auth_login_default() {
245 let cmd = AuthLoginCommand::new();
246 assert_eq!(cmd.args(), vec!["auth", "login"]);
247 }
248
249 #[test]
250 fn test_auth_login_with_email() {
251 let cmd = AuthLoginCommand::new().email("user@example.com");
252 assert_eq!(
253 cmd.args(),
254 vec!["auth", "login", "--email", "user@example.com"]
255 );
256 }
257
258 #[test]
259 fn test_auth_login_with_sso() {
260 let cmd = AuthLoginCommand::new().sso("okta");
261 assert_eq!(cmd.args(), vec!["auth", "login", "--sso", "okta"]);
262 }
263
264 #[test]
265 fn test_auth_logout() {
266 let cmd = AuthLogoutCommand::new();
267 assert_eq!(cmd.args(), vec!["auth", "logout"]);
268 }
269
270 #[test]
271 fn test_setup_token() {
272 let cmd = SetupTokenCommand::new();
273 assert_eq!(cmd.args(), vec!["setup-token"]);
274 }
275}