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