add heroledger models

This commit is contained in:
Timur Gordon
2025-08-05 12:53:24 +02:00
parent 7d9a6906c6
commit 1a62fcacdd
12 changed files with 2240 additions and 318 deletions

View File

@@ -0,0 +1,301 @@
# AI Prompt: Convert V Language Specs to Rust Hero Models
## Objective
Convert V language model specifications (`.v` files) to Rust hero models that integrate with the heromodels framework. The generated Rust models should follow the established patterns for base data embedding, indexing, fluent builder APIs, and Rhai scripting integration.
## V Language Input Structure Analysis
### V Spec Patterns to Recognize:
1. **Module Declaration**: `module circle` or `module group`
2. **Base Embedding**: `core.Base` - represents the base model data
3. **Index Fields**: Fields marked with `@[index]` comments
4. **Mutability**: Fields declared with `pub mut:`
5. **Enums**: `pub enum Status { active, inactive, suspended }`
6. **Nested Structs**: Embedded configuration or related data structures
7. **Collections**: `[]u32`, `[]string`, `map[string]string`
8. **References**: `u32` fields typically represent foreign key references
### Example V Spec Structure:
```v
module circle
import freeflowuniverse.herolib.hero.models.core
pub struct User {
core.Base
pub mut:
username string @[index] // Unique username
email []string @[index] // Multiple email addresses
status UserStatus // Enum reference
profile UserProfile // Nested struct
metadata map[string]string // Key-value pairs
}
pub enum UserStatus {
active
inactive
suspended
}
pub struct UserProfile {
pub mut:
full_name string
bio string
links map[string]string
}
```
## Rust Hero Model Conversion Rules
### 1. File Structure and Imports
```rust
use heromodels_core::{Model, BaseModelData, IndexKey};
use heromodels_derive::model;
use rhai::CustomType;
use rhailib_derive::RhaiApi;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
```
### 2. Base Data Embedding
- **V**: `core.Base`
- **Rust**: `pub base_data: BaseModelData,`
### 3. Index Field Conversion
- **V**: `field_name string @[index]`
- **Rust**: `#[index] pub field_name: String,`
### 4. Type Mappings
| V Type | Rust Type |
|--------|-----------|
| `string` | `String` |
| `[]string` | `Vec<String>` |
| `[]u32` | `Vec<u32>` |
| `u32` | `u32` |
| `u64` | `u64` |
| `f64` | `f64` |
| `bool` | `bool` |
| `map[string]string` | `std::collections::HashMap<String, String>` |
### 5. Struct Declaration Pattern
```rust
/// Documentation comment describing the model
#[model]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType, Default, RhaiApi)]
pub struct ModelName {
/// Base model data
pub base_data: BaseModelData,
#[index]
pub indexed_field: String,
pub regular_field: String,
pub optional_field: Option<String>,
pub nested_struct: NestedType,
pub collection: Vec<u32>,
pub metadata: std::collections::HashMap<String, String>,
}
```
### 6. Enum Conversion
```rust
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum UserStatus {
Active,
Inactive,
Suspended,
}
```
### 7. Fluent Builder Implementation
Every model must implement a fluent builder pattern:
```rust
impl ModelName {
/// Create a new instance
pub fn new(id: u32) -> Self {
Self {
base_data: BaseModelData::new(id),
indexed_field: String::new(),
regular_field: String::new(),
optional_field: None,
nested_struct: NestedType::new(),
collection: Vec::new(),
metadata: std::collections::HashMap::new(),
}
}
/// Set indexed field (fluent)
pub fn indexed_field(mut self, value: impl ToString) -> Self {
self.indexed_field = value.to_string();
self
}
/// Set regular field (fluent)
pub fn regular_field(mut self, value: impl ToString) -> Self {
self.regular_field = value.to_string();
self
}
/// Set optional field (fluent)
pub fn optional_field(mut self, value: impl ToString) -> Self {
self.optional_field = Some(value.to_string());
self
}
/// Set nested struct (fluent)
pub fn nested_struct(mut self, value: NestedType) -> Self {
self.nested_struct = value;
self
}
/// Add to collection (fluent)
pub fn add_to_collection(mut self, value: u32) -> Self {
self.collection.push(value);
self
}
/// Set entire collection (fluent)
pub fn collection(mut self, value: Vec<u32>) -> Self {
self.collection = value;
self
}
/// Add metadata entry (fluent)
pub fn add_metadata(mut self, key: impl ToString, value: impl ToString) -> Self {
self.metadata.insert(key.to_string(), value.to_string());
self
}
/// Build the final instance
pub fn build(self) -> Self {
self
}
}
```
### 8. Model Trait Implementation
```rust
impl Model for ModelName {
fn db_prefix() -> &'static str {
"modelname"
}
fn get_id(&self) -> u32 {
self.base_data.id
}
fn base_data_mut(&mut self) -> &mut BaseModelData {
&mut self.base_data
}
fn db_keys(&self) -> Vec<IndexKey> {
let mut keys = Vec::new();
// Add index keys for fields marked with #[index]
keys.push(IndexKey::new("indexed_field", &self.indexed_field));
// Add additional index keys as needed
keys
}
}
```
### 9. Nested Struct Builder Pattern
For embedded types, implement similar builder patterns:
```rust
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct NestedType {
pub field1: String,
pub field2: String,
}
impl NestedType {
pub fn new() -> Self {
Self {
field1: String::new(),
field2: String::new(),
}
}
pub fn field1(mut self, value: impl ToString) -> Self {
self.field1 = value.to_string();
self
}
pub fn field2(mut self, value: impl ToString) -> Self {
self.field2 = value.to_string();
self
}
pub fn build(self) -> Self {
self
}
}
```
## Conversion Steps
1. **Analyze V Spec Structure**
- Identify the module name and main structs
- Note which fields are marked with `@[index]`
- Identify nested structs and enums
- Map field types from V to Rust
2. **Create Rust File Structure**
- Add appropriate imports
- Convert enums first (they're often referenced by structs)
- Convert nested structs before main structs
3. **Implement Main Struct**
- Add `#[model]` macro and derives
- Embed `BaseModelData` as `base_data`
- Mark indexed fields with `#[index]`
- Convert field types according to mapping table
4. **Implement Builder Pattern**
- Add `new(id: u32)` constructor
- Add fluent setter methods for each field
- Handle optional fields appropriately
- Add collection manipulation methods
5. **Implement Model Trait**
- Define appropriate `db_prefix`
- Implement required trait methods
- Add index keys for searchable fields
6. **Add Documentation**
- Document the struct and its purpose
- Document each field's meaning
- Add usage examples in comments
## Example Usage After Conversion
```rust
let user = User::new(1)
.username("john_doe")
.add_email("john@example.com")
.add_email("john.doe@company.com")
.status(UserStatus::Active)
.profile(
UserProfile::new()
.full_name("John Doe")
.bio("Software developer")
.build()
)
.add_metadata("department", "engineering")
.build();
```
## Notes and Best Practices
1. **Field Naming**: Convert V snake_case to Rust snake_case (usually no change needed)
2. **Optional Fields**: Use `Option<T>` for fields that may be empty in V
3. **Collections**: Always provide both `add_item` and `set_collection` methods
4. **Error Handling**: Builder methods should not panic; use appropriate defaults
5. **Documentation**: Include comprehensive documentation for public APIs
6. **Testing**: Consider adding unit tests for builder patterns
7. **Validation**: Add validation logic in builder methods if needed
## File Organization
Place the converted Rust models in the appropriate subdirectory under `heromodels/src/models/` based on the domain (e.g., `user/`, `finance/`, `governance/`, etc.).