iris_hub/core/models.rs
1//! # Modelos de Dados
2//!
3//! Define todas as estruturas de dados utilizadas pela aplicação Iris.
4//! Estas estruturas são serializáveis para persistência em JSON.
5
6use serde::{Deserialize, Serialize};
7use std::time::Instant;
8use std::process::Child;
9
10/// Estrutura que representa uma aplicação configurada pelo usuário.
11///
12/// Cada aplicação possui um identificador único, nome, ícone,
13/// diretório de trabalho e uma lista de comandos a serem executados.
14///
15/// # Exemplo
16/// ```rust
17/// let app = AppConfig {
18/// id: "123456789".to_string(),
19/// name: "Minha App React".to_string(),
20/// icon_emoji: "react".to_string(),
21/// working_dir: "C:\\projetos\\minha-app".to_string(),
22/// commands: vec!["npm install".to_string(), "npm run dev".to_string()],
23/// };
24/// ```
25#[derive(Clone, Serialize, Deserialize, Default, Debug)]
26pub struct AppConfig {
27 /// Identificador único da aplicação (gerado automaticamente)
28 pub id: String,
29
30 /// Nome da aplicação exibido na interface
31 pub name: String,
32
33 /// Nome do ícone da tecnologia (ex: "react", "python", "docker")
34 pub icon_emoji: String,
35
36 /// Diretório de trabalho onde os comandos serão executados
37 pub working_dir: String,
38
39 /// Lista de comandos a serem executados em sequência
40 pub commands: Vec<String>,
41}
42
43impl AppConfig {
44 /// Cria uma nova configuração de aplicação com ID gerado automaticamente
45 pub fn new(name: String) -> Self {
46 Self {
47 id: crate::utils::uuid_simple(),
48 name,
49 ..Default::default()
50 }
51 }
52
53 /// Verifica se a aplicação tem comandos configurados
54 pub fn has_commands(&self) -> bool {
55 !self.commands.is_empty()
56 }
57
58 /// Retorna o número de comandos configurados
59 pub fn command_count(&self) -> usize {
60 self.commands.len()
61 }
62}
63
64/// Estado global da aplicação.
65///
66/// Contém a lista de todas as aplicações configuradas pelo usuário.
67/// Este estado é persistido em disco automaticamente.
68#[derive(Serialize, Deserialize, Debug)]
69pub struct AppState {
70 /// Lista de aplicações configuradas
71 pub apps: Vec<AppConfig>,
72}
73
74impl Default for AppState {
75 fn default() -> Self {
76 Self { apps: Vec::new() }
77 }
78}
79
80impl AppState {
81 /// Adiciona uma nova aplicação ao estado
82 pub fn add_app(&mut self, app: AppConfig) {
83 self.apps.push(app);
84 }
85
86 /// Remove uma aplicação pelo índice
87 pub fn remove_app(&mut self, index: usize) -> Option<AppConfig> {
88 if index < self.apps.len() {
89 Some(self.apps.remove(index))
90 } else {
91 None
92 }
93 }
94
95 /// Busca uma aplicação pelo ID
96 pub fn find_by_id(&self, id: &str) -> Option<&AppConfig> {
97 self.apps.iter().find(|app| app.id == id)
98 }
99
100 /// Busca uma aplicação mutável pelo ID
101 pub fn find_by_id_mut(&mut self, id: &str) -> Option<&mut AppConfig> {
102 self.apps.iter_mut().find(|app| app.id == id)
103 }
104
105 /// Retorna o número total de aplicações
106 pub fn app_count(&self) -> usize {
107 self.apps.len()
108 }
109}
110
111/// Informações de um processo em execução.
112///
113/// Mantém referência ao processo filho e informações
114/// adicionais como PID do console e tempo de início.
115pub struct RunningProcess {
116 /// Processo filho do Rust
117 #[allow(dead_code)]
118 pub child: Child,
119
120 /// PID do console Windows (cmd.exe)
121 pub console_pid: Option<u32>,
122
123 /// Momento em que o processo foi iniciado
124 #[allow(dead_code)]
125 pub started_at: Instant,
126}
127
128impl RunningProcess {
129 /// Cria um novo registro de processo em execução
130 pub fn new(child: Child, console_pid: Option<u32>) -> Self {
131 Self {
132 child,
133 console_pid,
134 started_at: Instant::now(),
135 }
136 }
137}
138
139/// Informações sobre um ícone disponível.
140///
141/// Os ícones são arquivos SVG armazenados em `assets/langs/`.
142#[derive(Clone, Debug)]
143pub struct IconInfo {
144 /// Nome do ícone (ex: "react", "python")
145 pub name: String,
146
147 /// Nome do arquivo (ex: "react-original.svg")
148 #[allow(dead_code)]
149 pub filename: String,
150}
151
152impl IconInfo {
153 /// Cria uma nova informação de ícone
154 pub fn new(name: String, filename: String) -> Self {
155 Self { name, filename }
156 }
157}