profile_kit
A flexible, lightweight Rust library for managing user profiles โ framework-agnostic, developer-friendly, and production-ready.
โจ Features
- ๐ Pluggable profile storage via trait abstraction
- โ๏ธ Designed for composability in any Rust project
- ๐ Supports user preferences (language, currency, newsletter opt-in)
- ๐งช Easy to test with in-memory implementation
- ๐ฆ Lightweight dependencies, ready for web or backend apps
๐ Quick Start
use serde_json::{json, Value};
use uuid::Uuid;
use profile_kit::model::{UserAttributes, UserPreferences, UserProfile};
fn main() {
let mut prefs = UserPreferences::new();
prefs.set_newsletter_opt_in(true);
prefs.set_extra("theme".to_string(), json!("dark"));
prefs.set_extra("custom_field".to_string(), json!({"key": "value"}));
let mut attrs = UserAttributes::new();
attrs.set_first_name("John".to_string());
attrs.set_last_name("Doe".to_string());
attrs.set_extra("theme", Value::String("dark".into()));
attrs.set_extra("roles", json!(vec!["admin", "editor"]));
let id = Uuid::now_v7().simple();
let email = "".to_string();
let mut profile = UserProfile::new(id.to_string(), email);
profile.set_email("john.doe@example.com".to_string());
profile.set_attributes(Some(attrs));
profile.set_preferences(Some(prefs));
let serialized = serde_json::to_string_pretty(&profile).expect("REASON");
eprintln!("Serialized profile: {}", serialized);
let deserialized: UserProfile = serde_json::from_str(&serialized).expect("REASON");
eprintln!("Deserialized profile: {:?}", deserialized);
eprintln!("roles : {:?}", deserialized.get_attributes().expect("REASON").get_extra("roles"));
eprintln!("first_name : {:?}", deserialized.get_attributes().expect("REASON").get_first_name());
}
๐ง Trait-based Storage Example
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use profile_kit::error::ProfileKitError;
use profile_kit::model::UserProfile;
use profile_kit::repository::UserProfileRepository;
pub struct InMemoryUserProfileRepository {
storage: Arc<RwLock<HashMap<String, UserProfile>>>,
}
impl InMemoryUserProfileRepository {
pub fn new() -> Self {
InMemoryUserProfileRepository {
storage: Arc::new(RwLock::new(HashMap::new())),
}
}
}
impl UserProfileRepository for InMemoryUserProfileRepository {
fn get_by_id(&self, id: String) -> Result<Option<UserProfile>, ProfileKitError> {
let storage = self.storage.read().map_err(|_| ProfileKitError::StorageError)?;
Ok(storage.get(&id).cloned())
}
fn create(&self, profile: UserProfile) -> Result<(), ProfileKitError> {
let mut storage = self.storage.write().map_err(|_| ProfileKitError::StorageError)?;
if storage.contains_key(&profile.id) {
return Err(ProfileKitError::AlreadyExists);
}
storage.insert(profile.id.clone(), profile);
Ok(())
}
fn update(&self, profile: UserProfile) -> Result<(), ProfileKitError> {
let mut storage = self.storage.write().map_err(|_| ProfileKitError::StorageError)?;
if !storage.contains_key(&profile.id) {
return Err(ProfileKitError::NotFound);
}
storage.insert(profile.id.clone(), profile);
Ok(())
}
fn delete(&self, id: String) -> Result<(), ProfileKitError> {
let mut storage = self.storage.write().map_err(|_| ProfileKitError::StorageError)?;
if storage.remove(&id).is_none() {
return Err(ProfileKitError::NotFound);
}
Ok(())
}
}
use uuid::Uuid;
use profile_kit::model;
fn main() {
let repo = InMemoryUserProfileRepository::new();
let id= Uuid::now_v7().simple();
let mut user = UserProfile::new(id.to_string(), "test@example.com".into());
user.set_email("john.doe@example.com".to_string());
repo.create(user).expect("Failed to create user");
eprintln!("id {:?}", id.to_string());
eprintln!("id {:?}", repo.get_by_id(id.to_string()));
}
๐ License
This project is licensed under the Apache-2.0 license. LICENSE
๐งโ Author
Jerry Maheswara jerrymaheswara@gmail.com
โค๏ธ Built with Love in Rust
This project is built with โค๏ธ using Rust โ a systems programming language that is safe, fast, and concurrent. Rust is the perfect choice for building reliable and efficient applications.
๐ Contributing
Pull requests, issues, and feedback are welcome!
If you find this crate useful, give it a โญ and share it with others in the Rust community.