Files
osiris/STRUCTURE.md
Timur Gordon 097360ad12 first commit
2025-10-20 22:24:25 +02:00

7.1 KiB

OSIRIS Code Structure

📁 Directory Organization

Objects (src/objects/)

Each OSIRIS object has its own directory with:

  • mod.rs - Object definition and core logic
  • rhai.rs - Rhai integration (CustomType, builder API)
src/objects/
├── mod.rs                    # Module exports
├── note/
│   ├── mod.rs               # Note object definition
│   └── rhai.rs              # Note Rhai integration
└── event/
    ├── mod.rs               # Event object definition
    └── rhai.rs              # Event Rhai integration

Rhai Support (src/rhai_support/)

Core Rhai infrastructure (not object-specific):

  • instance.rs - OsirisInstance type for multi-instance support
  • mod.rs - Module exports and re-exports
src/rhai_support/
├── mod.rs                   # Re-exports from object modules
└── instance.rs              # OsirisInstance implementation

Runner (src/bin/runner/)

Standalone binary for running OSIRIS scripts:

  • main.rs - CLI and script execution
  • engine.rs - Engine factory with instance configuration
src/bin/runner/
├── main.rs                  # CLI interface
└── engine.rs                # Engine configuration

Core (src/)

Core OSIRIS functionality:

  • store/ - GenericStore, HeroDbClient, BaseData
  • index/ - Field indexing
  • error/ - Error types
  • config/ - Configuration
  • interfaces/ - Traits and interfaces
  • retrieve/ - Retrieval logic

🎯 Design Principles

1. Co-location

Object-specific code lives with the object:

objects/note/
  ├── mod.rs    # Note struct, impl
  └── rhai.rs   # Note Rhai support

2. Separation of Concerns

  • Objects - Domain models and business logic
  • Rhai Support - Scripting integration
  • Store - Persistence layer
  • Runner - Execution environment

3. Feature Gating

Rhai support is optional via rhai-support feature:

#[cfg(feature = "rhai-support")]
pub mod rhai;

4. Clean Exports

Clear module boundaries with re-exports:

// src/objects/mod.rs
pub mod note;
pub use note::Note;

// src/rhai_support/mod.rs
pub use crate::objects::note::rhai::register_note_api;

📝 Adding a New Object

1. Create Object Directory

mkdir -p src/objects/task

2. Create Object Definition (mod.rs)

use crate::store::BaseData;
use serde::{Deserialize, Serialize};

#[cfg(feature = "rhai-support")]
pub mod rhai;

#[derive(Debug, Clone, Serialize, Deserialize, crate::DeriveObject)]
pub struct Task {
    pub base_data: BaseData,
    
    #[index]
    pub title: String,
    
    pub completed: bool,
}

impl Task {
    pub fn new(ns: String) -> Self {
        Self {
            base_data: BaseData::new(ns),
            title: String::new(),
            completed: false,
        }
    }
}

3. Create Rhai Integration (rhai.rs)

use crate::objects::Task;
use rhai::{CustomType, Engine, TypeBuilder};

impl CustomType for Task {
    fn build(mut builder: TypeBuilder<Self>) {
        builder
            .with_name("Task")
            .with_fn("new", |ns: String| Task::new(ns))
            .with_fn("set_title", |task: &mut Task, title: String| {
                task.title = title;
                task.base_data.update_modified();
            })
            .with_fn("set_completed", |task: &mut Task, completed: bool| {
                task.completed = completed;
                task.base_data.update_modified();
            });
    }
}

pub fn register_task_api(engine: &mut Engine) {
    engine.build_type::<Task>();
    
    // Builder pattern
    engine.register_fn("task", |ns: String| Task::new(ns));
    engine.register_fn("title", |mut task: Task, title: String| {
        task.title = title;
        task.base_data.update_modified();
        task
    });
    engine.register_fn("completed", |mut task: Task, completed: bool| {
        task.completed = completed;
        task.base_data.update_modified();
        task
    });
}

4. Update Module Exports

// src/objects/mod.rs
pub mod task;
pub use task::Task;

// src/rhai_support/mod.rs
pub use crate::objects::task::rhai::register_task_api;

5. Register in Engine

// src/bin/runner/engine.rs
use osiris::rhai_support::register_task_api;

register_task_api(&mut engine);

6. Use in Scripts

let my_task = task("tasks")
    .title("Complete OSIRIS integration")
    .completed(true);

my_instance.put_task(my_task);

🔍 File Responsibilities

Object mod.rs

  • Struct definition with #[derive(DeriveObject)]
  • Index fields marked with #[index]
  • Constructor methods (new, with_id)
  • Business logic methods
  • Builder pattern methods (optional)

Object rhai.rs

  • CustomType implementation
  • register_*_api function
  • Rhai-specific builder methods
  • Type conversions for Rhai

rhai_support/instance.rs

  • OsirisInstance struct
  • Multi-instance support
  • CRUD operations per instance
  • Async → Sync bridge

bin/runner/engine.rs

  • OsirisConfig for instance configuration
  • create_osiris_engine_with_config function
  • Engine setup and registration

bin/runner/main.rs

  • CLI argument parsing
  • Instance configuration from CLI
  • Script loading and execution

🎨 Benefits of This Structure

1. Discoverability

All code for an object is in one place:

objects/note/
  ├── mod.rs    # "What is a Note?"
  └── rhai.rs   # "How do I use Note in Rhai?"

2. Maintainability

Changes to an object are localized:

  • Add a field → Update mod.rs and rhai.rs
  • No hunting through multiple directories

3. Scalability

Easy to add new objects:

  • Create directory
  • Add two files
  • Update exports
  • Done!

4. Testability

Each object can have its own tests:

objects/note/
  ├── mod.rs
  ├── rhai.rs
  └── tests.rs

5. Clear Dependencies

Objects (domain) → Independent
  ↓
Rhai Support → Depends on Objects
  ↓
Runner → Depends on Rhai Support

📊 Module Graph

osiris (lib)
├── objects/
│   ├── note/
│   │   ├── mod.rs (Note struct)
│   │   └── rhai.rs (Note Rhai)
│   └── event/
│       ├── mod.rs (Event struct)
│       └── rhai.rs (Event Rhai)
├── rhai_support/
│   ├── instance.rs (OsirisInstance)
│   └── mod.rs (re-exports)
├── store/ (GenericStore, BaseData)
├── index/ (FieldIndex)
└── error/ (Error types)

runner (bin)
├── main.rs (CLI)
└── engine.rs (Engine factory)

Summary

Old Structure:

src/rhai_support/
  ├── note_rhai.rs
  ├── event_rhai.rs
  ├── engine.rs
  └── instance.rs

New Structure:

src/objects/
  ├── note/
  │   ├── mod.rs
  │   └── rhai.rs
  └── event/
      ├── mod.rs
      └── rhai.rs

src/rhai_support/
  ├── instance.rs
  └── mod.rs (re-exports only)

Benefits:

  • Better organization
  • Co-located code
  • Easier to find things
  • Cleaner separation
  • Scalable structure