8.5 KiB
Architecture of the rhailib_dsl
Crate
The rhailib_dsl
crate serves as the central Domain-Specific Language (DSL) implementation for the Rhai scripting engine within the heromodels ecosystem. It provides a comprehensive set of business domain modules that expose Rust data structures and operations to Rhai scripts through a fluent, chainable API.
Core Architecture
The DSL follows a modular architecture where each business domain is implemented as a separate module with its own Rhai integration:
graph TD
A[rhailib_dsl] --> B[Business Domains]
B --> C[biz - Business Operations]
B --> D[finance - Financial Models]
B --> E[library - Content Management]
B --> F[flow - Workflow Management]
B --> G[calendar - Time Management]
B --> H[circle - Community Management]
B --> I[contact - Contact Management]
B --> J[access - Access Control]
B --> K[core - Core Utilities]
B --> L[object - Generic Objects]
C --> C1[company]
C --> C2[product]
C --> C3[sale]
C --> C4[shareholder]
D --> D1[account]
D --> D2[asset]
D --> D3[marketplace]
E --> E1[collection]
E --> E2[image]
E --> E3[pdf]
E --> E4[markdown]
E --> E5[book]
E --> E6[slideshow]
F --> F1[flow]
F --> F2[flow_step]
F --> F3[signature_requirement]
Design Patterns
1. Builder Pattern Integration
Each domain model follows a consistent builder pattern that enables fluent, chainable APIs in Rhai scripts:
let company = new_company()
.name("Acme Corp")
.email("contact@acme.com")
.business_type("global")
.status("active");
2. Macro-Driven Code Generation
The crate heavily utilizes procedural macros for:
- Authorization:
register_authorized_*_fn!
macros for CRUD operations - Type Conversion:
id_from_i64_to_u32
for safe ID conversions - Derive Macros:
FromVec
for array wrapper types
3. Type Safety with Rhai Integration
Each Rust type is carefully wrapped for Rhai compatibility:
- Custom Types: Using
#[rhai_type]
for proper Rhai integration - Array Wrappers: Specialized array types (e.g.,
RhaiCollectionArray
) for collections - Error Handling: Comprehensive error propagation with
Result<T, Box<EvalAltResult>>
Module Structure
Business Domain Modules
biz
- Business Operations
Handles core business entities:
- Company: Corporate entity management with registration, status, and business type
- Product: Product catalog and inventory management
- Sale: Sales transaction processing
- Shareholder: Equity and ownership management
finance
- Financial Models
Manages financial operations:
- Account: Financial account management
- Asset: Asset tracking and valuation
- Marketplace: Trading and marketplace operations
library
- Content Management
Comprehensive content management system:
- Collection: Content organization and grouping
- Image: Image asset management with dimensions
- PDF: Document management with page tracking
- Markdown: Text content with formatting
- Book: Multi-page publications with table of contents
- Slideshow: Presentation management
flow
- Workflow Management
Business process automation:
- Flow: Workflow definition and execution
- FlowStep: Individual workflow steps
- SignatureRequirement: Digital signature management
Core Infrastructure Modules
access
- Access Control
Security and permission management for resource access.
calendar
- Time Management
Calendar and scheduling functionality.
circle
- Community Management
Community and group management with themes and membership.
contact
- Contact Management
Contact information and relationship management.
core
- Core Utilities
Fundamental utilities including comment systems.
object
- Generic Objects
Generic object handling and manipulation.
Rhai Integration Patterns
Function Registration
Each module follows a consistent pattern for Rhai function registration:
#[export_module]
mod rhai_module_name {
// Constructor functions
#[rhai_fn(name = "new_entity")]
pub fn new_entity() -> RhaiEntity { ... }
// Setter functions (chainable)
#[rhai_fn(name = "field_name", return_raw)]
pub fn set_field(entity: &mut RhaiEntity, value: Type) -> Result<RhaiEntity, Box<EvalAltResult>> { ... }
// Getter functions
#[rhai_fn(get = "field_name", pure)]
pub fn get_field(entity: &mut RhaiEntity) -> Type { ... }
}
CRUD Operations
Standardized CRUD operations are generated using macros:
register_authorized_create_by_id_fn!(/* save operations */);
register_authorized_get_by_id_fn!(/* retrieve operations */);
register_authorized_delete_by_id_fn!(/* delete operations */);
register_authorized_list_fn!(/* list operations */);
JSON Serialization
A generic JSON serialization system allows any domain object to be converted to JSON:
fn register_json_method<T>(engine: &mut Engine)
where T: CustomType + Clone + Serialize
This enables Rhai scripts to call .json()
on any domain object for debugging or data export.
Data Flow Architecture
sequenceDiagram
participant Script as Rhai Script
participant DSL as DSL Module
participant Model as Domain Model
participant DB as Database
participant Auth as Authorization
Script->>DSL: new_entity()
DSL->>Model: Entity::new()
Model-->>DSL: Entity instance
DSL-->>Script: RhaiEntity
Script->>DSL: entity.field(value)
DSL->>Model: entity.field(value)
Model-->>DSL: Updated entity
DSL-->>Script: RhaiEntity
Script->>DSL: save_entity(entity)
DSL->>Auth: Check permissions
Auth-->>DSL: Authorization result
DSL->>DB: Store entity
DB-->>DSL: Stored entity
DSL-->>Script: Result
Security Architecture
Authorization Layer
All database operations go through an authorization layer:
- Permission Checking: Each operation validates user permissions
- Resource-Based Access: Access control based on resource types
- Caller Identification: Operations are attributed to specific callers
Type Safety
- ID Conversion: Safe conversion between Rhai's i64 and Rust's u32 IDs
- Error Propagation: Comprehensive error handling prevents script crashes
- Input Validation: Type checking and validation at the Rhai boundary
Performance Considerations
Memory Management
- Move Semantics: Efficient ownership transfer using
std::mem::take
- Clone Optimization: Strategic cloning only when necessary
- Reference Counting: Shared ownership where appropriate
Compilation Efficiency
- Macro Generation: Compile-time code generation reduces runtime overhead
- Module Separation: Modular compilation for faster build times
- Feature Flags: Conditional compilation based on requirements
Integration Points
External Dependencies
- heromodels: Core domain models and database abstractions
- heromodels_core: Fundamental data structures
- heromodels-derive: Procedural macros for model generation
- rhai: Scripting engine integration
- serde: Serialization for JSON export
Internal Dependencies
- macros: Authorization and utility macros
- derive: Custom derive macros for Rhai integration
Usage Patterns
Script Development
Typical Rhai script patterns enabled by this DSL:
// Create and configure entities
let company = new_company()
.name("Tech Startup")
.business_type("startup")
.email("hello@techstartup.com");
// Save to database
let saved_company = save_company(company);
// Retrieve and modify
let existing = get_company(saved_company.id);
let updated = existing.status("active");
save_company(updated);
// Export data
print(company.json());
Error Handling
Comprehensive error handling throughout:
- Type Validation: Invalid enum values are caught and reported
- Database Errors: Database operation failures are propagated
- Authorization Errors: Permission failures are clearly communicated
Extensibility
The architecture supports easy extension:
- New Domains: Add new business domains following existing patterns
- Custom Operations: Extend existing domains with new operations
- Integration: Easy integration with external systems through Rhai scripts
This modular, type-safe architecture provides a powerful foundation for business logic implementation while maintaining security and performance.