use super::generated;
use super::ResourceDefinition;
use crate::types::ResolvedType;
use std::collections::HashMap;
use std::sync::OnceLock;
static REGISTRY: OnceLock<ResourceRegistry> = OnceLock::new();
pub fn get() -> &'static ResourceRegistry {
REGISTRY.get_or_init(ResourceRegistry::new)
}
pub struct ResourceRegistry {
resources: HashMap<(String, String), ResourceDefinition>,
modules: Vec<&'static str>,
}
impl ResourceRegistry {
fn new() -> Self {
let mut registry = Self {
resources: HashMap::new(),
modules: vec!["S3", "Network", "CloudWatch", "IAM", "EC2", "Secret", "RDS"],
};
for def in generated::all_resources() {
registry.register(def);
}
registry
}
fn register(&mut self, def: ResourceDefinition) {
let key = (def.module.to_string(), def.function.to_string());
self.resources.insert(key, def);
}
pub fn get(&self, module: &str, function: &str) -> Option<&ResourceDefinition> {
let key = (module.to_string(), function.to_string());
self.resources.get(&key)
}
pub fn is_module(&self, name: &str) -> bool {
self.modules.contains(&name)
}
pub fn resolve_member(&self, module: &str, function: &str) -> ResolvedType {
if let Some(def) = self.get(module, function) {
let params: Vec<(String, ResolvedType)> = def
.all_params()
.iter()
.map(|p| (p.name.to_string(), p.param_type.clone()))
.collect();
ResolvedType::Function {
params,
returns: Box::new(def.returns.clone()),
}
} else {
ResolvedType::Unknown
}
}
pub fn resolve_return(&self, module: &str, function: &str) -> ResolvedType {
self.get(module, function)
.map(|def| def.returns.clone())
.unwrap_or(ResolvedType::Unknown)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_registry_lookup() {
let registry = get();
let bucket = registry.get("S3", "createBucket");
assert!(bucket.is_some());
let def = bucket.unwrap();
assert_eq!(def.module, "S3");
assert_eq!(def.function, "createBucket");
assert_eq!(def.required_params.len(), 1);
assert_eq!(def.security_params.len(), 2); assert_eq!(def.preferred_params.len(), 2); }
#[test]
fn test_registry_resolve_member() {
let registry = get();
let fn_type = registry.resolve_member("S3", "createBucket");
assert!(matches!(fn_type, ResolvedType::Function { .. }));
}
#[test]
fn test_registry_unknown() {
let registry = get();
let unknown = registry.get("Unknown", "foo");
assert!(unknown.is_none());
}
}