This document outlines the core data structures (models) used on the server-side of the LogseqXR application. These models define how data is structured, stored, and manipulated.
Defines parameters for the physics-based graph layout simulation.
Core Structure (from src/models/simulation_params.rs)
// In src/models/simulation_params.rs
#[derive(Debug, Clone, Serialize, Deserialize, Copy)]
pub struct SimulationParams {
pub iterations: u32,
pub spring_strength: f32,
pub repulsion_strength: f32,
pub damping: f32,
pub time_step: f32,
pub max_repulsion_distance: f32,
pub mass_scale: f32,
pub boundary_damping: f32,
pub enable_bounds: bool,
pub viewport_bounds: f32,
pub collision_radius: f32,
pub max_velocity: f32,
pub phase: SimulationPhase,
pub mode: SimulationMode,
}Note: Some physics parameters like gravity_strength and center_attraction_strength are part of PhysicsSettings within the main AppFullSettings and are used to influence the SimulationParams at runtime, but are not direct fields of this struct. The viewport_bounds, collision_radius, max_velocity, enable_bounds fields are directly part of SimulationParams in src/models/simulation_params.rs and are influenced by PhysicsSettings.
- Configuring the physics engine for graph layout.
- Allowing real-time adjustment of simulation behavior.
- Defining boundary conditions for the simulation space.
The server defines two main structures for managing UI-related settings:
-
UserSettings(fromsrc/models/user_settings.rs): This structure is user-specific and primarily stores a user'spubkeyand their personalizedUISettings(which itself containsvisualisation,system, andxrsettings relevant to the client). It's used for persisting individual user preferences.// In src/models/user_settings.rs #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UserSettings { pub pubkey: String, pub settings: UISettings, // The actual client-facing settings structure pub last_modified: i64, // Unix timestamp }
-
UISettings(fromsrc/config/mod.rs): This structure represents the actual set of UI configurations that are sent to the client (serialized as camelCase JSON). It's derived from the globalAppFullSettingsfor public/default views or from a specific user'sUserSettings.// In src/config/mod.rs #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct UISettings { pub visualisation: VisualisationSettings, // Sourced from AppFullSettings.visualisation pub system: UISystemSettings, // Contains client-relevant parts of AppFullSettings.system pub xr: XRSettings, // Sourced from AppFullSettings.xr // Note: AuthSettings from AppFullSettings are used server-side; client gets tokens/features. // AI service configurations (like API keys) are NOT part of UISettings. // Client interacts with AI services via API endpoints; server uses ProtectedSettings for keys. } #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct UISystemSettings { // Contains only the client-relevant parts of ServerSystemConfigFromFile pub websocket: ClientWebSocketSettings, // Derived from ServerFullWebSocketSettings pub debug: DebugSettings, // Client-safe debug flags // persistSettings and customBackendUrl are client-side settings, // but their server-side counterparts might influence these. }
- Clarification:
LayoutConfigandThemeConfigare not distinct top-level structures withinUISettings.- Theme-related aspects (colors, styles) are primarily part of
VisualisationSettings(e.g.,visualisation.rendering.backgroundColor,visualisation.nodes.baseColor). - Layout aspects are generally managed client-side or are an emergent property of the physics simulation and camera settings.
- Theme-related aspects (colors, styles) are primarily part of
- AI Settings: AI service configurations (API keys, model choices, endpoints) are not part of
UISettingssent to the client. The client interacts with AI services via dedicated API endpoints. The server manages AI API keys and configurations withinAppFullSettings(for general AI behavior) andProtectedSettings(for sensitive keys, often user-specific).
- Clarification:
- User-Specific Settings (
UserSettings): Saved to individual YAML files (e.g.,/app/user_settings/<pubkey>.yaml). - Global/Default Settings (
AppFullSettingsfrom whichUISettingscan be derived): Saved insettings.yaml.
This structure holds sensitive server-side configurations that are not directly exposed to clients but are used internally by the server.
Core Structure (from src/models/protected_settings.rs)
// In src/models/protected_settings.rs
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ProtectedSettings {
// These fields mirror parts of AppFullSettings.system but are managed separately for security/persistence.
pub network: ProtectedNetworkConfig, // Contains bind_address, port etc.
pub security: ServerSecurityConfig, // Contains allowed_origins, session_timeout etc. (often reuses SecuritySettings from config/mod.rs)
pub websocket_server: ProtectedWebSocketServerConfig, // Contains server-specific WebSocket settings
// User management and API keys
pub users: std::collections::HashMap<String, NostrUser>, // Keyed by Nostr pubkey (hex)
pub default_api_keys: ApiKeys, // Default API keys for services if no user-specific key
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct NostrUser {
pub pubkey: String, // Hex public key
pub npub: Option<String>,
pub is_power_user: bool,
pub api_keys: Option<ApiKeys>, // User-specific API keys
pub user_settings_path: Option<String>, // Path to their persisted UserSettings YAML
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ApiKeys {
pub perplexity: Option<String>,
pub openai: Option<String>,
pub ragflow: Option<String>,
// Potentially other AI service keys
}
// ProtectedNetworkConfig, ServerSecurityConfig (may reuse config::SecuritySettings),
// and ProtectedWebSocketServerConfig are also defined in this module or imported.- Management of server network configurations.
- Security policies (CORS, session timeouts).
- WebSocket server parameters.
- Storage of Nostr user profiles, including their individual API keys for AI services.
- Default API keys for services if no user-specific key is available.
The metadata store is responsible for holding information about each processed file (node) in the knowledge graph.
Core Structure (from src/models/metadata.rs)
The MetadataStore is a type alias for HashMap<String, Metadata>, where the key is typically a unique identifier for the content (e.g., file path or a derived ID).
// In src/models/metadata.rs
pub type MetadataStore = std::collections::HashMap<String, Metadata>;The Metadata struct contains details for each processed file/node:
// In src/models/metadata.rs
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
pub file_name: String, // Original file name
pub file_size: u64, // File size in bytes (ensure type matches actual usage, e.g., u64)
pub node_size: f64,
pub hyperlink_count: usize,
pub sha1: Option<String>, // SHA1 hash of the file content, optional
pub node_id: String, // Unique identifier for the graph node (often derived from file_name or path)
pub last_modified: Option<i64>, // Unix timestamp (seconds), optional
// AI Service related fields
pub perplexity_link: Option<String>, // Link to Perplexity discussion/page if available
pub last_perplexity_process_time: Option<i64>, // Timestamp of last Perplexity processing, optional
pub topic_counts: Option<std::collections::HashMap<String, usize>>, // Counts of topics/keywords, optional
// Other potential fields:
// pub title: Option<String>,
// pub tags: Option<Vec<String>>,
// pub content_type: Option<String>, // e.g., "markdown", "pdf"
// pub created_at: Option<i64>,
}- The
MetadataStoreitself is aHashMap. Relationships between nodes (edges) are typically stored separately inGraphDatawithinGraphService. Statistics are usually computed on-the-fly or by dedicated analysis processes rather than being stored directly inMetadataStore. - The
node_sizefield is calculated on the server based on file size and stored in the metadata for potential use by the client or other services.
- The
MetadataStore(as aHashMap) supports standard CRUD operations forMetadataentries. - Relationship management and statistics tracking are typically handled by services like
GraphServiceorFileServiceby processing the contents of theMetadataStore.
Shared mutable data structures like MetadataStore and settings objects are wrapped in Arc<RwLock<T>> within AppState to ensure thread-safe access.
// Example from app_state.rs
// pub metadata: Arc<RwLock<MetadataStore>>,
// pub settings: Arc<RwLock<AppFullSettings>>,Data models are designed to be serializable and deserializable using serde for various formats like JSON (for API communication) and YAML (for configuration files). The #[serde(rename_all = "camelCase")] attribute is often used for client compatibility.
Validation logic is typically implemented within the services that manage these models or during the deserialization process (e.g., using serde attributes or custom validation functions).