Some checks failed
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Cleanup (push) Has been cancelled
Core Lib Template
This is a template crate for the core runtime library using trait-based dependency injection. It replaces the problematic code generation approach with clean, trait-based abstractions.
Key Features
- Zero Code Generation: No build.rs, no environment variables, no generated code
- Pure Dependency Injection: Uses traits from the pure traits layer
- Implementation Freedom: Clone this template and customize as needed
- No Circular Dependencies: Clean dependency graph through trait abstractions
Architecture
This template follows the new 3-layer architecture:
Layer 1: Pure Traits (../../../traits/)
↓
Layer 2: Templates (this template)
↓
Layer 3: Implementation (your cloned crate)
Usage
1. Clone Template
# Clone this template to your implementation
cp -r templates/core-lib-template my-project/crates/core-lib
# Update Cargo.toml with your project name
sed -i 's/core-lib-template/core-lib/' my-project/crates/core-lib/Cargo.toml
2. Implement Providers
Create your concrete implementations:
use core_lib::*;
// Your page provider implementation
struct MyPageProvider {
components: HashMap<String, MyComponent>,
}
impl PageProvider for MyPageProvider {
type Component = MyComponent;
type View = AnyView;
type Props = ();
fn get_component(&self, id: &str) -> ComponentResult<Self::Component> {
self.components.get(id)
.cloned()
.ok_or_else(|| ComponentError::NotFound(id.to_string()))
}
fn render_component(
&self,
component: &Self::Component,
props: Self::Props,
language: &str
) -> ComponentResult<Self::View> {
// Your rendering logic here
Ok(component.render(language))
}
fn list_components(&self) -> Vec<String> {
self.components.keys().cloned().collect()
}
}
3. Configure Application
// Create your application context
let page_provider = MyPageProvider::new();
let content_provider = MyContentProvider::new();
let localization_provider = MyLocalizationProvider::new();
let site_config = load_site_config();
let app_context = AppContext::new(
page_provider,
content_provider,
localization_provider,
site_config,
);
// Create route handler
let language_detector = ConfigurableLanguageDetector::from_site_config(&app_context.site_config);
let route_resolver = GenericRouteResolver::new(app_context.page_provider.clone(), language_detector);
Modules
Core Modules
routing: Language detection, route resolution, generic route handlingcomponents: Layout providers, component rendering utilitiescontent: Content item types, query buildersi18n: Simple localization provider with HashMap storageerrors: Comprehensive error handling with user-friendly messagesutils: Path utilities, string formatting, configuration builders
Feature Modules (Optional)
Enable via Cargo features:
wasm(default): WASM utilities (console, DOM, storage, HTTP)time: Time formatting, timezone handling, duration parsingids: UUID generation, slug utilities, content ID managementcontent: Content processing utilitiesi18n: Internationalization helpers
Benefits Over Code Generation
Before (Problematic)
// Generated at build time, hardcoded dependencies
core_lib::generate_client_render_component!();
After (Clean)
// Trait-based, implementation provides concrete types
impl<P: PageProvider> RouteRenderer for ClientRenderer<P> {
type View = AnyView;
type Component = P::Component;
fn render_component(&self, component: &Self::Component, ...) -> RoutingResult<Self::View> {
self.page_provider.render_component(component, (), language)
}
}
Example Implementation
See the comprehensive tests in each module for usage examples. Here's a minimal setup:
use core_lib::{*, routing::*, components::*, i18n::*};
// 1. Create providers
let mut page_provider = MyPageProvider::new();
page_provider.register_component("index", IndexComponent);
page_provider.register_component("about", AboutComponent);
let mut localization = SimpleLocalizationProvider::new("en".to_string());
localization.add_translation("en".to_string(), "welcome".to_string(), "Welcome".to_string());
// 2. Create language detector from config
let language_detector = ConfigurableLanguageDetector::new(languages, "en".to_string());
// 3. Create route resolver
let route_resolver = GenericRouteResolver::new(page_provider, language_detector);
// 4. Handle requests
let resolution = route_resolver.resolve_route("/about")?;
if let Some(component) = resolution.component {
let result = route_handler.handle_route(
Some(&component),
&resolution.path,
&resolution.language,
&resolution.parameters
)?;
println!("Rendered: {:?}", result.view);
}
Migration from Foundation
When migrating from the old foundation crate:
- Remove build.rs: No more code generation
- Replace generated code: Use trait-based providers instead
- Inject dependencies: Pass concrete implementations via constructors
- Remove environment dependencies: Use configuration objects instead
Features
Configure optional functionality via Cargo features:
[features]
default = ["wasm"]
full = ["wasm", "time", "ids", "content", "i18n"]
minimal = []
Testing
Each module includes comprehensive tests. Run with:
cargo test
cargo test --all-features # Test with all features enabled
cargo test --no-default-features # Test minimal configuration
Compatibility
- Rust 2021 Edition
- WASM Compatible: Conditional compilation for WASM vs native
- Feature Gated: Only compile what you need
- Framework Agnostic: Works with any Leptos application
This template solves the circular dependency and tight coupling issues while maintaining full implementation flexibility through trait-based dependency injection.