1pub fn env_var_name_for_service(service: &str) -> String {
38 let lower = service.to_lowercase();
39 let curated = match lower.as_str() {
40 s if s.contains("aws") => Some("AWS_ACCESS_KEY_ID"),
41 s if s.contains("github") || s.starts_with("gh-") || s.starts_with("ghp_") => {
42 Some("GITHUB_TOKEN")
43 }
44 s if s.contains("gitlab") => Some("GITLAB_TOKEN"),
45 s if s.contains("slack") => Some("SLACK_BOT_TOKEN"),
46 s if s.contains("openai") => Some("OPENAI_API_KEY"),
47 s if s.contains("anthropic") => Some("ANTHROPIC_API_KEY"),
48 s if s.contains("stripe") => Some("STRIPE_SECRET_KEY"),
49 s if s.contains("twilio") => Some("TWILIO_AUTH_TOKEN"),
50 s if s.contains("sendgrid") => Some("SENDGRID_API_KEY"),
51 s if s.contains("google") || s.contains("gcp") => Some("GOOGLE_API_KEY"),
52 s if s.contains("azure") => Some("AZURE_CLIENT_SECRET"),
53 s if s.contains("npm") => Some("NPM_TOKEN"),
54 s if s.contains("pypi") => Some("PYPI_TOKEN"),
55 s if s.contains("docker") => Some("DOCKER_PASSWORD"),
56 s if s.contains("datadog") => Some("DATADOG_API_KEY"),
57 s if s.contains("snowflake") => Some("SNOWFLAKE_PASSWORD"),
58 _ => None,
59 };
60 curated
61 .map(|s| s.to_string())
62 .unwrap_or_else(|| service_to_screaming_snake(service))
63}
64
65fn service_to_screaming_snake(service: &str) -> String {
66 let mut out = String::with_capacity(service.len() + 4);
67 for ch in service.chars() {
68 if ch.is_ascii_alphanumeric() {
69 out.push(ch.to_ascii_uppercase());
70 } else if !out.ends_with('_') {
71 out.push('_');
72 }
73 }
74 out.trim_matches('_').to_string() + "_KEY"
75}
76
77pub fn fix_replacement_text(service: &str) -> String {
81 format!("${{{}}}", env_var_name_for_service(service))
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn curated_services_map_correctly() {
90 assert_eq!(env_var_name_for_service("aws"), "AWS_ACCESS_KEY_ID");
91 assert_eq!(env_var_name_for_service("aws-iam"), "AWS_ACCESS_KEY_ID");
92 assert_eq!(env_var_name_for_service("github"), "GITHUB_TOKEN");
93 assert_eq!(env_var_name_for_service("openai"), "OPENAI_API_KEY");
94 assert_eq!(env_var_name_for_service("anthropic"), "ANTHROPIC_API_KEY");
95 assert_eq!(env_var_name_for_service("stripe"), "STRIPE_SECRET_KEY");
96 assert_eq!(env_var_name_for_service("snowflake"), "SNOWFLAKE_PASSWORD");
97 }
98
99 #[test]
100 fn unknown_service_falls_back_to_screaming_snake() {
101 assert_eq!(
102 env_var_name_for_service("acme-widget-api"),
103 "ACME_WIDGET_API_KEY"
104 );
105 assert_eq!(env_var_name_for_service("RevenueCat"), "REVENUECAT_KEY");
106 }
107
108 #[test]
109 fn fix_replacement_text_wraps_in_dollar_braces() {
110 assert_eq!(fix_replacement_text("aws"), "${AWS_ACCESS_KEY_ID}");
111 assert_eq!(fix_replacement_text("acme-x"), "${ACME_X_KEY}");
112 }
113
114 #[test]
115 fn empty_service_does_not_panic() {
116 assert_eq!(env_var_name_for_service(""), "_KEY");
118 }
119}