# Rhai System A thread-safe system for creating and managing Rhai script engines with hot reloading support for multiple script files. ## Overview Rhai System is a Rust module that simplifies working with the [Rhai scripting language](https://rhai.rs/) by providing a system for creating thread-safe Rhai engines with pre-compiled scripts. It supports hot reloading of multiple script files, ensuring your application always uses the latest version of your scripts without requiring a restart. ## Features - **Thread Safety**: Uses Rhai's `sync` feature to ensure engines are `Send + Sync` - **Multiple Script Support**: Compiles and merges multiple Rhai script files into a single AST - **Hot Reload**: Automatically detects changes to script files and recompiles them without requiring application restart - **Cross-Script Function Calls**: Functions defined in one script can call functions defined in another script - **Detailed Error Handling**: Provides clear error messages when scripts fail to compile - **Performance Optimized**: Efficiently recompiles only the scripts that have changed ## Usage ### Basic Usage ```rust use rhai_system::create_hot_reloadable_system; use std::path::PathBuf; // Create a hot reloadable system with multiple script files let script_paths = vec![ PathBuf::from("scripts/main.rhai"), PathBuf::from("scripts/utils.rhai"), ]; let system = create_hot_reloadable_system(&script_paths, None).unwrap(); // Call a function from the script let result: i64 = system.call_fn("add", (40, 2)).unwrap(); assert_eq!(result, 42); // The system will automatically reload scripts when they change ``` ### Watching for Changes The system automatically sets up file watchers for all script files: ```rust use rhai_system::create_hot_reloadable_system; use std::path::PathBuf; use std::thread; use std::time::Duration; // Create a hot reloadable system let script_paths = vec![PathBuf::from("scripts/main.rhai")]; let system = create_hot_reloadable_system(&script_paths, None).unwrap(); // Start watching for changes to the script files system.watch(); // The system will now automatically reload scripts when they change // Your application can continue running and using the latest version of the scripts ``` ### Thread-Safe Usage The system is designed to be thread-safe, allowing you to use it from multiple threads: ```rust use rhai_system::create_hot_reloadable_system; use std::path::PathBuf; use std::thread; use std::sync::Arc; // Create a hot reloadable system let script_paths = vec![PathBuf::from("scripts/main.rhai")]; let system = Arc::new(create_hot_reloadable_system(&script_paths, None).unwrap()); // Clone the system for use in another thread let system_clone = Arc::clone(&system); // Start watching for changes in the main thread system.watch(); // Use the system in another thread let handle = thread::spawn(move || { // Create a thread-local clone of the system let thread_system = system_clone.clone_for_thread(); // Call functions from the script let result: i64 = thread_system.call_fn("add", (40, 2)).unwrap(); assert_eq!(result, 42); }); handle.join().unwrap(); ``` ## Module Resolution Rhai System supports the BasePathModuleResolver approach for resolving module imports: - Uses a single base path for resolving all module imports - Makes the resolution process more predictable and consistent - Simplifies the Rhai module import system by removing the complexity of relative path resolution See the `examples/base_path_imports` directory for a comprehensive example of this approach. ## Error Handling The system provides detailed error information when scripts fail to compile: ```rust use rhai_system::create_hot_reloadable_system; use std::path::PathBuf; let script_paths = vec![PathBuf::from("non_existent.rhai")]; let result = create_hot_reloadable_system(&script_paths, None); match result { Err(err) => { // Error will contain: // - Which script failed to compile // - The reason for the failure println!("Error: {}", err); } Ok(_) => panic!("Expected an error"), } ``` ## Testing The project follows Rust's standard testing approach: ```bash # Run all tests cargo test # Run a specific test cargo test test_hot_reload_callback ``` ## Installation Add this to your `Cargo.toml`: ```toml [dependencies] rhai_system = { path = "path/to/rhai_system" } ``` ## Examples See the `examples` directory for complete examples: - `hot_reload`: Demonstrates hot reloading of multiple script files - `base_path_imports`: Demonstrates the BasePathModuleResolver approach for module imports