Skip to content

Commit f1d2bed

Browse files
authored
Merge pull request #14 from mirrorstack-ai/refactor/13-creds-load-helper
refactor(creds): extract load_or_login_hint helper
2 parents 27e10ee + 6915012 commit f1d2bed

4 files changed

Lines changed: 28 additions & 22 deletions

File tree

src/commands/module.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use dialoguer::{Confirm, Input, theme::ColorfulTheme};
1616
use indicatif::{ProgressBar, ProgressStyle};
1717

1818
use crate::api::{self, ApiError, CreateModuleInput};
19-
use crate::credentials::{self, LoadError};
19+
use crate::credentials;
2020

2121
use super::{
2222
DEFAULT_API_BASE, DEFAULT_APPS_API_BASE, DEFAULT_WEB_BASE, ENV_API_URL, ENV_APPS_API_URL,
@@ -64,16 +64,7 @@ pub fn run(args: ModuleArgs) -> Result<()> {
6464
fn init(args: InitArgs) -> Result<()> {
6565
let theme = ColorfulTheme::default();
6666

67-
let creds = match credentials::load() {
68-
Ok(c) => c,
69-
Err(LoadError::NotFound) => {
70-
return Err(anyhow!(
71-
"not signed in. Run `mirrorstack login` to sign in."
72-
));
73-
}
74-
Err(e) => return Err(e.into()),
75-
};
76-
67+
let creds = credentials::load_or_login_hint()?;
7768
let api_base = resolve_base(ENV_API_URL, DEFAULT_API_BASE);
7869
let apps_base = resolve_base(ENV_APPS_API_URL, DEFAULT_APPS_API_BASE);
7970
let web_base = resolve_base(ENV_WEB_URL, DEFAULT_WEB_BASE);

src/commands/whoami.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,15 @@ use anyhow::{Result, anyhow};
99
use clap::Args;
1010

1111
use crate::api::{self, ApiError};
12-
use crate::credentials::{self, LoadError};
12+
use crate::credentials;
1313

1414
use super::{DEFAULT_API_BASE, ENV_API_URL, resolve_base};
1515

1616
#[derive(Args)]
1717
pub struct WhoamiArgs {}
1818

1919
pub fn run(_args: WhoamiArgs) -> Result<()> {
20-
let creds = match credentials::load() {
21-
Ok(c) => c,
22-
Err(LoadError::NotFound) => {
23-
return Err(anyhow!(
24-
"not signed in. Run `mirrorstack login` to sign in."
25-
));
26-
}
27-
Err(e) => return Err(e.into()),
28-
};
29-
20+
let creds = credentials::load_or_login_hint()?;
3021
let api_base = resolve_base(ENV_API_URL, DEFAULT_API_BASE);
3122

3223
match api::me(&api_base, &creds.access_token) {

src/credentials/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ pub fn load() -> Result<Credentials, LoadError> {
7777
}
7878
}
7979

80+
/// Wrap [`load`] with the auth-required command idiom: a missing file
81+
/// becomes a "run `mirrorstack login`" hint instead of the raw error.
82+
/// Used by every command that needs an authenticated session.
83+
pub fn load_or_login_hint() -> Result<Credentials> {
84+
match load() {
85+
Ok(c) => Ok(c),
86+
Err(LoadError::NotFound) => Err(anyhow::anyhow!(
87+
"not signed in. Run `mirrorstack login` to sign in."
88+
)),
89+
Err(e) => Err(e.into()),
90+
}
91+
}
92+
8093
/// Encode `SystemTime` as RFC 3339 in JSON. Avoids pulling chrono just
8194
/// for this; serde_json's default for SystemTime is a tagged struct
8295
/// which is ugly on disk.

src/credentials/tests.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ fn credentials_lifecycle() {
3333
// load() before save() returns NotFound.
3434
assert!(matches!(load(), Err(LoadError::NotFound)));
3535

36+
// load_or_login_hint() before save() surfaces the login hint.
37+
let hint_err = load_or_login_hint().unwrap_err();
38+
assert!(
39+
hint_err.to_string().contains("mirrorstack login"),
40+
"expected login hint, got: {hint_err}"
41+
);
42+
3643
// save → load roundtrip preserves token strings + expires_at.
3744
let want = Credentials {
3845
access_token: "AT".into(),
@@ -41,6 +48,10 @@ fn credentials_lifecycle() {
4148
};
4249
save(&want).expect("save");
4350
let got = load().expect("load");
51+
52+
// load_or_login_hint() after save() returns the same data as load().
53+
let got_hint = load_or_login_hint().expect("load_or_login_hint");
54+
assert_eq!(got_hint, got);
4455
assert_eq!(got.access_token, want.access_token);
4556
assert_eq!(got.refresh_token, want.refresh_token);
4657
let skew = got

0 commit comments

Comments
 (0)