Skip to content

Commit e80e25b

Browse files
domenkozarclaude
andcommitted
feat: load provider information from registry in config init
- Add name() and description() methods to Provider trait - Implement provider info methods for all providers - Update config init to dynamically load providers from registry - Add list_providers() method to ProviderRegistry - Export provider module to allow access to ProviderRegistry This allows the init command to automatically discover all available providers rather than hardcoding them, making it easier to add new providers in the future. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 96ec2ce commit e80e25b

File tree

8 files changed

+73
-5
lines changed

8 files changed

+73
-5
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
88
use std::process::Command;
99
use thiserror::Error;
1010

11-
mod provider;
11+
pub mod provider;
1212
use provider::{Provider as ProviderTrait, ProviderRegistry};
1313

1414
#[cfg(feature = "macros")]

src/main.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,26 @@ fn main() -> Result<()> {
159159
Commands::Config { action } => match action {
160160
ConfigAction::Init => {
161161
use inquire::Select;
162+
use secretspec::provider::ProviderRegistry;
162163

163-
let providers = vec!["keyring", "dotenv", "env"];
164-
let provider = Select::new("Select your preferred provider backend:", providers)
165-
.with_help_message("keyring: Uses system keychain (Recommended)\ndotenv: Traditional .env files\nenv: Read-only environment variables")
166-
.prompt()?;
164+
// Get providers from registry
165+
let registry = ProviderRegistry::new();
166+
let mut providers = registry.list_providers();
167+
// Sort providers by name for consistent display
168+
providers.sort_by_key(|(name, _)| *name);
169+
170+
// Create provider choices with descriptions
171+
let provider_choices: Vec<String> = providers
172+
.iter()
173+
.map(|(name, provider)| format!("{}: {}", name, provider.description()))
174+
.collect();
175+
176+
let selected_choice =
177+
Select::new("Select your preferred provider backend:", provider_choices)
178+
.prompt()?;
179+
180+
// Extract provider name from the selected choice
181+
let provider = selected_choice.split(':').next().unwrap_or("keyring");
167182

168183
let profiles = vec!["development", "default", "none"];
169184
let profile_choice = Select::new("Select your default profile:", profiles)

src/provider/dotenv.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,12 @@ impl Provider for DotEnvProvider {
4848
vars.insert(key.to_string(), value.to_string());
4949
self.save_env_vars(&vars)
5050
}
51+
52+
fn name(&self) -> &'static str {
53+
"dotenv"
54+
}
55+
56+
fn description(&self) -> &'static str {
57+
"Traditional .env files"
58+
}
5159
}

src/provider/env.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,12 @@ impl Provider for EnvProvider {
2626
fn allows_set(&self) -> bool {
2727
false
2828
}
29+
30+
fn name(&self) -> &'static str {
31+
"env"
32+
}
33+
34+
fn description(&self) -> &'static str {
35+
"Read-only environment variables"
36+
}
2937
}

src/provider/keyring.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,12 @@ impl Provider for KeyringProvider {
3333
entry.set_password(value)?;
3434
Ok(())
3535
}
36+
37+
fn name(&self) -> &'static str {
38+
"keyring"
39+
}
40+
41+
fn description(&self) -> &'static str {
42+
"Uses system keychain (Recommended)"
43+
}
3644
}

src/provider/lastpass.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ impl Provider for LastPassProvider {
161161

162162
Ok(())
163163
}
164+
165+
fn name(&self) -> &'static str {
166+
"lastpass"
167+
}
168+
169+
fn description(&self) -> &'static str {
170+
"LastPass password manager"
171+
}
164172
}
165173

166174
impl Default for LastPassProvider {

src/provider/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ pub trait Provider: Send + Sync {
2323
fn allows_set(&self) -> bool {
2424
true
2525
}
26+
27+
/// Returns the name of this provider for display purposes
28+
fn name(&self) -> &'static str;
29+
30+
/// Returns a brief description of this provider
31+
fn description(&self) -> &'static str;
2632
}
2733

2834
pub struct ProviderRegistry {
@@ -58,4 +64,11 @@ impl ProviderRegistry {
5864
pub fn get(&self, name: &str) -> Option<&Box<dyn Provider>> {
5965
self.backends.get(name)
6066
}
67+
68+
pub fn list_providers(&self) -> Vec<(&str, &dyn Provider)> {
69+
self.backends
70+
.iter()
71+
.map(|(name, provider)| (name.as_str(), provider.as_ref()))
72+
.collect()
73+
}
6174
}

src/provider/onepassword.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ impl Provider for OnePasswordProvider {
207207

208208
Ok(())
209209
}
210+
211+
fn name(&self) -> &'static str {
212+
"1password"
213+
}
214+
215+
fn description(&self) -> &'static str {
216+
"1Password password manager"
217+
}
210218
}
211219

212220
impl Default for OnePasswordProvider {

0 commit comments

Comments
 (0)