Skip to main content

codex_wrapper/command/
login.rs

1use crate::Codex;
2use crate::command::CodexCommand;
3use crate::error::Result;
4use crate::exec::{self, CommandOutput};
5
6#[derive(Debug, Clone, Default)]
7pub struct LoginCommand {
8    config_overrides: Vec<String>,
9    enabled_features: Vec<String>,
10    disabled_features: Vec<String>,
11    with_api_key: bool,
12    device_auth: bool,
13}
14
15impl LoginCommand {
16    #[must_use]
17    pub fn new() -> Self {
18        Self::default()
19    }
20
21    #[must_use]
22    pub fn config(mut self, key_value: impl Into<String>) -> Self {
23        self.config_overrides.push(key_value.into());
24        self
25    }
26
27    #[must_use]
28    pub fn enable(mut self, feature: impl Into<String>) -> Self {
29        self.enabled_features.push(feature.into());
30        self
31    }
32
33    #[must_use]
34    pub fn disable(mut self, feature: impl Into<String>) -> Self {
35        self.disabled_features.push(feature.into());
36        self
37    }
38
39    #[must_use]
40    pub fn with_api_key(mut self) -> Self {
41        self.with_api_key = true;
42        self
43    }
44
45    #[must_use]
46    pub fn device_auth(mut self) -> Self {
47        self.device_auth = true;
48        self
49    }
50}
51
52impl CodexCommand for LoginCommand {
53    type Output = CommandOutput;
54
55    fn args(&self) -> Vec<String> {
56        let mut args = vec!["login".into()];
57        push_common(
58            &mut args,
59            &self.config_overrides,
60            &self.enabled_features,
61            &self.disabled_features,
62        );
63        if self.with_api_key {
64            args.push("--with-api-key".into());
65        }
66        if self.device_auth {
67            args.push("--device-auth".into());
68        }
69        args
70    }
71
72    async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
73        exec::run_codex(codex, self.args()).await
74    }
75}
76
77#[derive(Debug, Clone, Default)]
78pub struct LoginStatusCommand {
79    config_overrides: Vec<String>,
80    enabled_features: Vec<String>,
81    disabled_features: Vec<String>,
82}
83
84impl LoginStatusCommand {
85    #[must_use]
86    pub fn new() -> Self {
87        Self::default()
88    }
89
90    #[must_use]
91    pub fn config(mut self, key_value: impl Into<String>) -> Self {
92        self.config_overrides.push(key_value.into());
93        self
94    }
95
96    #[must_use]
97    pub fn enable(mut self, feature: impl Into<String>) -> Self {
98        self.enabled_features.push(feature.into());
99        self
100    }
101
102    #[must_use]
103    pub fn disable(mut self, feature: impl Into<String>) -> Self {
104        self.disabled_features.push(feature.into());
105        self
106    }
107}
108
109impl CodexCommand for LoginStatusCommand {
110    type Output = CommandOutput;
111
112    fn args(&self) -> Vec<String> {
113        let mut args = vec!["login".into(), "status".into()];
114        push_common(
115            &mut args,
116            &self.config_overrides,
117            &self.enabled_features,
118            &self.disabled_features,
119        );
120        args
121    }
122
123    async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
124        exec::run_codex(codex, self.args()).await
125    }
126}
127
128#[derive(Debug, Clone, Default)]
129pub struct LogoutCommand;
130
131impl LogoutCommand {
132    #[must_use]
133    pub fn new() -> Self {
134        Self
135    }
136}
137
138impl CodexCommand for LogoutCommand {
139    type Output = CommandOutput;
140
141    fn args(&self) -> Vec<String> {
142        vec!["logout".into()]
143    }
144
145    async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
146        exec::run_codex(codex, self.args()).await
147    }
148}
149
150fn push_common(
151    args: &mut Vec<String>,
152    configs: &[String],
153    enabled: &[String],
154    disabled: &[String],
155) {
156    for value in configs {
157        args.push("-c".into());
158        args.push(value.clone());
159    }
160    for value in enabled {
161        args.push("--enable".into());
162        args.push(value.clone());
163    }
164    for value in disabled {
165        args.push("--disable".into());
166        args.push(value.clone());
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173
174    #[test]
175    fn login_args() {
176        assert_eq!(
177            LoginCommand::new().with_api_key().args(),
178            vec!["login", "--with-api-key"]
179        );
180    }
181
182    #[test]
183    fn login_status_args() {
184        assert_eq!(LoginStatusCommand::new().args(), vec!["login", "status"]);
185    }
186
187    #[test]
188    fn logout_args() {
189        assert_eq!(LogoutCommand::new().args(), vec!["logout"]);
190    }
191}