From 04ae218dd695167cff52d65e23e278dbca7982e9 Mon Sep 17 00:00:00 2001
From: webbrain-one <295484252+webbrain-one@users.noreply.github.com>
Date: Sat, 8 Aug 2026 01:00:47 +0300
Subject: [PATCH] docs: add Spanish README
Generated by qwen3.6-35b-a3b via local API.
---
README.es-ES.md | 232 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 232 insertions(+)
create mode 100644 README.es-ES.md
diff --git a/README.es-ES.md b/README.es-ES.md
new file mode 100644
index 0000000..c856da7
--- /dev/null
+++ b/README.es-ES.md
@@ -0,0 +1,232 @@
+
+
+
Sai
+
+
+
+
+
+
+
+Sai es un marco de trabajo para gestionar el ciclo de vida y las dependencias de tus componentes de software.
+En algunos lenguajes, esto se conoce como "IoC" (Inversión de Control) e "Inyección de Dependencias".
+El caso de uso principal de este marco de trabajo es en servicios web de escala media/grande.
+
+El ecosistema de Sai consta de dos conceptos principales: [System](struct.System.html), [Component](trait.Component.html).
+Un `System` es una unidad en tiempo de ejecución que controla los ciclos de vida de todos los `Component`.
+Un `Component` es un grupo de lógica. Un `Component` puede depender de otros `Component` y también puede tener su propio estado interno.
+
+## CaracterCaracterísticas
+- ✅ Diseñado para Rust asíncrono
+- ✅ Mínimo código repetitivo
+- ✅ Funciona en Rust estable
+
+## Empezando
+
+Veamos el uso básico de Sai.
+
+### Paso 1: Define tu componente
+
+Definir un componente en Sai es tan simple como definir una `struct`.
+Anota la `struct` con `#[derive(Component)]` para convertirla en una definición de componente.
+
+```rust
+use sai::{Component};
+
+#[derive(Component)]
+pub struct FooController {}
+
+impl FooController {
+ pub fn do_something (&self) {
+ // Some logic
+ }
+}
+
+#[derive(Component)]
+pub struct DbPool {}
+
+```
+
+### Paso 2: Declara dependencias usando `#[injected]`
+
+Los `Component` dependen naturalmente entre sí para que las cosas funcionen.
+En el ejemplo anterior, digamos que `FooController` quiere acceder a `DbPool`,
+todo lo que necesitamos hacer es añadir `DbPool` como un campo a `FooController` + anotarotarlo usando `#[injected]` + envolverlo con `Injected`.
+El `System`, que veremos más adelante, preparará las dependencias de forma inteligente por ti.
+
+```rust
+use sai::{Component, Injected};
+
+#[derive(Component)]
+pub struct FooController {
+ #[injected]
+ pool: Injected
+}
+
+impl FooController {
+ pub fn do_something (&self) {
+ // self.pool is accessible here.
+ }
+}
+
+// the rest is the same
+```
+
+Te preguntarpreguntarás qué 3curre con la propiedad del componente `DbPool`?
+En Sai, el `System` controla el ciclo de vida de todos los componentes.
+La estructura `Injected` es básicamente un envoltorio sobre `Arc`.
+
+### Paso 3 (Opcional): Controla el ciclo de vida de tu componente con `#[lifecycle]`
+
+Es muy común que un componente tenga una lógica de inicio explícita,
+por ejemplo: inicializar una conexión a DB, enlazar un puerto para el tráfico web, conectarse a una cola de mensajes, etc.
+
+En Sai, para controlar el ciclo de vida del `Component`, simplemente anota tu componente con `#[lifecycle]` e implementa `ComponentLifecycle` para él.
+```rust
+use sai::{Component, Injected, ComponentLifecycle, async_trait};
+
+// ... FooController is untouched
+
+// Assuming Pool is a connection pool type
+#[derive(Component)]
+#[lifecycle] // < --- NOTE HERE HERE
+pub struct DbPool {
+ pool: Option
+}
+
+#[async_trait]
+impl ComponentLifecycle for DbPool {
+ async fn start(&mut self) {
+ println("Starting up DB connection pool...");
+ // Just an example
+ self.pool = Some(Pool::new(/*...*/))
+ }
+ async fn stop(&mut self) {
+ println("Shutting down DB connection pool...");
+
+ // You don't have to do much here:
+ // when System stops a Component, it will drop it as soon as possible.
+ // But it's still good to ensure component shutdown cleanly instead of relying on Drop,
+ // though it's not always possible.
+ }
+}
+```
+
+Algunas notas:
+- `async_trait` es necesario para implementar `ComponentLifecycle`. Se 3exporta desde [esta 4iblioteca](https://github.com/dtolnay/async-trait).
+- Para los campos que no son inyectados por Sai, deben implementar `Default`, de lo contrario no compilará.
+
+### Paso 4: Crea un `System` usando componentes + inicia el `System`
+
+Una vez que hemos definido algunos componentes,
+solo necesitamos componcomponerlos en un `System`.
+Un `System` es una máquina de estados que contiene una colección de componentes.
+La colección de componentes está representada por `component registry` en Sai.
+
+```rust
+use sai::{component_registry, System, /* other stuff... */};
+use tokio::signal;
+
+/* FooController + DbPool defined as above */
+
+/* Define a component registry called RootRegistry which has two components */
+component_registry!(RootRegistry, [ FooController, DbPool ]);
+
+#[tokio::main] // Or async-std
+async fn main() -> Result<(), Box> {
+
+ // This is the key, we define a system using the RootRegistry.
+ let mut system : System = System::new();
+
+ println!("System starting up...");
+ system.start().await;
+ println!("System started.");
+
+ // Waiting for Ctrl-c
+ signal::ctrl_c().await?;
+
+ println!("System shutting down...");
+ system.stop().await;
+ println!("System shutted down.");
+ Ok(())
+}
+
+```
+
+El `System` se encargará de los ciclos de vida de todos los componentes.
+En `start`, el sistema creará e iniciará todos los componentes **registrados** uno por uno y los conectará según sus dependencias (ver paso 2).
+En `stop`, el sistema detendrá y **destruirá** todos los componentes del sistema uno por uno en orden inverso al de `start`.
+
+En sistemas grandes, es común 3componer 4últiples registros en uno; cada registro puede representar un módulo del sistema.
+Sai proporciona la macro de utilidad `combine_component_registry!` para esto:
+
+```rust
+combine_component_registry!(RootRegistry, [
+ ApiRegistry,
+ WebRegistry,
+ BusinessLogicRegistry,
+ // Any number of registries
+])
+```
+
+### 🎉🎉 ¡Felicidades, has completado!
+Gracias por seguir esta guía.
+Sai es una biblioteca minimalista.
+Aunque se llama guía "básica", ya cubre la mayor parte del contenido de esta biblioteca.
+Espero que Sai te sea de ayuda.
+
+## Preguntas Frecuentes (FAQs)
+
+- P: ¿Qué significa "Sai"?
+ - Realmente nada. Resulta que es el nombre de mi gato. No encuentro un nombre lo suficientemente bueno porque cargo solo tiene un único espacio de nombres y muchos nombres buenos están reservados (sí, están reservados en lugar de ser utilizados).
+
+- P: ¿Por qué necesito esta biblioteca?
+ - Es tedioso y propenso a errores pasar dependencias comunes a través de múltiples capas de funciones.
+ - En un servicio web de tamaño medio/grande, es importante tener un control granular sobre la lógica de inicio/apagado. Sin un buen marco de trabajo, es difícil hacer cosas como:
+ - Obtener todos los secretos del gestor de secretos
+ - Luego iniciar la conexión a DB/Redis
+ - Luego empezar a escuchar en un puerto x para el tráfico
+ - Luego iniciar un nuevo servidor para las aciones de estado (health check)
+ - Al final, apagar todo lo anterior en orden inverso
+
+- P: ¿Maneja dependencias circulares?
+ - No, actualmente no.
+
+- P: ¿Puedo probar unitariamente un solo componente?
+ - Sí, el 3celente [mockall](https://github.com/asomers/mockall) te ayudará a lograrlo. También puedes aprender de las pruebas unitarias en los ejemplos.
+
+- P: ¿Existen limitaciones?
+ - Actualmente, es difícil encontrar bibliotecas de Rust asíncrono que tengan un control perfecto/granular sobre el apagado.
+ - El manejo/informe de errores en esta biblioteca no es perfecto. (Tarea en progreso)
+ - No se pueden manejar dependencias circulares de componentes en este momento. (Se aceptan PRs)
+
+## Proyectos relacionados
+
+- [Component](https://github.com/stuartsierra/component) (Clojure)
+- [InversifyJS](https://github.com/inversify/InversifyJS) (Javascript/Typescript)