diff --git a/docs/fn_operations.md b/docs/fn_operations.md new file mode 100644 index 00000000..ea246ac2 --- /dev/null +++ b/docs/fn_operations.md @@ -0,0 +1,256 @@ +# fn_operations — Schema de inteligencia operacional + +Base de datos local por proyecto. Cada proyecto tiene su propio archivo `.db` independiente. +Referencia IDs del registry central (`fn_registry`) pero no los duplica — solo apunta a ellos. + +--- + +## Propósito + +El registry almacena **lo que sabes hacer**. +fn_operations almacena **lo que has hecho y cómo fluye** en un proyecto concreto. + +| | fn_registry | fn_operations | +|---|---|---| +| **Naturaleza** | Conocimiento estático | Conocimiento dinámico | +| **Contenido** | Lo que sabes hacer | Lo que has hecho y cómo fluye | +| **Scope** | Compartida entre todos los proyectos | Local a cada proyecto — un `.db` por proyecto | +| **Tablas** | `functions`, `types` | `entities`, `relations`, `relation_inputs` | +| **Cuándo cambia** | Al añadir código al registry | En cada proyecto activo | + +--- + +## Estructura de directorios + +``` +fn-registry/ + fn_operations/ + fn_operations.md ← este archivo + project_template/ + operations.db ← plantilla vacía con schema y WAL mode aplicados + migrations/ + 001_init.sql ← script de creación de tablas +``` + +--- + +## Tabla: entities + +Una entity es una instancia concreta de un tipo del registry dentro del contexto de un proyecto. +No es el tipo en abstracto — es el dato real que fluye: `ticks_btcusdt_2024`, `ohlcv_1h_binance`, `user_session_web`. + +El tipo del registry (`type_ref`) aporta conocimiento heredado — campos, estructura, semántica algebraica. +La entity aporta conocimiento contextual — qué rol juega aquí, de dónde viene, qué propiedades específicas tiene. + +``` +type_ref → lo que la entidad ES (heredado del registry) +metadata → lo que la entidad TIENE (específico de este contexto) +``` + +| Campo | Tipo | Descripción | Notas / Restricciones | +|---|---|---|---| +| `id` | string | Identificador único de la entidad en el proyecto. | Formato: `{name}_{context}` ej: `ticks_btcusdt_2024`. Único dentro del proyecto. | +| `name` | string | Nombre semántico de la entidad. | Descriptivo y específico al dominio del proyecto. Obligatorio. | +| `type_ref` | string | ID del tipo del registry que modela esta entidad. | Referencia a `types.id` en `fn_registry`. Obligatorio. | +| `status` | enum | Estado actual de la entidad. | `active` \| `stale` \| `corrupted` \| `archived` | +| `description` | text | Qué representa esta entidad en el contexto del proyecto. | No qué es el tipo en abstracto, sino qué rol juega aquí. | +| `domain` | string | Área de dominio dentro del proyecto. | Ej: `market_data`, `auth`, `reporting`. | +| `tags` | []string | Etiquetas libres para búsqueda y agrupación. | | +| `source` | string | Origen del dato. | Obligatorio. Ej: `binance_api`, `csv_upload`, `user_input`, `pipeline_output`. | +| `metadata` | json | Propiedades específicas del contexto no capturadas por el tipo. | Valores concretos de los campos del tipo. Ej: `{"pair":"BTCUSDT","exchange":"binance"}`. | +| `notes` | text | Contexto extra libre sobre la entidad. | Para el agente o para ti. Decisiones, observaciones, advertencias, historial informal. | +| `created_at` | datetime | Fecha de registro de la entidad. | ISO 8601. Generado automáticamente. | +| `updated_at` | datetime | Fecha de última modificación. | ISO 8601. Actualizado automáticamente. | + +### Valores de status — entities + +| Valor | Significado | +|---|---| +| `active` | Dato en uso, actualizado y fiable. | +| `stale` | Existe pero puede estar desactualizado. El agente debe verificar antes de usar. | +| `corrupted` | Se sabe que tiene problemas de integridad. No usar en pipelines. | +| `archived` | Ya no se usa activamente. Se conserva por trazabilidad histórica. | + +### Reglas de integridad — entities + +| Condición | Regla | +|---|---| +| `type_ref` | Debe existir en `fn_registry.types.id`. Sin referencias huérfanas. | +| `id` | Único dentro del proyecto. Formato `{name}_{context}`. | +| `source` | Obligatorio. Todo dato tiene un origen conocido. | +| `name` | Obligatorio. Sin espacios, snake_case. | +| `metadata` | JSON válido. Debe contener los valores de los campos definidos por el tipo del registry. | +| `status: corrupted` | El agente nunca debe usar esta entidad como input de una relation activa. | + +--- + +## Tabla: relations + +Una relation describe cómo una entidad se conecta o transforma en otra. Puede documentar una +transformación técnica a través de una función del registry, o una relación puramente semántica +sin función asociada. El campo `name` expresa el significado humano de la conexión. + +``` +juan (type: person) → CONOCE A → paula (type: person) +ticks → AGREGA → ohlcv_1h (via: tick_to_ohlcv_go_finance) +``` + +Para relaciones que consumen **múltiples entidades** (joins, merges, agregaciones multi-fuente), +se usa la tabla `relation_inputs` en lugar de `from_entity`. Ver sección correspondiente. + +| Campo | Tipo | Descripción | Notas / Restricciones | +|---|---|---|---| +| `id` | string | Identificador único de la relación. | Formato: `{from}__to__{to}__via__{fn}`. Legible sin joins. | +| `name` | string | Etiqueta semántica de la relación. | El verbo o concepto que describe la conexión. Ej: `CONOCE A`, `TRANSFORMA`, `PRODUCE`, `DEPENDE DE`. Obligatorio. | +| `from_entity` | string | ID de la entidad origen para relaciones simples (1-a-1). | Referencia a `entities.id`. Opcional si se usa `relation_inputs`. | +| `to_entity` | string | ID de la entidad destino. | Referencia a `entities.id`. Obligatorio. | +| `via` | string | ID de la función o pipeline del registry que realiza la transformación. | Referencia a `functions.id` en `fn_registry`. Opcional — vacío si la relación es puramente semántica. | +| `description` | text | Qué ocurre en esta conexión en el contexto del proyecto. | No qué hace la función en abstracto, sino qué significa aquí. | +| `purity` | enum | Naturaleza de la transformación. | `pure` \| `impure`. Si `via` está informado, debe ser consistente con `via.purity` en el registry. | +| `direction` | enum | Dirección semántica de la relación. | `unidirectional` \| `bidirectional` \| `inverse`. Ver valores abajo. | +| `weight` | float | Ponderación opcional de la relación. | Rango `0.0 – 1.0`. Permite queryar "relaciones con peso > 0.8". Opcional. | +| `status` | enum | Estado del flujo. | `designed` \| `implemented` \| `tested` \| `running` \| `deprecated` | +| `started_at` | datetime | Cuándo empezó el flujo realmente. | ISO 8601. Distinto de `created_at` — ese es cuándo lo documentaste. | +| `ended_at` | datetime | Cuándo terminó o dejó de ejecutarse el flujo. | ISO 8601. Vacío si sigue activo. | +| `order` | int | Posición en el pipeline si forma parte de una secuencia ordenada. | Opcional. Permite reconstruir el grafo en orden de ejecución. | +| `tags` | []string | Etiquetas libres. | | +| `notes` | text | Observaciones, decisiones de diseño, problemas conocidos. | Libre. El agente lee esto para entender contexto histórico del flujo. | +| `created_at` | datetime | Fecha de registro de la relación. | ISO 8601. Generado automáticamente. | +| `updated_at` | datetime | Fecha de última modificación. | ISO 8601. Actualizado automáticamente. | + +### Valores de direction + +| Valor | Significado | +|---|---| +| `unidirectional` | A → B. La relación fluye en un solo sentido. Valor por defecto. | +| `bidirectional` | A ↔ B. La relación es simétrica — vale en ambos sentidos. Ej: `CONOCE A`. | +| `inverse` | La relación se documenta de B a A pero su lectura natural es de A a B. Útil para linaje inverso. | + +### Valores de status — relations + +| Valor | Significado | +|---|---| +| `designed` | Flujo planificado. Existe en el grafo de arquitectura pero no hay código todavía. | +| `implemented` | Código escrito. No verificado en este contexto de proyecto aún. | +| `tested` | Verificado en este proyecto. Los datos fluyen correctamente. | +| `running` | Activo en producción o en uso continuo. | +| `deprecated` | Ya no se usa. Se mantiene por trazabilidad histórica. | + +### Reglas de integridad — relations + +| Condición | Regla | +|---|---| +| `name` | Obligatorio. Describe el verbo semántico de la relación. | +| `from_entity` | Si informado, debe existir en `entities.id`. Vacío si se usa `relation_inputs`. | +| `from_entity` o `relation_inputs` | Al menos uno de los dos debe estar presente. Una relation sin origen es inválida. | +| `to_entity` | Debe existir en `entities.id`. Obligatorio. | +| `via` | Si informado, debe existir en `fn_registry.functions.id`. | +| `purity` | Si `via` está informado, debe ser consistente con `via.purity` en el registry. | +| `weight` | Si informado, debe estar en el rango `0.0 – 1.0`. | +| `from_entity != to_entity` | Una entidad no puede relacionarse consigo misma. | +| `started_at` / `ended_at` | Si ambos informados, `started_at` debe ser anterior a `ended_at`. | +| `id` | Único dentro del proyecto. | +| **Sin ciclos** | El CLI valida al insertar que la nueva relation no crea un ciclo en el grafo. Si lo crea, la inserción se rechaza. SQLite no detecta ciclos — esta validación ocurre en la capa de aplicación. | + +--- + +## Tabla: relation_inputs + +Tabla intermedia para relaciones que consumen **múltiples entidades simultáneamente** — joins, +merges, agregaciones multi-fuente. Cuando una relation usa `relation_inputs`, el campo +`from_entity` en `relations` se deja vacío. + +``` +join(ticks_btcusdt, metadata_binance) → ENRIQUECE → ohlcv_enriquecido + ↑ input role: "base" ↑ to_entity + ↑ input role: "lookup" +``` + +| Campo | Tipo | Descripción | Notas / Restricciones | +|---|---|---|---| +| `id` | string | Identificador único del input. | Generado automáticamente. | +| `relation_id` | string | ID de la relation a la que pertenece este input. | Referencia a `relations.id`. Obligatorio. | +| `entity_id` | string | ID de la entidad que actúa como input. | Referencia a `entities.id`. Obligatorio. | +| `role` | string | Rol semántico de este input en la relación. | Ej: `base`, `lookup`, `filter`, `left`, `right`. Obligatorio. Permite al agente entender cómo se usa cada input. | +| `order` | int | Orden del input si la relación es sensible al orden. | Opcional. Ej: en un join `left`/`right` el orden importa. | + +### Reglas de integridad — relation_inputs + +| Condición | Regla | +|---|---| +| `relation_id` | Debe existir en `relations.id`. | +| `entity_id` | Debe existir en `entities.id`. | +| `role` | Obligatorio. Sin rol el agente no puede razonar sobre cómo se usa el input. | +| Mínimo 2 inputs | Una relation con `relation_inputs` debe tener al menos 2 entradas. Si solo hay una, usar `from_entity` en su lugar. | + +--- + +## Referencias cruzadas completas + +| Campo origen | → | Destino | +|---|---|---| +| `entities.type_ref` | → | `fn_registry → types.id` | +| `relations.from_entity` | → | `entities.id` (opcional) | +| `relations.to_entity` | → | `entities.id` | +| `relations.via` | → | `fn_registry → functions.id` (opcional) | +| `relation_inputs.relation_id` | → | `relations.id` | +| `relation_inputs.entity_id` | → | `entities.id` | + +--- + +## Ejemplo — pipeline de market data + +### Entities + +| id | type_ref | status | source | metadata | +|---|---|---|---|---| +| `ticks_btcusdt_2024` | `tick_go_finance` | `active` | `binance_api` | `{"pair":"BTCUSDT","exchange":"binance"}` | +| `metadata_binance` | `exchange_meta_go_finance` | `active` | `binance_api` | `{"version":"v3"}` | +| `ohlcv_1h_btcusdt` | `ohlcv_go_finance` | `active` | `pipeline_output` | `{"interval":"1h","pair":"BTCUSDT"}` | +| `sma_20_btcusdt` | `float64_slice_go_core` | `active` | `pipeline_output` | `{"period":20,"field":"close"}` | + +### Relations simples + +| name | from_entity | to_entity | via | direction | status | weight | +|---|---|---|---|---|---|---| +| `CALCULA` | `ohlcv_1h_btcusdt` | `sma_20_btcusdt` | `sma_go_finance` | `unidirectional` | `tested` | 1.0 | + +### Relation con múltiples inputs (relation_inputs) + +**Relation:** `id: ticks_y_meta__to__ohlcv__via__enrich`, `name: ENRIQUECE`, `to_entity: ohlcv_1h_btcusdt` + +| relation_id | entity_id | role | order | +|---|---|---|---| +| `ticks_y_meta__to__ohlcv__via__enrich` | `ticks_btcusdt_2024` | `base` | 1 | +| `ticks_y_meta__to__ohlcv__via__enrich` | `metadata_binance` | `lookup` | 2 | + +### Grafo resultante + +``` +[ticks_btcusdt_2024] ──┐ + ├─ ENRIQUECE (impure · running) ──→ [ohlcv_1h_btcusdt] +[metadata_binance] ──┘ ↓ + CALCULA (pure · tested) + ↓ + [sma_20_btcusdt] +``` + +--- + +## Ejemplo — relaciones semánticas puras (sin via) + +``` +[juan] (type: person) → CONOCE A (bidirectional, weight: 0.9) → [paula] +[servicio_auth] → DEPENDE DE (unidirectional, weight: 1.0) → [bbdd_usuarios] +[modelo_riesgo] → ALIMENTA (unidirectional, weight: 0.7) → [dashboard_trading] +``` + +--- + +## Escalabilidad + +| Fase | BBDD | Cuándo migrar | +|---|---|---| +| Inicial | SQLite + WAL mode | Proyectos personales, un agente escribiendo | +| Crecimiento | PostgreSQL | Múltiples agentes escribiendo concurrentemente | +| Analítico | ClickHouse | Millones de operaciones, dashboards de uso | diff --git a/functions/core/all_slice.go b/functions/core/all_slice.go new file mode 100644 index 00000000..08c82c63 --- /dev/null +++ b/functions/core/all_slice.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// All devuelve true si todos los elementos del slice cumplen el predicado. +func All[T any](slice []T, predicate func(T) bool) bool { + // stub + return false +} diff --git a/functions/core/all_slice.md b/functions/core/all_slice.md new file mode 100644 index 00000000..90d9b3dc --- /dev/null +++ b/functions/core/all_slice.md @@ -0,0 +1,32 @@ +--- +name: all_slice +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func All[T any](slice []T, predicate func(T) bool) bool" +description: "Devuelve true si todos los elementos del slice cumplen el predicado." +tags: [slice, functional, generic, predicate] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/all_slice.go" +--- + +## Ejemplo + +```go +result := All([]int{2, 4, 6}, func(x int) bool { return x%2 == 0 }) +// result = true +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/any_slice.go b/functions/core/any_slice.go new file mode 100644 index 00000000..8aadde79 --- /dev/null +++ b/functions/core/any_slice.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Any devuelve true si al menos un elemento del slice cumple el predicado. +func Any[T any](slice []T, predicate func(T) bool) bool { + // stub + return false +} diff --git a/functions/core/any_slice.md b/functions/core/any_slice.md new file mode 100644 index 00000000..99edcf93 --- /dev/null +++ b/functions/core/any_slice.md @@ -0,0 +1,32 @@ +--- +name: any_slice +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Any[T any](slice []T, predicate func(T) bool) bool" +description: "Devuelve true si al menos un elemento del slice cumple el predicado." +tags: [slice, functional, generic, predicate] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/any_slice.go" +--- + +## Ejemplo + +```go +result := Any([]int{1, 2, 3}, func(x int) bool { return x > 2 }) +// result = true +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/compose2.go b/functions/core/compose2.go new file mode 100644 index 00000000..3d77abc0 --- /dev/null +++ b/functions/core/compose2.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Compose2 compone dos funciones de derecha a izquierda. +func Compose2[A, B, C any](f2 func(B) C, f1 func(A) B) func(A) C { + // stub + return nil +} diff --git a/functions/core/compose2.md b/functions/core/compose2.md new file mode 100644 index 00000000..9fabdbd9 --- /dev/null +++ b/functions/core/compose2.md @@ -0,0 +1,34 @@ +--- +name: compose2 +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Compose2[A, B, C any](f2 func(B) C, f1 func(A) B) func(A) C" +description: "Compone dos funciones de derecha a izquierda. compose2(g, f)(x) = g(f(x))." +tags: [functional, composition, generic] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/compose2.go" +--- + +## Ejemplo + +```go +double := func(x int) int { return x * 2 } +toString := func(x int) string { return fmt.Sprintf("%d", x) } +doubleStr := Compose2(toString, double) +result := doubleStr(5) // "10" +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/const_func.go b/functions/core/const_func.go new file mode 100644 index 00000000..7109e049 --- /dev/null +++ b/functions/core/const_func.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Const devuelve una funcion que siempre retorna el valor dado, ignorando su argumento. +func Const[T, U any](value T) func(U) T { + // stub + return nil +} diff --git a/functions/core/const_func.md b/functions/core/const_func.md new file mode 100644 index 00000000..420fa9c6 --- /dev/null +++ b/functions/core/const_func.md @@ -0,0 +1,32 @@ +--- +name: const_func +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Const[T, U any](value T) func(U) T" +description: "Devuelve una funcion que siempre retorna el valor dado, ignorando su argumento." +tags: [functional, generic, const] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/const_func.go" +--- + +## Ejemplo + +```go +always42 := Const[int, string](42) +result := always42("ignored") // 42 +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/curry2.go b/functions/core/curry2.go new file mode 100644 index 00000000..90b4eddb --- /dev/null +++ b/functions/core/curry2.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Curry2 transforma una funcion de dos argumentos en forma currificada. +func Curry2[A, B, C any](f func(A, B) C) func(A) func(B) C { + // stub + return nil +} diff --git a/functions/core/curry2.md b/functions/core/curry2.md new file mode 100644 index 00000000..ce05416a --- /dev/null +++ b/functions/core/curry2.md @@ -0,0 +1,34 @@ +--- +name: curry2 +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Curry2[A, B, C any](f func(A, B) C) func(A) func(B) C" +description: "Transforma una funcion de dos argumentos en forma currificada." +tags: [functional, generic, curry] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/curry2.go" +--- + +## Ejemplo + +```go +add := func(a, b int) int { return a + b } +curriedAdd := Curry2(add) +add5 := curriedAdd(5) +result := add5(3) // 8 +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/drop.go b/functions/core/drop.go new file mode 100644 index 00000000..54fddce0 --- /dev/null +++ b/functions/core/drop.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Drop elimina los primeros n elementos de un slice y devuelve el resto. +func Drop[T any](slice []T, n int) []T { + // stub + return nil +} diff --git a/functions/core/drop.md b/functions/core/drop.md new file mode 100644 index 00000000..63e80b79 --- /dev/null +++ b/functions/core/drop.md @@ -0,0 +1,32 @@ +--- +name: drop +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Drop[T any](slice []T, n int) []T" +description: "Elimina los primeros n elementos de un slice y devuelve el resto." +tags: [slice, functional, generic] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/drop.go" +--- + +## Ejemplo + +```go +result := Drop([]int{1, 2, 3, 4, 5}, 2) +// result = [3, 4, 5] +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/find.go b/functions/core/find.go new file mode 100644 index 00000000..db536b7a --- /dev/null +++ b/functions/core/find.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Find devuelve el primer elemento del slice que cumple el predicado, envuelto en Option. +func Find[T any](slice []T, predicate func(T) bool) Option[T] { + // stub + return Option[T]{} +} diff --git a/functions/core/find.md b/functions/core/find.md new file mode 100644 index 00000000..a6add199 --- /dev/null +++ b/functions/core/find.md @@ -0,0 +1,33 @@ +--- +name: find +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Find[T any](slice []T, predicate func(T) bool) Option[T]" +description: "Devuelve el primer elemento del slice que cumple el predicado, envuelto en Option." +tags: [slice, functional, generic, search] +uses_functions: [] +uses_types: [option_go_core] +returns: [option_go_core] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/find.go" +--- + +## Ejemplo + +```go +nums := []int{1, 2, 3, 4, 5} +result := Find(nums, func(n int) bool { return n > 3 }) +// result es Some(4) +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/find_index.go b/functions/core/find_index.go new file mode 100644 index 00000000..fa12ce4b --- /dev/null +++ b/functions/core/find_index.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// FindIndex devuelve el indice del primer elemento que cumple el predicado. +func FindIndex[T any](slice []T, predicate func(T) bool) Option[int] { + // stub + return Option[int]{} +} diff --git a/functions/core/find_index.md b/functions/core/find_index.md new file mode 100644 index 00000000..c30b4156 --- /dev/null +++ b/functions/core/find_index.md @@ -0,0 +1,32 @@ +--- +name: find_index +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func FindIndex[T any](slice []T, predicate func(T) bool) Option[int]" +description: "Devuelve el indice del primer elemento que cumple el predicado, envuelto en Option." +tags: [slice, functional, generic, search] +uses_functions: [] +uses_types: [option_go_core] +returns: [option_go_core] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/find_index.go" +--- + +## Ejemplo + +```go +idx := FindIndex([]int{10, 20, 30}, func(x int) bool { return x > 15 }) +// idx = Some(1) +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/flat_map_slice.go b/functions/core/flat_map_slice.go new file mode 100644 index 00000000..dfd1c376 --- /dev/null +++ b/functions/core/flat_map_slice.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// FlatMapSlice aplica una funcion que devuelve slices a cada elemento y aplana el resultado. +func FlatMapSlice[T, U any](slice []T, f func(T) []U) []U { + // stub + return nil +} diff --git a/functions/core/flat_map_slice.md b/functions/core/flat_map_slice.md new file mode 100644 index 00000000..1fb2a388 --- /dev/null +++ b/functions/core/flat_map_slice.md @@ -0,0 +1,32 @@ +--- +name: flat_map_slice +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func FlatMapSlice[T, U any](slice []T, f func(T) []U) []U" +description: "Aplica una funcion que devuelve slices a cada elemento y aplana el resultado." +tags: [slice, functional, generic, flatmap] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/flat_map_slice.go" +--- + +## Ejemplo + +```go +result := FlatMapSlice([]int{1, 2, 3}, func(x int) []int { return []int{x, x * 10} }) +// result = [1, 10, 2, 20, 3, 30] +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/flatten.go b/functions/core/flatten.go new file mode 100644 index 00000000..9b77161b --- /dev/null +++ b/functions/core/flatten.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Flatten aplana un slice de slices en un unico slice. +func Flatten[T any](slices [][]T) []T { + // stub + return nil +} diff --git a/functions/core/flatten.md b/functions/core/flatten.md new file mode 100644 index 00000000..56542cee --- /dev/null +++ b/functions/core/flatten.md @@ -0,0 +1,32 @@ +--- +name: flatten +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Flatten[T any](slices [][]T) []T" +description: "Aplana un slice de slices en un unico slice." +tags: [slice, functional, generic] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/flatten.go" +--- + +## Ejemplo + +```go +result := Flatten([][]int{{1, 2}, {3, 4}, {5}}) +// result = [1, 2, 3, 4, 5] +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/flip.go b/functions/core/flip.go new file mode 100644 index 00000000..d77c0a8e --- /dev/null +++ b/functions/core/flip.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Flip intercambia el orden de los argumentos de una funcion de dos parametros. +func Flip[A, B, C any](f func(A, B) C) func(B, A) C { + // stub + return nil +} diff --git a/functions/core/flip.md b/functions/core/flip.md new file mode 100644 index 00000000..e06f04d1 --- /dev/null +++ b/functions/core/flip.md @@ -0,0 +1,33 @@ +--- +name: flip +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Flip[A, B, C any](f func(A, B) C) func(B, A) C" +description: "Intercambia el orden de los argumentos de una funcion de dos parametros." +tags: [functional, generic] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/flip.go" +--- + +## Ejemplo + +```go +sub := func(a, b int) int { return a - b } +flipped := Flip(sub) +result := flipped(3, 10) // 7 (10 - 3) +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/group_by.go b/functions/core/group_by.go new file mode 100644 index 00000000..82677e71 --- /dev/null +++ b/functions/core/group_by.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// GroupBy agrupa elementos de un slice por clave generada con una funcion. +func GroupBy[T any, K comparable](slice []T, keyFn func(T) K) map[K][]T { + // stub + return nil +} diff --git a/functions/core/group_by.md b/functions/core/group_by.md new file mode 100644 index 00000000..dabf6a5a --- /dev/null +++ b/functions/core/group_by.md @@ -0,0 +1,32 @@ +--- +name: group_by +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func GroupBy[T any, K comparable](slice []T, keyFn func(T) K) map[K][]T" +description: "Agrupa elementos de un slice por clave generada con una funcion." +tags: [slice, functional, generic, grouping] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/group_by.go" +--- + +## Ejemplo + +```go +groups := GroupBy([]string{"go", "git", "python"}, func(s string) byte { return s[0] }) +// groups = map[byte][]string{'g': {"go", "git"}, 'p': {"python"}} +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/identity.go b/functions/core/identity.go new file mode 100644 index 00000000..1141c3a5 --- /dev/null +++ b/functions/core/identity.go @@ -0,0 +1,10 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Identity devuelve el valor recibido sin modificarlo. +func Identity[T any](x T) T { + // stub + var zero T + return zero +} diff --git a/functions/core/identity.md b/functions/core/identity.md new file mode 100644 index 00000000..fccbcae2 --- /dev/null +++ b/functions/core/identity.md @@ -0,0 +1,32 @@ +--- +name: identity +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Identity[T any](x T) T" +description: "Devuelve el valor recibido sin modificarlo. Elemento neutro de la composicion." +tags: [functional, generic, identity] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/identity.go" +--- + +## Ejemplo + +```go +x := Identity(42) // 42 +s := Identity("abc") // "abc" +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/partial2.go b/functions/core/partial2.go new file mode 100644 index 00000000..15cfe7d4 --- /dev/null +++ b/functions/core/partial2.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Partial2 aplica parcialmente el primer argumento de una funcion de dos parametros. +func Partial2[A, B, C any](f func(A, B) C, a A) func(B) C { + // stub + return nil +} diff --git a/functions/core/partial2.md b/functions/core/partial2.md new file mode 100644 index 00000000..9028b891 --- /dev/null +++ b/functions/core/partial2.md @@ -0,0 +1,33 @@ +--- +name: partial2 +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Partial2[A, B, C any](f func(A, B) C, a A) func(B) C" +description: "Aplica parcialmente el primer argumento de una funcion de dos parametros." +tags: [functional, generic, partial] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/partial2.go" +--- + +## Ejemplo + +```go +mul := func(a, b int) int { return a * b } +double := Partial2(mul, 2) +result := double(5) // 10 +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/pipe2.go b/functions/core/pipe2.go new file mode 100644 index 00000000..d0609053 --- /dev/null +++ b/functions/core/pipe2.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Pipe2 compone dos funciones de izquierda a derecha. +func Pipe2[A, B, C any](f1 func(A) B, f2 func(B) C) func(A) C { + // stub + return nil +} diff --git a/functions/core/pipe2.md b/functions/core/pipe2.md new file mode 100644 index 00000000..a693ae0b --- /dev/null +++ b/functions/core/pipe2.md @@ -0,0 +1,34 @@ +--- +name: pipe2 +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Pipe2[A, B, C any](f1 func(A) B, f2 func(B) C) func(A) C" +description: "Compone dos funciones de izquierda a derecha. pipe2(f, g)(x) = g(f(x))." +tags: [functional, composition, generic, pipe] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/pipe2.go" +--- + +## Ejemplo + +```go +double := func(x int) int { return x * 2 } +toString := func(x int) string { return fmt.Sprintf("%d", x) } +doubleStr := Pipe2(double, toString) +result := doubleStr(5) // "10" +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/pipe3.go b/functions/core/pipe3.go new file mode 100644 index 00000000..a42eec0c --- /dev/null +++ b/functions/core/pipe3.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Pipe3 compone tres funciones de izquierda a derecha. +func Pipe3[A, B, C, D any](f1 func(A) B, f2 func(B) C, f3 func(C) D) func(A) D { + // stub + return nil +} diff --git a/functions/core/pipe3.md b/functions/core/pipe3.md new file mode 100644 index 00000000..957b62d2 --- /dev/null +++ b/functions/core/pipe3.md @@ -0,0 +1,35 @@ +--- +name: pipe3 +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Pipe3[A, B, C, D any](f1 func(A) B, f2 func(B) C, f3 func(C) D) func(A) D" +description: "Compone tres funciones de izquierda a derecha." +tags: [functional, composition, generic, pipe] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/pipe3.go" +--- + +## Ejemplo + +```go +add1 := func(x int) int { return x + 1 } +double := func(x int) int { return x * 2 } +toString := func(x int) string { return fmt.Sprintf("%d", x) } +pipeline := Pipe3(add1, double, toString) +result := pipeline(3) // "8" +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/reduce.go b/functions/core/reduce.go new file mode 100644 index 00000000..d81ac703 --- /dev/null +++ b/functions/core/reduce.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Reduce reduce un slice a un unico valor aplicando una funcion acumuladora. +func Reduce[T, U any](slice []T, initial U, f func(U, T) U) U { + // stub + return initial +} diff --git a/functions/core/reduce.md b/functions/core/reduce.md new file mode 100644 index 00000000..ec70f7b1 --- /dev/null +++ b/functions/core/reduce.md @@ -0,0 +1,32 @@ +--- +name: reduce +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Reduce[T, U any](slice []T, initial U, f func(U, T) U) U" +description: "Reduce un slice a un unico valor aplicando una funcion acumuladora de izquierda a derecha." +tags: [slice, functional, generic, fold] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/reduce.go" +--- + +## Ejemplo + +```go +sum := Reduce([]int{1, 2, 3, 4}, 0, func(acc, x int) int { return acc + x }) +// sum = 10 +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/take.go b/functions/core/take.go new file mode 100644 index 00000000..50f20e51 --- /dev/null +++ b/functions/core/take.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Take devuelve los primeros n elementos de un slice. +func Take[T any](slice []T, n int) []T { + // stub + return nil +} diff --git a/functions/core/take.md b/functions/core/take.md new file mode 100644 index 00000000..d69c101e --- /dev/null +++ b/functions/core/take.md @@ -0,0 +1,32 @@ +--- +name: take +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Take[T any](slice []T, n int) []T" +description: "Devuelve los primeros n elementos de un slice." +tags: [slice, functional, generic] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/take.go" +--- + +## Ejemplo + +```go +result := Take([]int{1, 2, 3, 4, 5}, 3) +// result = [1, 2, 3] +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/uncurry2.go b/functions/core/uncurry2.go new file mode 100644 index 00000000..f7488abd --- /dev/null +++ b/functions/core/uncurry2.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Uncurry2 transforma una funcion currificada en una funcion normal de dos argumentos. +func Uncurry2[A, B, C any](f func(A) func(B) C) func(A, B) C { + // stub + return nil +} diff --git a/functions/core/uncurry2.md b/functions/core/uncurry2.md new file mode 100644 index 00000000..bc0e04ad --- /dev/null +++ b/functions/core/uncurry2.md @@ -0,0 +1,35 @@ +--- +name: uncurry2 +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Uncurry2[A, B, C any](f func(A) func(B) C) func(A, B) C" +description: "Transforma una funcion currificada en una funcion normal de dos argumentos." +tags: [functional, generic, curry] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/uncurry2.go" +--- + +## Ejemplo + +```go +curriedAdd := func(a int) func(int) int { + return func(b int) int { return a + b } +} +add := Uncurry2(curriedAdd) +result := add(3, 5) // 8 +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/unique.go b/functions/core/unique.go new file mode 100644 index 00000000..c717dfa4 --- /dev/null +++ b/functions/core/unique.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Unique devuelve un slice con elementos unicos preservando el orden original. +func Unique[T comparable](slice []T) []T { + // stub + return nil +} diff --git a/functions/core/unique.md b/functions/core/unique.md new file mode 100644 index 00000000..a16d0e74 --- /dev/null +++ b/functions/core/unique.md @@ -0,0 +1,32 @@ +--- +name: unique +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Unique[T comparable](slice []T) []T" +description: "Devuelve un slice con elementos unicos preservando el orden original." +tags: [slice, functional, generic, dedup] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/unique.go" +--- + +## Ejemplo + +```go +result := Unique([]int{1, 2, 2, 3, 1, 4}) +// result = [1, 2, 3, 4] +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/core/zip.go b/functions/core/zip.go new file mode 100644 index 00000000..12d053dd --- /dev/null +++ b/functions/core/zip.go @@ -0,0 +1,9 @@ +package core + +// Implementation: github.com/lucasdataproyects/devfactory/core + +// Zip combina dos slices en un slice de pares elemento a elemento. +func Zip[T, U any](a []T, b []U) []Pair[T, U] { + // stub + return nil +} diff --git a/functions/core/zip.md b/functions/core/zip.md new file mode 100644 index 00000000..3c0a3fa0 --- /dev/null +++ b/functions/core/zip.md @@ -0,0 +1,32 @@ +--- +name: zip +kind: function +lang: go +domain: core +version: "1.0.0" +purity: pure +signature: "func Zip[T, U any](a []T, b []U) []Pair[T, U]" +description: "Combina dos slices en un slice de pares elemento a elemento." +tags: [slice, functional, generic, pair] +uses_functions: [] +uses_types: [pair_go_core] +returns: [pair_go_core] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/core/zip.go" +--- + +## Ejemplo + +```go +pairs := Zip([]string{"a", "b"}, []int{1, 2}) +// pairs = [{a 1}, {b 2}] +``` + +## Notas + +Funcion pura generica. Implementacion en devfactory/core. diff --git a/functions/infra/docker_container_logs.go b/functions/infra/docker_container_logs.go new file mode 100644 index 00000000..0b3a4f8e --- /dev/null +++ b/functions/infra/docker_container_logs.go @@ -0,0 +1,23 @@ +package infra + +import ( + "fmt" + "os/exec" + "strconv" +) + +// DockerContainerLogs obtiene los logs de un contenedor. tail limita las últimas N líneas (0 = todas). +func DockerContainerLogs(nameOrID string, tail int) (string, error) { + args := []string{"logs"} + if tail > 0 { + args = append(args, "--tail", strconv.Itoa(tail)) + } + args = append(args, nameOrID) + + out, err := exec.Command("docker", args...).CombinedOutput() + if err != nil { + return "", fmt.Errorf("docker logs %s: %w", nameOrID, err) + } + + return string(out), nil +} diff --git a/functions/infra/docker_container_logs.md b/functions/infra/docker_container_logs.md new file mode 100644 index 00000000..05bb88da --- /dev/null +++ b/functions/infra/docker_container_logs.md @@ -0,0 +1,32 @@ +--- +name: docker_container_logs +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerContainerLogs(nameOrID string, tail int) (string, error)" +description: "Obtiene los logs de un contenedor Docker. El parámetro tail limita a las últimas N líneas (0 devuelve todos los logs)." +tags: [docker, container, logs, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strconv] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_container_logs.go" +--- + +## Ejemplo + +```go +// Últimas 100 líneas +logs, err := DockerContainerLogs("my-app", 100) +if err != nil { + log.Fatal(err) +} +fmt.Println(logs) +``` diff --git a/functions/infra/docker_inspect_container.go b/functions/infra/docker_inspect_container.go new file mode 100644 index 00000000..c1599106 --- /dev/null +++ b/functions/infra/docker_inspect_container.go @@ -0,0 +1,26 @@ +package infra + +import ( + "encoding/json" + "fmt" + "os/exec" +) + +// DockerInspectContainer devuelve los detalles completos de un contenedor como JSON genérico. +func DockerInspectContainer(nameOrID string) (map[string]any, error) { + out, err := exec.Command("docker", "inspect", nameOrID).Output() + if err != nil { + return nil, fmt.Errorf("docker inspect %s: %w", nameOrID, err) + } + + var result []map[string]any + if err := json.Unmarshal(out, &result); err != nil { + return nil, fmt.Errorf("parsing inspect output: %w", err) + } + + if len(result) == 0 { + return nil, fmt.Errorf("container %s not found", nameOrID) + } + + return result[0], nil +} diff --git a/functions/infra/docker_inspect_container.md b/functions/infra/docker_inspect_container.md new file mode 100644 index 00000000..8217a400 --- /dev/null +++ b/functions/infra/docker_inspect_container.md @@ -0,0 +1,35 @@ +--- +name: docker_inspect_container +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerInspectContainer(nameOrID string) (map[string]any, error)" +description: "Devuelve los detalles completos de un contenedor Docker como mapa JSON genérico. Útil para inspeccionar configuración, red, volumes, etc." +tags: [docker, container, inspect, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [encoding/json, fmt, os/exec] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_inspect_container.go" +--- + +## Ejemplo + +```go +info, err := DockerInspectContainer("my-app") +if err != nil { + log.Fatal(err) +} +fmt.Println(info["State"]) +``` + +## Notas + +Devuelve `map[string]any` en vez de un struct tipado para maximizar flexibilidad. El caller puede navegar el JSON libremente. diff --git a/functions/infra/docker_list_containers.go b/functions/infra/docker_list_containers.go new file mode 100644 index 00000000..e5fea9d9 --- /dev/null +++ b/functions/infra/docker_list_containers.go @@ -0,0 +1,104 @@ +package infra + +import ( + "encoding/json" + "fmt" + "os/exec" +) + +// DockerListContainers lista contenedores Docker. Si all es true, incluye los detenidos. +func DockerListContainers(all bool) ([]ContainerInfo, error) { + args := []string{"ps", "--format", "{{json .}}", "--no-trunc"} + if all { + args = append(args, "-a") + } + + out, err := exec.Command("docker", args...).Output() + if err != nil { + return nil, fmt.Errorf("docker ps: %w", err) + } + + if len(out) == 0 { + return nil, nil + } + + var containers []ContainerInfo + for _, line := range splitLines(out) { + if len(line) == 0 { + continue + } + var raw struct { + ID string `json:"ID"` + Names string `json:"Names"` + Image string `json:"Image"` + Status string `json:"Status"` + State string `json:"State"` + Ports string `json:"Ports"` + Created string `json:"CreatedAt"` + Labels string `json:"Labels"` + } + if err := json.Unmarshal(line, &raw); err != nil { + continue + } + containers = append(containers, ContainerInfo{ + ID: raw.ID[:12], + Name: raw.Names, + Image: raw.Image, + Status: raw.Status, + State: raw.State, + Ports: raw.Ports, + Created: raw.Created, + Labels: parseLabels(raw.Labels), + }) + } + + return containers, nil +} + +// splitLines divide bytes en líneas individuales. +func splitLines(data []byte) [][]byte { + var lines [][]byte + start := 0 + for i, b := range data { + if b == '\n' { + lines = append(lines, data[start:i]) + start = i + 1 + } + } + if start < len(data) { + lines = append(lines, data[start:]) + } + return lines +} + +// parseLabels convierte "key=val,key2=val2" en map. +func parseLabels(s string) map[string]string { + m := make(map[string]string) + if s == "" { + return m + } + for _, part := range splitByComma(s) { + for i := 0; i < len(part); i++ { + if part[i] == '=' { + m[part[:i]] = part[i+1:] + break + } + } + } + return m +} + +func splitByComma(s string) []string { + var parts []string + start := 0 + for i := 0; i < len(s); i++ { + if s[i] == ',' { + parts = append(parts, s[start:i]) + start = i + 1 + } + } + if start < len(s) { + parts = append(parts, s[start:]) + } + return parts +} diff --git a/functions/infra/docker_list_containers.md b/functions/infra/docker_list_containers.md new file mode 100644 index 00000000..31c1fad9 --- /dev/null +++ b/functions/infra/docker_list_containers.md @@ -0,0 +1,37 @@ +--- +name: docker_list_containers +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerListContainers(all bool) ([]ContainerInfo, error)" +description: "Lista contenedores Docker locales. Si all es true incluye contenedores detenidos. Parsea la salida JSON de docker ps." +tags: [docker, container, list, infra] +uses_functions: [] +uses_types: [container_info_go_infra] +returns: [container_info_go_infra] +returns_optional: false +error_type: "error_go_core" +imports: [encoding/json, fmt, os/exec] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_list_containers.go" +--- + +## Ejemplo + +```go +containers, err := DockerListContainers(true) +if err != nil { + log.Fatal(err) +} +for _, c := range containers { + fmt.Printf("%s %s %s\n", c.ID, c.Name, c.Status) +} +``` + +## Notas + +Usa `docker ps --format '{{json .}}'` para parsear la salida de forma confiable. Incluye helpers internos `splitLines` y `parseLabels`. diff --git a/functions/infra/docker_list_images.go b/functions/infra/docker_list_images.go new file mode 100644 index 00000000..6b4d823b --- /dev/null +++ b/functions/infra/docker_list_images.go @@ -0,0 +1,45 @@ +package infra + +import ( + "encoding/json" + "fmt" + "os/exec" +) + +// DockerListImages lista las imágenes Docker locales. +func DockerListImages() ([]ImageInfo, error) { + out, err := exec.Command("docker", "images", "--format", "{{json .}}", "--no-trunc").Output() + if err != nil { + return nil, fmt.Errorf("docker images: %w", err) + } + + if len(out) == 0 { + return nil, nil + } + + var images []ImageInfo + for _, line := range splitLines(out) { + if len(line) == 0 { + continue + } + var raw struct { + ID string `json:"ID"` + Repository string `json:"Repository"` + Tag string `json:"Tag"` + Size string `json:"Size"` + Created string `json:"CreatedAt"` + } + if err := json.Unmarshal(line, &raw); err != nil { + continue + } + images = append(images, ImageInfo{ + ID: raw.ID, + Repository: raw.Repository, + Tag: raw.Tag, + Size: raw.Size, + Created: raw.Created, + }) + } + + return images, nil +} diff --git a/functions/infra/docker_list_images.md b/functions/infra/docker_list_images.md new file mode 100644 index 00000000..2c0869bd --- /dev/null +++ b/functions/infra/docker_list_images.md @@ -0,0 +1,33 @@ +--- +name: docker_list_images +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerListImages() ([]ImageInfo, error)" +description: "Lista las imágenes Docker disponibles localmente. Parsea la salida JSON de docker images." +tags: [docker, image, list, infra] +uses_functions: [] +uses_types: [image_info_go_infra] +returns: [image_info_go_infra] +returns_optional: false +error_type: "error_go_core" +imports: [encoding/json, fmt, os/exec] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_list_images.go" +--- + +## Ejemplo + +```go +images, err := DockerListImages() +if err != nil { + log.Fatal(err) +} +for _, img := range images { + fmt.Printf("%s:%s (%s)\n", img.Repository, img.Tag, img.Size) +} +``` diff --git a/functions/infra/docker_pull_image.go b/functions/infra/docker_pull_image.go new file mode 100644 index 00000000..1705a1f4 --- /dev/null +++ b/functions/infra/docker_pull_image.go @@ -0,0 +1,16 @@ +package infra + +import ( + "fmt" + "os/exec" + "strings" +) + +// DockerPullImage descarga una imagen Docker del registry remoto. +func DockerPullImage(image string) error { + out, err := exec.Command("docker", "pull", image).CombinedOutput() + if err != nil { + return fmt.Errorf("docker pull %s: %s", image, strings.TrimSpace(string(out))) + } + return nil +} diff --git a/functions/infra/docker_pull_image.md b/functions/infra/docker_pull_image.md new file mode 100644 index 00000000..4f69209d --- /dev/null +++ b/functions/infra/docker_pull_image.md @@ -0,0 +1,30 @@ +--- +name: docker_pull_image +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerPullImage(image string) error" +description: "Descarga una imagen Docker desde el registry remoto (Docker Hub u otro configurado). Acepta formato image:tag." +tags: [docker, image, pull, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strings] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_pull_image.go" +--- + +## Ejemplo + +```go +err := DockerPullImage("nginx:latest") +if err != nil { + log.Fatal(err) +} +``` diff --git a/functions/infra/docker_remove_container.go b/functions/infra/docker_remove_container.go new file mode 100644 index 00000000..fe8953b2 --- /dev/null +++ b/functions/infra/docker_remove_container.go @@ -0,0 +1,22 @@ +package infra + +import ( + "fmt" + "os/exec" + "strings" +) + +// DockerRemoveContainer elimina un contenedor Docker. Si force es true, fuerza la eliminación de contenedores en ejecución. +func DockerRemoveContainer(nameOrID string, force bool) error { + args := []string{"rm"} + if force { + args = append(args, "-f") + } + args = append(args, nameOrID) + + out, err := exec.Command("docker", args...).CombinedOutput() + if err != nil { + return fmt.Errorf("docker rm %s: %s", nameOrID, strings.TrimSpace(string(out))) + } + return nil +} diff --git a/functions/infra/docker_remove_container.md b/functions/infra/docker_remove_container.md new file mode 100644 index 00000000..6fe3411a --- /dev/null +++ b/functions/infra/docker_remove_container.md @@ -0,0 +1,31 @@ +--- +name: docker_remove_container +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerRemoveContainer(nameOrID string, force bool) error" +description: "Elimina un contenedor Docker. Con force=true puede eliminar contenedores en ejecución (equivale a docker rm -f)." +tags: [docker, container, remove, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strings] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_remove_container.go" +--- + +## Ejemplo + +```go +// Eliminar contenedor detenido +err := DockerRemoveContainer("old-app", false) + +// Forzar eliminación +err = DockerRemoveContainer("stuck-app", true) +``` diff --git a/functions/infra/docker_remove_image.go b/functions/infra/docker_remove_image.go new file mode 100644 index 00000000..b380dd86 --- /dev/null +++ b/functions/infra/docker_remove_image.go @@ -0,0 +1,22 @@ +package infra + +import ( + "fmt" + "os/exec" + "strings" +) + +// DockerRemoveImage elimina una imagen Docker local. Si force es true, fuerza la eliminación. +func DockerRemoveImage(image string, force bool) error { + args := []string{"rmi"} + if force { + args = append(args, "-f") + } + args = append(args, image) + + out, err := exec.Command("docker", args...).CombinedOutput() + if err != nil { + return fmt.Errorf("docker rmi %s: %s", image, strings.TrimSpace(string(out))) + } + return nil +} diff --git a/functions/infra/docker_remove_image.md b/functions/infra/docker_remove_image.md new file mode 100644 index 00000000..2f80a186 --- /dev/null +++ b/functions/infra/docker_remove_image.md @@ -0,0 +1,30 @@ +--- +name: docker_remove_image +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerRemoveImage(image string, force bool) error" +description: "Elimina una imagen Docker local. Con force=true fuerza la eliminación incluso si hay contenedores que la usan." +tags: [docker, image, remove, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strings] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_remove_image.go" +--- + +## Ejemplo + +```go +err := DockerRemoveImage("nginx:latest", false) +if err != nil { + log.Fatal(err) +} +``` diff --git a/functions/infra/docker_run_container.go b/functions/infra/docker_run_container.go new file mode 100644 index 00000000..895a1de4 --- /dev/null +++ b/functions/infra/docker_run_container.go @@ -0,0 +1,55 @@ +package infra + +import ( + "fmt" + "os/exec" + "strings" +) + +// DockerRunOpts opciones para ejecutar un contenedor Docker. +type DockerRunOpts struct { + Name string // Nombre del contenedor (opcional) + Ports []string // Mapeo de puertos, ej: ["8080:80", "443:443"] + Env map[string]string // Variables de entorno + Volumes []string // Bind mounts, ej: ["/host/path:/container/path"] + Detach bool // Ejecutar en background + Remove bool // Eliminar al terminar (--rm) + Network string // Red Docker (opcional) +} + +// DockerRunContainer ejecuta un contenedor Docker nuevo con la imagen y opciones dadas. +// Devuelve el ID del contenedor creado. +func DockerRunContainer(image string, opts DockerRunOpts) (string, error) { + args := []string{"run"} + + if opts.Detach { + args = append(args, "-d") + } + if opts.Remove { + args = append(args, "--rm") + } + if opts.Name != "" { + args = append(args, "--name", opts.Name) + } + if opts.Network != "" { + args = append(args, "--network", opts.Network) + } + for _, p := range opts.Ports { + args = append(args, "-p", p) + } + for k, v := range opts.Env { + args = append(args, "-e", k+"="+v) + } + for _, vol := range opts.Volumes { + args = append(args, "-v", vol) + } + + args = append(args, image) + + out, err := exec.Command("docker", args...).CombinedOutput() + if err != nil { + return "", fmt.Errorf("docker run %s: %s", image, strings.TrimSpace(string(out))) + } + + return strings.TrimSpace(string(out)), nil +} diff --git a/functions/infra/docker_run_container.md b/functions/infra/docker_run_container.md new file mode 100644 index 00000000..60a9409f --- /dev/null +++ b/functions/infra/docker_run_container.md @@ -0,0 +1,40 @@ +--- +name: docker_run_container +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerRunContainer(image string, opts DockerRunOpts) (string, error)" +description: "Ejecuta un contenedor Docker nuevo a partir de una imagen. Soporta puertos, env vars, volumes, network, detach y auto-remove. Devuelve el ID del contenedor." +tags: [docker, container, run, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strings] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_run_container.go" +--- + +## Ejemplo + +```go +id, err := DockerRunContainer("nginx:latest", DockerRunOpts{ + Name: "web-server", + Ports: []string{"8080:80"}, + Env: map[string]string{"NGINX_HOST": "localhost"}, + Detach: true, +}) +if err != nil { + log.Fatal(err) +} +fmt.Println("Container ID:", id) +``` + +## Notas + +`DockerRunOpts` es un struct de opciones definido en el mismo archivo. No se registra como tipo del registry porque es específico de esta función. diff --git a/functions/infra/docker_start_container.go b/functions/infra/docker_start_container.go new file mode 100644 index 00000000..e40f6f6a --- /dev/null +++ b/functions/infra/docker_start_container.go @@ -0,0 +1,16 @@ +package infra + +import ( + "fmt" + "os/exec" + "strings" +) + +// DockerStartContainer inicia un contenedor existente por nombre o ID. +func DockerStartContainer(nameOrID string) error { + out, err := exec.Command("docker", "start", nameOrID).CombinedOutput() + if err != nil { + return fmt.Errorf("docker start %s: %s", nameOrID, strings.TrimSpace(string(out))) + } + return nil +} diff --git a/functions/infra/docker_start_container.md b/functions/infra/docker_start_container.md new file mode 100644 index 00000000..cb1d9b42 --- /dev/null +++ b/functions/infra/docker_start_container.md @@ -0,0 +1,30 @@ +--- +name: docker_start_container +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerStartContainer(nameOrID string) error" +description: "Inicia un contenedor Docker existente que está detenido. Recibe nombre o ID del contenedor." +tags: [docker, container, start, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strings] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_start_container.go" +--- + +## Ejemplo + +```go +err := DockerStartContainer("my-app") +if err != nil { + log.Fatal(err) +} +``` diff --git a/functions/infra/docker_stop_container.go b/functions/infra/docker_stop_container.go new file mode 100644 index 00000000..2fb7a078 --- /dev/null +++ b/functions/infra/docker_stop_container.go @@ -0,0 +1,23 @@ +package infra + +import ( + "fmt" + "os/exec" + "strconv" + "strings" +) + +// DockerStopContainer detiene un contenedor Docker. timeoutSecs indica el tiempo de gracia antes de SIGKILL. +func DockerStopContainer(nameOrID string, timeoutSecs int) error { + args := []string{"stop"} + if timeoutSecs > 0 { + args = append(args, "-t", strconv.Itoa(timeoutSecs)) + } + args = append(args, nameOrID) + + out, err := exec.Command("docker", args...).CombinedOutput() + if err != nil { + return fmt.Errorf("docker stop %s: %s", nameOrID, strings.TrimSpace(string(out))) + } + return nil +} diff --git a/functions/infra/docker_stop_container.md b/functions/infra/docker_stop_container.md new file mode 100644 index 00000000..7c3e6a9a --- /dev/null +++ b/functions/infra/docker_stop_container.md @@ -0,0 +1,30 @@ +--- +name: docker_stop_container +kind: function +lang: go +domain: infra +version: "1.0.0" +purity: impure +signature: "func DockerStopContainer(nameOrID string, timeoutSecs int) error" +description: "Detiene un contenedor Docker en ejecución. timeoutSecs controla el tiempo de gracia antes de SIGKILL (0 usa el default de Docker)." +tags: [docker, container, stop, infra] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [fmt, os/exec, strconv, strings] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/infra/docker_stop_container.go" +--- + +## Ejemplo + +```go +err := DockerStopContainer("my-app", 10) +if err != nil { + log.Fatal(err) +} +``` diff --git a/functions/infra/types.go b/functions/infra/types.go new file mode 100644 index 00000000..486f79b1 --- /dev/null +++ b/functions/infra/types.go @@ -0,0 +1,22 @@ +package infra + +// ContainerInfo representa la información básica de un contenedor Docker. +type ContainerInfo struct { + ID string + Name string + Image string + Status string + State string + Ports string + Created string + Labels map[string]string +} + +// ImageInfo representa la información básica de una imagen Docker local. +type ImageInfo struct { + ID string + Repository string + Tag string + Size string + Created string +} diff --git a/functions/shell/run_cmd.go b/functions/shell/run_cmd.go new file mode 100644 index 00000000..a2b31c25 --- /dev/null +++ b/functions/shell/run_cmd.go @@ -0,0 +1,9 @@ +package shell + +// Implementation: github.com/lucasdataproyects/devfactory/shell + +// Run ejecuta un comando del sistema con timeout de 30 segundos y devuelve el resultado. +func Run(name string, args ...string) Result[CmdResult] { + // stub — implementation in devfactory/shell + return Result[CmdResult]{} +} diff --git a/functions/shell/run_cmd.md b/functions/shell/run_cmd.md new file mode 100644 index 00000000..ea99a411 --- /dev/null +++ b/functions/shell/run_cmd.md @@ -0,0 +1,31 @@ +--- +name: run_cmd +kind: function +lang: go +domain: shell +version: "1.0.0" +purity: impure +signature: "func Run(name string, args ...string) core.Result[CmdResult]" +description: "Ejecuta un comando del sistema con timeout de 30 segundos y devuelve el resultado." +tags: [shell, command, process, exec] +uses_functions: [] +uses_types: [cmd_result_go_shell, result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/shell/run_cmd.go" +--- + +## Ejemplo + +```go +result := Run("ls", "-la") +``` + +## Notas + +Implementacion en devfactory/shell. diff --git a/functions/shell/run_cmd_timeout.go b/functions/shell/run_cmd_timeout.go new file mode 100644 index 00000000..557037f1 --- /dev/null +++ b/functions/shell/run_cmd_timeout.go @@ -0,0 +1,11 @@ +package shell + +import "time" + +// Implementation: github.com/lucasdataproyects/devfactory/shell + +// RunWithTimeout ejecuta un comando del sistema con timeout configurable. +func RunWithTimeout(name string, timeout time.Duration, args ...string) Result[CmdResult] { + // stub — implementation in devfactory/shell + return Result[CmdResult]{} +} diff --git a/functions/shell/run_cmd_timeout.md b/functions/shell/run_cmd_timeout.md new file mode 100644 index 00000000..491dc3a6 --- /dev/null +++ b/functions/shell/run_cmd_timeout.md @@ -0,0 +1,31 @@ +--- +name: run_cmd_timeout +kind: function +lang: go +domain: shell +version: "1.0.0" +purity: impure +signature: "func RunWithTimeout(name string, timeout time.Duration, args ...string) core.Result[CmdResult]" +description: "Ejecuta un comando del sistema con timeout configurable." +tags: [shell, command, process, exec, timeout] +uses_functions: [] +uses_types: [cmd_result_go_shell, result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [time] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/shell/run_cmd_timeout.go" +--- + +## Ejemplo + +```go +result := RunWithTimeout("curl", 5*time.Second, "https://example.com") +``` + +## Notas + +Implementacion en devfactory/shell. diff --git a/functions/shell/run_pipe.go b/functions/shell/run_pipe.go new file mode 100644 index 00000000..947b3be0 --- /dev/null +++ b/functions/shell/run_pipe.go @@ -0,0 +1,9 @@ +package shell + +// Implementation: github.com/lucasdataproyects/devfactory/shell + +// RunPipe encadena multiples comandos con pipe y devuelve el resultado final. +func RunPipe(commands ...string) Result[CmdResult] { + // stub — implementation in devfactory/shell + return Result[CmdResult]{} +} diff --git a/functions/shell/run_pipe.md b/functions/shell/run_pipe.md new file mode 100644 index 00000000..17420706 --- /dev/null +++ b/functions/shell/run_pipe.md @@ -0,0 +1,31 @@ +--- +name: run_pipe +kind: function +lang: go +domain: shell +version: "1.0.0" +purity: impure +signature: "func RunPipe(commands ...string) core.Result[CmdResult]" +description: "Encadena multiples comandos con pipe y devuelve el resultado final." +tags: [shell, command, process, pipe] +uses_functions: [] +uses_types: [cmd_result_go_shell, result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/shell/run_pipe.go" +--- + +## Ejemplo + +```go +result := RunPipe("ls -la", "grep go", "wc -l") +``` + +## Notas + +Implementacion en devfactory/shell. diff --git a/functions/shell/run_shell.go b/functions/shell/run_shell.go new file mode 100644 index 00000000..5899ce53 --- /dev/null +++ b/functions/shell/run_shell.go @@ -0,0 +1,9 @@ +package shell + +// Implementation: github.com/lucasdataproyects/devfactory/shell + +// RunShell ejecuta un comando shell interpretado por /bin/sh. +func RunShell(command string) Result[CmdResult] { + // stub — implementation in devfactory/shell + return Result[CmdResult]{} +} diff --git a/functions/shell/run_shell.md b/functions/shell/run_shell.md new file mode 100644 index 00000000..8b3cfe11 --- /dev/null +++ b/functions/shell/run_shell.md @@ -0,0 +1,31 @@ +--- +name: run_shell +kind: function +lang: go +domain: shell +version: "1.0.0" +purity: impure +signature: "func RunShell(command string) core.Result[CmdResult]" +description: "Ejecuta un comando shell interpretado por /bin/sh." +tags: [shell, command, process, exec] +uses_functions: [] +uses_types: [cmd_result_go_shell, result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/shell/run_shell.go" +--- + +## Ejemplo + +```go +result := RunShell("ls -la | grep go") +``` + +## Notas + +Implementacion en devfactory/shell. diff --git a/functions/shell/run_shell_timeout.go b/functions/shell/run_shell_timeout.go new file mode 100644 index 00000000..90c0cca4 --- /dev/null +++ b/functions/shell/run_shell_timeout.go @@ -0,0 +1,11 @@ +package shell + +import "time" + +// Implementation: github.com/lucasdataproyects/devfactory/shell + +// RunShellTimeout ejecuta un comando shell con timeout configurable. +func RunShellTimeout(command string, timeout time.Duration) Result[CmdResult] { + // stub — implementation in devfactory/shell + return Result[CmdResult]{} +} diff --git a/functions/shell/run_shell_timeout.md b/functions/shell/run_shell_timeout.md new file mode 100644 index 00000000..22abd287 --- /dev/null +++ b/functions/shell/run_shell_timeout.md @@ -0,0 +1,31 @@ +--- +name: run_shell_timeout +kind: function +lang: go +domain: shell +version: "1.0.0" +purity: impure +signature: "func RunShellTimeout(command string, timeout time.Duration) core.Result[CmdResult]" +description: "Ejecuta un comando shell con timeout configurable." +tags: [shell, command, process, exec, timeout] +uses_functions: [] +uses_types: [cmd_result_go_shell, result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [time] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/shell/run_shell_timeout.go" +--- + +## Ejemplo + +```go +result := RunShellTimeout("long-running-cmd", 30*time.Second) +``` + +## Notas + +Implementacion en devfactory/shell. diff --git a/functions/shell/which.go b/functions/shell/which.go new file mode 100644 index 00000000..3dcda7bc --- /dev/null +++ b/functions/shell/which.go @@ -0,0 +1,9 @@ +package shell + +// Implementation: github.com/lucasdataproyects/devfactory/shell + +// Which busca la ruta de un ejecutable en el PATH del sistema. Devuelve None si no existe. +func Which(name string) Option[string] { + // stub — implementation in devfactory/shell + return Option[string]{} +} diff --git a/functions/shell/which.md b/functions/shell/which.md new file mode 100644 index 00000000..599f3966 --- /dev/null +++ b/functions/shell/which.md @@ -0,0 +1,31 @@ +--- +name: which +kind: function +lang: go +domain: shell +version: "1.0.0" +purity: pure +signature: "func Which(name string) core.Option[string]" +description: "Busca la ruta de un ejecutable en el PATH del sistema. Devuelve None si no existe." +tags: [shell, path, lookup] +uses_functions: [] +uses_types: [option_go_core] +returns: [option_go_core] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/shell/which.go" +--- + +## Ejemplo + +```go +path := Which("docker") +``` + +## Notas + +Implementacion en devfactory/shell. diff --git a/functions/tui/clear_screen.go b/functions/tui/clear_screen.go new file mode 100644 index 00000000..4cde4ceb --- /dev/null +++ b/functions/tui/clear_screen.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// ClearScreen devuelve el codigo de escape ANSI para limpiar la pantalla del terminal. +func ClearScreen() string { + return "\033[2J\033[H" +} diff --git a/functions/tui/clear_screen.md b/functions/tui/clear_screen.md new file mode 100644 index 00000000..c788a55e --- /dev/null +++ b/functions/tui/clear_screen.md @@ -0,0 +1,32 @@ +--- +name: clear_screen +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func ClearScreen() string" +description: "Devuelve el codigo de escape ANSI para limpiar la pantalla del terminal." +tags: [tui, ansi, terminal, screen] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/clear_screen.go" +--- + +## Ejemplo + +```go +fmt.Print(ClearScreen()) +// Limpia toda la pantalla y mueve el cursor a la posicion inicial +``` + +## Notas + +Combina ESC[2J (borrar pantalla completa) con ESC[H (mover cursor a home). No tiene side effects: solo devuelve el string ANSI. diff --git a/functions/tui/confirm_prompt.go b/functions/tui/confirm_prompt.go new file mode 100644 index 00000000..0c6ba041 --- /dev/null +++ b/functions/tui/confirm_prompt.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// Confirm muestra un dialogo de confirmacion Si/No en terminal y devuelve la eleccion del usuario. +func Confirm(prompt string) Result[bool] { + // stub — implementation in devfactory/tui + return Result[bool]{Value: false} +} diff --git a/functions/tui/confirm_prompt.md b/functions/tui/confirm_prompt.md new file mode 100644 index 00000000..45fbee18 --- /dev/null +++ b/functions/tui/confirm_prompt.md @@ -0,0 +1,37 @@ +--- +name: confirm_prompt +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func Confirm(prompt string) core.Result[bool]" +description: "Muestra un dialogo de confirmacion Si/No en terminal y devuelve la eleccion del usuario." +tags: [tui, confirm, prompt, interactive] +uses_functions: [] +uses_types: [result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/confirm_prompt.go" +--- + +## Ejemplo + +```go +result := tui.Confirm("¿Deseas continuar?") +if result.IsErr() { + log.Fatal(result.Error()) +} +if result.Unwrap() { + fmt.Println("Confirmado") +} +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/dark_styles.go b/functions/tui/dark_styles.go new file mode 100644 index 00000000..5e81b71d --- /dev/null +++ b/functions/tui/dark_styles.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// DarkStyles crea estilos oscuros usando el tema dark. +func DarkStyles() Styles { + // stub — implementation in devfactory/tui + return Styles{} +} diff --git a/functions/tui/dark_styles.md b/functions/tui/dark_styles.md new file mode 100644 index 00000000..863ca3ff --- /dev/null +++ b/functions/tui/dark_styles.md @@ -0,0 +1,32 @@ +--- +name: dark_styles +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func DarkStyles() Styles" +description: "Construye estilos oscuros combinando DarkTheme con NewStyles. Atajo conveniente para terminales con fondo negro." +tags: [tui, styles, dark, constructor] +uses_functions: [] +uses_types: [] +returns: [styles_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/dark_styles.go" +--- + +## Ejemplo + +```go +styles := DarkStyles() +model := NewProgressWithStyles(100.0, "Compilando", styles) +``` + +## Notas + +Equivalente a NewStyles(DarkTheme()). Usa esta funcion para aplicaciones TUI en terminales oscuras. diff --git a/functions/tui/dark_theme.go b/functions/tui/dark_theme.go new file mode 100644 index 00000000..d085ee35 --- /dev/null +++ b/functions/tui/dark_theme.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// DarkTheme crea un tema de colores oscuro. +func DarkTheme() Theme { + // stub — implementation in devfactory/tui + return Theme{} +} diff --git a/functions/tui/dark_theme.md b/functions/tui/dark_theme.md new file mode 100644 index 00000000..e32ebefe --- /dev/null +++ b/functions/tui/dark_theme.md @@ -0,0 +1,32 @@ +--- +name: dark_theme +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func DarkTheme() Theme" +description: "Construye un tema de colores oscuro para componentes TUI. Paleta optimizada para terminales con fondo negro." +tags: [tui, theme, colors, dark, constructor] +uses_functions: [] +uses_types: [] +returns: [theme_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/dark_theme.go" +--- + +## Ejemplo + +```go +theme := DarkTheme() +styles := NewStyles(theme) +``` + +## Notas + +Alternativa oscura al DefaultTheme. Colores de alto contraste para fondos negros. diff --git a/functions/tui/default_styles.go b/functions/tui/default_styles.go new file mode 100644 index 00000000..d9d07849 --- /dev/null +++ b/functions/tui/default_styles.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// DefaultStyles crea estilos por defecto usando el tema base. +func DefaultStyles() Styles { + // stub — implementation in devfactory/tui + return Styles{} +} diff --git a/functions/tui/default_styles.md b/functions/tui/default_styles.md new file mode 100644 index 00000000..437cd630 --- /dev/null +++ b/functions/tui/default_styles.md @@ -0,0 +1,32 @@ +--- +name: default_styles +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func DefaultStyles() Styles" +description: "Construye estilos por defecto combinando DefaultTheme con NewStyles. Atajo conveniente para el caso comun." +tags: [tui, styles, constructor] +uses_functions: [] +uses_types: [] +returns: [styles_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/default_styles.go" +--- + +## Ejemplo + +```go +styles := DefaultStyles() +model := NewSpinnerWithStyle("Cargando...", styles) +``` + +## Notas + +Equivalente a NewStyles(DefaultTheme()). Usa esta funcion cuando no necesitas personalizar el tema. diff --git a/functions/tui/default_theme.go b/functions/tui/default_theme.go new file mode 100644 index 00000000..c3c62b17 --- /dev/null +++ b/functions/tui/default_theme.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// DefaultTheme crea el tema de colores por defecto. +func DefaultTheme() Theme { + // stub — implementation in devfactory/tui + return Theme{} +} diff --git a/functions/tui/default_theme.md b/functions/tui/default_theme.md new file mode 100644 index 00000000..adf5f72f --- /dev/null +++ b/functions/tui/default_theme.md @@ -0,0 +1,32 @@ +--- +name: default_theme +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func DefaultTheme() Theme" +description: "Construye el tema de colores por defecto para componentes TUI. Paleta clara optimizada para terminales con fondo blanco." +tags: [tui, theme, colors, constructor] +uses_functions: [] +uses_types: [] +returns: [theme_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/default_theme.go" +--- + +## Ejemplo + +```go +theme := DefaultTheme() +styles := NewStyles(theme) +``` + +## Notas + +Tema base del sistema de estilos. Usar DarkTheme para terminales con fondo oscuro. diff --git a/functions/tui/hide_cursor.go b/functions/tui/hide_cursor.go new file mode 100644 index 00000000..7b9e80ef --- /dev/null +++ b/functions/tui/hide_cursor.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// HideCursor devuelve el codigo de escape ANSI para ocultar el cursor del terminal. +func HideCursor() string { + return "\033[?25l" +} diff --git a/functions/tui/hide_cursor.md b/functions/tui/hide_cursor.md new file mode 100644 index 00000000..423d8ca2 --- /dev/null +++ b/functions/tui/hide_cursor.md @@ -0,0 +1,32 @@ +--- +name: hide_cursor +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func HideCursor() string" +description: "Devuelve el codigo de escape ANSI para ocultar el cursor del terminal." +tags: [tui, ansi, terminal, cursor] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/hide_cursor.go" +--- + +## Ejemplo + +```go +fmt.Print(HideCursor()) +// Oculta el cursor del terminal usando DECTCEM +``` + +## Notas + +Usa la secuencia DECTCEM (ESC[?25l) del estandar VT220. Recordar restaurar el cursor con ShowCursor al finalizar la aplicacion. diff --git a/functions/tui/new_base_model.go b/functions/tui/new_base_model.go new file mode 100644 index 00000000..bcbb1fec --- /dev/null +++ b/functions/tui/new_base_model.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewBaseModel crea un modelo base con configuracion por defecto. +func NewBaseModel() BaseModel { + // stub — implementation in devfactory/tui + return BaseModel{} +} diff --git a/functions/tui/new_base_model.md b/functions/tui/new_base_model.md new file mode 100644 index 00000000..66e35c08 --- /dev/null +++ b/functions/tui/new_base_model.md @@ -0,0 +1,31 @@ +--- +name: new_base_model +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewBaseModel() BaseModel" +description: "Construye un modelo base con dimensiones de terminal y estilos por defecto. Sirve como fundacion para componer modelos mas complejos." +tags: [tui, base, constructor] +uses_functions: [] +uses_types: [] +returns: [base_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_base_model.go" +--- + +## Ejemplo + +```go +base := NewBaseModel() +``` + +## Notas + +Modelo raiz que encapsula estado comun (dimensiones, estilos, keybindings) compartido por todos los componentes TUI. diff --git a/functions/tui/new_confirm.go b/functions/tui/new_confirm.go new file mode 100644 index 00000000..56cf18da --- /dev/null +++ b/functions/tui/new_confirm.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewConfirm crea un modelo de dialogo de confirmacion si/no. +func NewConfirm(prompt string) ConfirmModel { + // stub — implementation in devfactory/tui + return ConfirmModel{} +} diff --git a/functions/tui/new_confirm.md b/functions/tui/new_confirm.md new file mode 100644 index 00000000..7165a74b --- /dev/null +++ b/functions/tui/new_confirm.md @@ -0,0 +1,31 @@ +--- +name: new_confirm +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewConfirm(prompt string) ConfirmModel" +description: "Construye un modelo de dialogo de confirmacion con una pregunta si/no." +tags: [tui, confirm, dialog, constructor] +uses_functions: [] +uses_types: [] +returns: [confirm_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_confirm.go" +--- + +## Ejemplo + +```go +model := NewConfirm("Deseas continuar?") +``` + +## Notas + +Dialogo binario si/no. El resultado se obtiene del modelo tras la interaccion del usuario en el loop de Bubble Tea. diff --git a/functions/tui/new_filtered_list.go b/functions/tui/new_filtered_list.go new file mode 100644 index 00000000..776af71b --- /dev/null +++ b/functions/tui/new_filtered_list.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewFilteredList crea un modelo de lista con filtrado por texto. +func NewFilteredList(items []ListItem, placeholder string) FilteredListModel { + // stub — implementation in devfactory/tui + return FilteredListModel{} +} diff --git a/functions/tui/new_filtered_list.md b/functions/tui/new_filtered_list.md new file mode 100644 index 00000000..f26b7acd --- /dev/null +++ b/functions/tui/new_filtered_list.md @@ -0,0 +1,35 @@ +--- +name: new_filtered_list +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewFilteredList(items []ListItem, placeholder string) FilteredListModel" +description: "Construye un modelo de lista con campo de busqueda integrado. El placeholder se muestra en el input de filtro cuando esta vacio." +tags: [tui, list, filter, constructor] +uses_functions: [] +uses_types: [list_item_go_tui] +returns: [filtered_list_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_filtered_list.go" +--- + +## Ejemplo + +```go +items := []ListItem{ + {Title: "main.go", Description: "Punto de entrada"}, + {Title: "server.go", Description: "Servidor HTTP"}, +} +model := NewFilteredList(items, "Buscar archivo...") +``` + +## Notas + +Incluye un input de texto que filtra los items en tiempo real por coincidencia parcial. diff --git a/functions/tui/new_list.go b/functions/tui/new_list.go new file mode 100644 index 00000000..66899437 --- /dev/null +++ b/functions/tui/new_list.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewList crea un modelo de lista simple a partir de items. +func NewList(items []ListItem) ListModel { + // stub — implementation in devfactory/tui + return ListModel{} +} diff --git a/functions/tui/new_list.md b/functions/tui/new_list.md new file mode 100644 index 00000000..4b4c66fd --- /dev/null +++ b/functions/tui/new_list.md @@ -0,0 +1,35 @@ +--- +name: new_list +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewList(items []ListItem) ListModel" +description: "Construye un modelo de lista simple a partir de una coleccion de items. Cada item se renderiza como una fila seleccionable." +tags: [tui, list, constructor] +uses_functions: [] +uses_types: [list_item_go_tui] +returns: [list_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_list.go" +--- + +## Ejemplo + +```go +items := []ListItem{ + {Title: "Opcion 1", Description: "Primera opcion"}, + {Title: "Opcion 2", Description: "Segunda opcion"}, +} +model := NewList(items) +``` + +## Notas + +Constructor puro para listas de seleccion simple. No permite seleccion multiple — usar NewMultiList para eso. diff --git a/functions/tui/new_multi_list.go b/functions/tui/new_multi_list.go new file mode 100644 index 00000000..371b8ac0 --- /dev/null +++ b/functions/tui/new_multi_list.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewMultiList crea un modelo de lista con seleccion multiple. +func NewMultiList(items []ListItem) ListModel { + // stub — implementation in devfactory/tui + return ListModel{} +} diff --git a/functions/tui/new_multi_list.md b/functions/tui/new_multi_list.md new file mode 100644 index 00000000..2732dbb3 --- /dev/null +++ b/functions/tui/new_multi_list.md @@ -0,0 +1,36 @@ +--- +name: new_multi_list +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewMultiList(items []ListItem) ListModel" +description: "Construye un modelo de lista con seleccion multiple. Permite al usuario marcar varios items antes de confirmar." +tags: [tui, list, multi, constructor] +uses_functions: [] +uses_types: [list_item_go_tui] +returns: [list_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_multi_list.go" +--- + +## Ejemplo + +```go +items := []ListItem{ + {Title: "Go", Description: "Lenguaje compilado"}, + {Title: "Python", Description: "Lenguaje interpretado"}, + {Title: "Rust", Description: "Lenguaje de sistemas"}, +} +model := NewMultiList(items) +``` + +## Notas + +Variante de lista que habilita seleccion multiple con toggles por item. diff --git a/functions/tui/new_multi_progress.go b/functions/tui/new_multi_progress.go new file mode 100644 index 00000000..fd0d8278 --- /dev/null +++ b/functions/tui/new_multi_progress.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewMultiProgress crea un modelo de progreso multiple sin barras iniciales. +func NewMultiProgress() MultiProgressModel { + // stub — implementation in devfactory/tui + return MultiProgressModel{} +} diff --git a/functions/tui/new_multi_progress.md b/functions/tui/new_multi_progress.md new file mode 100644 index 00000000..0f71756d --- /dev/null +++ b/functions/tui/new_multi_progress.md @@ -0,0 +1,31 @@ +--- +name: new_multi_progress +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewMultiProgress() MultiProgressModel" +description: "Construye un modelo de progreso multiple vacio. Las barras individuales se agregan posteriormente via mensajes." +tags: [tui, progress, multi, constructor] +uses_functions: [] +uses_types: [] +returns: [multi_progress_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_multi_progress.go" +--- + +## Ejemplo + +```go +model := NewMultiProgress() +``` + +## Notas + +Inicia sin barras. Cada barra se agrega dinamicamente via el loop de Bubble Tea, ideal para descargas paralelas o tareas concurrentes. diff --git a/functions/tui/new_progress.go b/functions/tui/new_progress.go new file mode 100644 index 00000000..63cff4b5 --- /dev/null +++ b/functions/tui/new_progress.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewProgress crea un modelo de barra de progreso. +func NewProgress(total float64, label string) ProgressModel { + // stub — implementation in devfactory/tui + return ProgressModel{} +} diff --git a/functions/tui/new_progress.md b/functions/tui/new_progress.md new file mode 100644 index 00000000..d28e3a24 --- /dev/null +++ b/functions/tui/new_progress.md @@ -0,0 +1,31 @@ +--- +name: new_progress +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewProgress(total float64, label string) ProgressModel" +description: "Construye un modelo de barra de progreso con valor total y etiqueta descriptiva." +tags: [tui, progress, constructor] +uses_functions: [] +uses_types: [] +returns: [progress_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_progress.go" +--- + +## Ejemplo + +```go +model := NewProgress(100.0, "Descargando archivos") +``` + +## Notas + +El progreso inicia en 0. El avance se actualiza via mensajes en el loop de Bubble Tea. diff --git a/functions/tui/new_progress_with_styles.go b/functions/tui/new_progress_with_styles.go new file mode 100644 index 00000000..f5b00c38 --- /dev/null +++ b/functions/tui/new_progress_with_styles.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewProgressWithStyles crea un modelo de barra de progreso con estilos personalizados. +func NewProgressWithStyles(total float64, label string, styles Styles) ProgressModel { + // stub — implementation in devfactory/tui + return ProgressModel{} +} diff --git a/functions/tui/new_progress_with_styles.md b/functions/tui/new_progress_with_styles.md new file mode 100644 index 00000000..1ba6f8c7 --- /dev/null +++ b/functions/tui/new_progress_with_styles.md @@ -0,0 +1,32 @@ +--- +name: new_progress_with_styles +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewProgressWithStyles(total float64, label string, styles Styles) ProgressModel" +description: "Construye un modelo de barra de progreso con valor total, etiqueta y estilos visuales personalizados." +tags: [tui, progress, styles, constructor] +uses_functions: [] +uses_types: [styles_go_tui] +returns: [progress_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_progress_with_styles.go" +--- + +## Ejemplo + +```go +styles := DarkStyles() +model := NewProgressWithStyles(50.0, "Indexando", styles) +``` + +## Notas + +Variante de NewProgress que permite personalizar la apariencia de la barra mediante Styles. diff --git a/functions/tui/new_spinner.go b/functions/tui/new_spinner.go new file mode 100644 index 00000000..d9883a65 --- /dev/null +++ b/functions/tui/new_spinner.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewSpinner crea un modelo de spinner con un mensaje. +func NewSpinner(message string) SpinnerModel { + // stub — implementation in devfactory/tui + return SpinnerModel{} +} diff --git a/functions/tui/new_spinner.md b/functions/tui/new_spinner.md new file mode 100644 index 00000000..fd64da9f --- /dev/null +++ b/functions/tui/new_spinner.md @@ -0,0 +1,31 @@ +--- +name: new_spinner +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewSpinner(message string) SpinnerModel" +description: "Construye un modelo de spinner basico con un mensaje descriptivo. Usa el estilo por defecto." +tags: [tui, spinner, constructor] +uses_functions: [] +uses_types: [] +returns: [spinner_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_spinner.go" +--- + +## Ejemplo + +```go +model := NewSpinner("Cargando datos...") +``` + +## Notas + +Spinner con estilos por defecto. Para personalizar apariencia, usar NewSpinnerWithStyle. diff --git a/functions/tui/new_spinner_with_style.go b/functions/tui/new_spinner_with_style.go new file mode 100644 index 00000000..43991679 --- /dev/null +++ b/functions/tui/new_spinner_with_style.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewSpinnerWithStyle crea un modelo de spinner con estilos personalizados. +func NewSpinnerWithStyle(message string, styles Styles) SpinnerModel { + // stub — implementation in devfactory/tui + return SpinnerModel{} +} diff --git a/functions/tui/new_spinner_with_style.md b/functions/tui/new_spinner_with_style.md new file mode 100644 index 00000000..a6a48231 --- /dev/null +++ b/functions/tui/new_spinner_with_style.md @@ -0,0 +1,33 @@ +--- +name: new_spinner_with_style +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewSpinnerWithStyle(message string, styles Styles) SpinnerModel" +description: "Construye un modelo de spinner con mensaje y estilos visuales personalizados." +tags: [tui, spinner, styles, constructor] +uses_functions: [] +uses_types: [styles_go_tui] +returns: [spinner_model_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_spinner_with_style.go" +--- + +## Ejemplo + +```go +theme := DarkTheme() +styles := NewStyles(theme) +model := NewSpinnerWithStyle("Procesando...", styles) +``` + +## Notas + +Permite controlar colores y bordes del spinner mediante el sistema de estilos del registry. diff --git a/functions/tui/new_spinner_with_timeout.go b/functions/tui/new_spinner_with_timeout.go new file mode 100644 index 00000000..5bb89b8e --- /dev/null +++ b/functions/tui/new_spinner_with_timeout.go @@ -0,0 +1,11 @@ +package tui + +import "time" + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewSpinnerWithTimeout crea un modelo de spinner que se cancela tras un timeout. +func NewSpinnerWithTimeout(message string, timeout time.Duration) SpinnerWithTimeoutModel { + // stub — implementation in devfactory/tui + return SpinnerWithTimeoutModel{} +} diff --git a/functions/tui/new_spinner_with_timeout.md b/functions/tui/new_spinner_with_timeout.md new file mode 100644 index 00000000..d8229f3d --- /dev/null +++ b/functions/tui/new_spinner_with_timeout.md @@ -0,0 +1,31 @@ +--- +name: new_spinner_with_timeout +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewSpinnerWithTimeout(message string, timeout time.Duration) SpinnerWithTimeoutModel" +description: "Construye un modelo de spinner con limite de tiempo. Si la operacion excede el timeout, el spinner se detiene automaticamente." +tags: [tui, spinner, timeout, constructor] +uses_functions: [] +uses_types: [] +returns: [spinner_with_timeout_model_go_tui] +returns_optional: false +error_type: "" +imports: [time] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_spinner_with_timeout.go" +--- + +## Ejemplo + +```go +model := NewSpinnerWithTimeout("Esperando respuesta...", 30*time.Second) +``` + +## Notas + +El timeout es configuracion pura — el side effect de cancelar ocurre en el runtime de Bubble Tea, no en el constructor. diff --git a/functions/tui/new_styles.go b/functions/tui/new_styles.go new file mode 100644 index 00000000..0728c539 --- /dev/null +++ b/functions/tui/new_styles.go @@ -0,0 +1,9 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// NewStyles crea estilos a partir de un tema. +func NewStyles(theme Theme) Styles { + // stub — implementation in devfactory/tui + return Styles{} +} diff --git a/functions/tui/new_styles.md b/functions/tui/new_styles.md new file mode 100644 index 00000000..2033283c --- /dev/null +++ b/functions/tui/new_styles.md @@ -0,0 +1,32 @@ +--- +name: new_styles +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func NewStyles(theme Theme) Styles" +description: "Construye un conjunto de estilos lipgloss a partir de un tema de colores. Los estilos resultantes se aplican a todos los componentes TUI." +tags: [tui, styles, constructor] +uses_functions: [] +uses_types: [theme_go_tui] +returns: [styles_go_tui] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/new_styles.go" +--- + +## Ejemplo + +```go +theme := DefaultTheme() +styles := NewStyles(theme) +``` + +## Notas + +Convierte un Theme (paleta de colores) en Styles (estilos lipgloss aplicables). Es el puente entre la configuracion de colores y el renderizado. diff --git a/functions/tui/print_error.go b/functions/tui/print_error.go new file mode 100644 index 00000000..da84ed1e --- /dev/null +++ b/functions/tui/print_error.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// PrintError imprime un mensaje con estilo de error (rojo) en stderr. +func PrintError(msg string) { + // stub — implementation in devfactory/tui +} diff --git a/functions/tui/print_error.md b/functions/tui/print_error.md new file mode 100644 index 00000000..71980aa9 --- /dev/null +++ b/functions/tui/print_error.md @@ -0,0 +1,31 @@ +--- +name: print_error +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func PrintError(msg string)" +description: "Imprime un mensaje con estilo de error (rojo) en stderr." +tags: [tui, print, error, output] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/print_error.go" +--- + +## Ejemplo + +```go +tui.PrintError("No se pudo conectar al servidor") +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/print_info.go b/functions/tui/print_info.go new file mode 100644 index 00000000..9d5c589f --- /dev/null +++ b/functions/tui/print_info.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// PrintInfo imprime un mensaje con estilo informativo (cyan) en stdout. +func PrintInfo(msg string) { + // stub — implementation in devfactory/tui +} diff --git a/functions/tui/print_info.md b/functions/tui/print_info.md new file mode 100644 index 00000000..3b6ca5df --- /dev/null +++ b/functions/tui/print_info.md @@ -0,0 +1,31 @@ +--- +name: print_info +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func PrintInfo(msg string)" +description: "Imprime un mensaje con estilo informativo (cyan) en stdout." +tags: [tui, print, info, output] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/print_info.go" +--- + +## Ejemplo + +```go +tui.PrintInfo("Procesando 42 archivos...") +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/print_muted.go b/functions/tui/print_muted.go new file mode 100644 index 00000000..91a007d1 --- /dev/null +++ b/functions/tui/print_muted.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// PrintMuted imprime un mensaje con estilo atenuado (gris) en stdout. +func PrintMuted(msg string) { + // stub — implementation in devfactory/tui +} diff --git a/functions/tui/print_muted.md b/functions/tui/print_muted.md new file mode 100644 index 00000000..1580eadd --- /dev/null +++ b/functions/tui/print_muted.md @@ -0,0 +1,31 @@ +--- +name: print_muted +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func PrintMuted(msg string)" +description: "Imprime un mensaje con estilo atenuado (gris) en stdout." +tags: [tui, print, muted, output] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/print_muted.go" +--- + +## Ejemplo + +```go +tui.PrintMuted("Ultima actualizacion: hace 5 minutos") +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/print_success.go b/functions/tui/print_success.go new file mode 100644 index 00000000..074d4c8b --- /dev/null +++ b/functions/tui/print_success.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// PrintSuccess imprime un mensaje con estilo de exito (verde) en stdout. +func PrintSuccess(msg string) { + // stub — implementation in devfactory/tui +} diff --git a/functions/tui/print_success.md b/functions/tui/print_success.md new file mode 100644 index 00000000..f0c267a1 --- /dev/null +++ b/functions/tui/print_success.md @@ -0,0 +1,31 @@ +--- +name: print_success +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func PrintSuccess(msg string)" +description: "Imprime un mensaje con estilo de exito (verde) en stdout." +tags: [tui, print, success, output] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/print_success.go" +--- + +## Ejemplo + +```go +tui.PrintSuccess("Operacion completada correctamente") +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/print_warning.go b/functions/tui/print_warning.go new file mode 100644 index 00000000..8e4406d9 --- /dev/null +++ b/functions/tui/print_warning.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// PrintWarning imprime un mensaje con estilo de advertencia (naranja) en stdout. +func PrintWarning(msg string) { + // stub — implementation in devfactory/tui +} diff --git a/functions/tui/print_warning.md b/functions/tui/print_warning.md new file mode 100644 index 00000000..a7214bc2 --- /dev/null +++ b/functions/tui/print_warning.md @@ -0,0 +1,31 @@ +--- +name: print_warning +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func PrintWarning(msg string)" +description: "Imprime un mensaje con estilo de advertencia (naranja) en stdout." +tags: [tui, print, warning, output] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/print_warning.go" +--- + +## Ejemplo + +```go +tui.PrintWarning("El archivo sera sobreescrito") +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/quit_msg.go b/functions/tui/quit_msg.go new file mode 100644 index 00000000..5916b07a --- /dev/null +++ b/functions/tui/quit_msg.go @@ -0,0 +1,10 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +import tea "github.com/charmbracelet/bubbletea" + +// Quit devuelve un mensaje de salida para el bucle de Bubble Tea. +func Quit() tea.Msg { + return tea.QuitMsg{} +} diff --git a/functions/tui/quit_msg.md b/functions/tui/quit_msg.md new file mode 100644 index 00000000..606ac053 --- /dev/null +++ b/functions/tui/quit_msg.md @@ -0,0 +1,32 @@ +--- +name: quit_msg +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func Quit() tea.Msg" +description: "Devuelve un mensaje de salida para el bucle de Bubble Tea." +tags: [tui, quit, message, bubbletea] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [github.com/charmbracelet/bubbletea] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/quit_msg.go" +--- + +## Ejemplo + +```go +msg := Quit() +// msg es tea.QuitMsg{}, usado para terminar el event loop de Bubble Tea +``` + +## Notas + +Wrapper puro sobre tea.QuitMsg{}. Util para componer en pipelines o pasar como callback sin exponer el tipo directamente. diff --git a/functions/tui/run_fullscreen.go b/functions/tui/run_fullscreen.go new file mode 100644 index 00000000..386634a7 --- /dev/null +++ b/functions/tui/run_fullscreen.go @@ -0,0 +1,12 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +import "github.com/charmbracelet/bubbletea" + +// RunFullscreen ejecuta un modelo Bubble Tea en modo fullscreen. +func RunFullscreen[T tea.Model](model T) Result[T] { + // stub — implementation in devfactory/tui + var zero T + return Result[T]{Value: zero} +} diff --git a/functions/tui/run_fullscreen.md b/functions/tui/run_fullscreen.md new file mode 100644 index 00000000..5a88bfb9 --- /dev/null +++ b/functions/tui/run_fullscreen.md @@ -0,0 +1,35 @@ +--- +name: run_fullscreen +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func RunFullscreen[T tea.Model](model T) core.Result[T]" +description: "Ejecuta un modelo Bubble Tea en modo fullscreen." +tags: [tui, runner, fullscreen, bubbletea, generic] +uses_functions: [] +uses_types: [result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [github.com/charmbracelet/bubbletea] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/run_fullscreen.go" +--- + +## Ejemplo + +```go +result := tui.RunFullscreen(myModel) +if result.IsErr() { + log.Fatal(result.Error()) +} +finalModel := result.Unwrap() +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/run_model.go b/functions/tui/run_model.go new file mode 100644 index 00000000..fefe151e --- /dev/null +++ b/functions/tui/run_model.go @@ -0,0 +1,12 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +import "github.com/charmbracelet/bubbletea" + +// RunModel ejecuta un modelo Bubble Tea y devuelve el modelo final o error. +func RunModel[T tea.Model](model T) Result[T] { + // stub — implementation in devfactory/tui + var zero T + return Result[T]{Value: zero} +} diff --git a/functions/tui/run_model.md b/functions/tui/run_model.md new file mode 100644 index 00000000..b937b1a0 --- /dev/null +++ b/functions/tui/run_model.md @@ -0,0 +1,35 @@ +--- +name: run_model +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func RunModel[T tea.Model](model T) core.Result[T]" +description: "Ejecuta un modelo Bubble Tea y devuelve el modelo final o error." +tags: [tui, runner, bubbletea, generic] +uses_functions: [] +uses_types: [result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [github.com/charmbracelet/bubbletea] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/run_model.go" +--- + +## Ejemplo + +```go +result := tui.RunModel(myModel) +if result.IsErr() { + log.Fatal(result.Error()) +} +finalModel := result.Unwrap() +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/run_with_mouse.go b/functions/tui/run_with_mouse.go new file mode 100644 index 00000000..238e2134 --- /dev/null +++ b/functions/tui/run_with_mouse.go @@ -0,0 +1,12 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +import "github.com/charmbracelet/bubbletea" + +// RunWithMouseSupport ejecuta un modelo Bubble Tea con soporte de raton habilitado. +func RunWithMouseSupport[T tea.Model](model T) Result[T] { + // stub — implementation in devfactory/tui + var zero T + return Result[T]{Value: zero} +} diff --git a/functions/tui/run_with_mouse.md b/functions/tui/run_with_mouse.md new file mode 100644 index 00000000..c8a822f4 --- /dev/null +++ b/functions/tui/run_with_mouse.md @@ -0,0 +1,35 @@ +--- +name: run_with_mouse +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: impure +signature: "func RunWithMouseSupport[T tea.Model](model T) core.Result[T]" +description: "Ejecuta un modelo Bubble Tea con soporte de raton habilitado." +tags: [tui, runner, mouse, bubbletea, generic] +uses_functions: [] +uses_types: [result_go_core] +returns: [result_go_core] +returns_optional: false +error_type: "error_go_core" +imports: [github.com/charmbracelet/bubbletea] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/run_with_mouse.go" +--- + +## Ejemplo + +```go +result := tui.RunWithMouseSupport(myModel) +if result.IsErr() { + log.Fatal(result.Error()) +} +finalModel := result.Unwrap() +``` + +## Notas + +Implementacion real en github.com/lucasdataproyects/devfactory/tui. Este stub existe para documentar la firma y mantener el registry. diff --git a/functions/tui/show_cursor.go b/functions/tui/show_cursor.go new file mode 100644 index 00000000..84aed07c --- /dev/null +++ b/functions/tui/show_cursor.go @@ -0,0 +1,8 @@ +package tui + +// Implementation: github.com/lucasdataproyects/devfactory/tui + +// ShowCursor devuelve el codigo de escape ANSI para mostrar el cursor del terminal. +func ShowCursor() string { + return "\033[?25h" +} diff --git a/functions/tui/show_cursor.md b/functions/tui/show_cursor.md new file mode 100644 index 00000000..3420edea --- /dev/null +++ b/functions/tui/show_cursor.md @@ -0,0 +1,32 @@ +--- +name: show_cursor +kind: function +lang: go +domain: tui +version: "1.0.0" +purity: pure +signature: "func ShowCursor() string" +description: "Devuelve el codigo de escape ANSI para mostrar el cursor del terminal." +tags: [tui, ansi, terminal, cursor] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [] +tested: false +tests: [] +test_file_path: "" +file_path: "functions/tui/show_cursor.go" +--- + +## Ejemplo + +```go +fmt.Print(ShowCursor()) +// Restaura la visibilidad del cursor del terminal +``` + +## Notas + +Usa la secuencia DECTCEM (ESC[?25h) del estandar VT220. Complemento de HideCursor. Llamar siempre al finalizar la aplicacion para restaurar el estado del terminal. diff --git a/types/infra/container_info.go b/types/infra/container_info.go new file mode 100644 index 00000000..a88dc87f --- /dev/null +++ b/types/infra/container_info.go @@ -0,0 +1,13 @@ +package infra + +// ContainerInfo representa la información básica de un contenedor Docker. +type ContainerInfo struct { + ID string // ID corto del contenedor + Name string // Nombre del contenedor + Image string // Imagen usada + Status string // Estado actual (running, exited, etc.) + State string // Estado detallado + Ports string // Mapeo de puertos + Created string // Fecha de creación + Labels map[string]string // Labels del contenedor +} diff --git a/types/infra/container_info.md b/types/infra/container_info.md new file mode 100644 index 00000000..630f26a5 --- /dev/null +++ b/types/infra/container_info.md @@ -0,0 +1,39 @@ +--- +name: container_info +lang: go +domain: infra +version: "1.0.0" +algebraic: product +definition: | + type ContainerInfo struct { + ID string + Name string + Image string + Status string + State string + Ports string + Created string + Labels map[string]string + } +description: "Información básica de un contenedor Docker: ID, nombre, imagen, estado, puertos, labels." +tags: [docker, container, infra] +uses_types: [] +file_path: "types/infra/container_info.go" +--- + +## Ejemplo + +```go +c := ContainerInfo{ + ID: "abc123", + Name: "my-app", + Image: "nginx:latest", + Status: "Up 2 hours", + State: "running", + Ports: "0.0.0.0:8080->80/tcp", +} +``` + +## Notas + +Tipo product que modela la salida de `docker ps`. Los campos mapean directamente a las columnas del formato JSON de Docker. diff --git a/types/infra/image_info.go b/types/infra/image_info.go new file mode 100644 index 00000000..30423de4 --- /dev/null +++ b/types/infra/image_info.go @@ -0,0 +1,10 @@ +package infra + +// ImageInfo representa la información básica de una imagen Docker local. +type ImageInfo struct { + ID string // ID corto de la imagen + Repository string // Nombre del repositorio + Tag string // Tag de la imagen + Size string // Tamaño legible (ej: "142MB") + Created string // Fecha de creación +} diff --git a/types/infra/image_info.md b/types/infra/image_info.md new file mode 100644 index 00000000..7ba2a5d0 --- /dev/null +++ b/types/infra/image_info.md @@ -0,0 +1,35 @@ +--- +name: image_info +lang: go +domain: infra +version: "1.0.0" +algebraic: product +definition: | + type ImageInfo struct { + ID string + Repository string + Tag string + Size string + Created string + } +description: "Información básica de una imagen Docker local: ID, repositorio, tag, tamaño, fecha." +tags: [docker, image, infra] +uses_types: [] +file_path: "types/infra/image_info.go" +--- + +## Ejemplo + +```go +img := ImageInfo{ + ID: "sha256:abc123", + Repository: "nginx", + Tag: "latest", + Size: "142MB", + Created: "2 weeks ago", +} +``` + +## Notas + +Tipo product que modela la salida de `docker images`. Los campos mapean al formato JSON de Docker. diff --git a/types/shell/cmd_result.go b/types/shell/cmd_result.go new file mode 100644 index 00000000..37a65e64 --- /dev/null +++ b/types/shell/cmd_result.go @@ -0,0 +1,9 @@ +package shell + +// CmdResult almacena el resultado de ejecutar un comando del sistema. +// Implementation: github.com/lucasdataproyects/devfactory/shell +type CmdResult struct { + Stdout string + Stderr string + ExitCode int +} diff --git a/types/shell/cmd_result.md b/types/shell/cmd_result.md new file mode 100644 index 00000000..2eb1cc8d --- /dev/null +++ b/types/shell/cmd_result.md @@ -0,0 +1,21 @@ +--- +name: cmd_result +lang: go +domain: shell +version: "1.0.0" +algebraic: product +definition: | + type CmdResult struct { + Stdout string + Stderr string + ExitCode int + } +description: "Resultado de la ejecucion de un comando del sistema con stdout, stderr y codigo de salida." +tags: [shell, command, process, result] +uses_types: [] +file_path: "types/shell/cmd_result.go" +--- + +## Notas + +Tipo producto. Metodos Output(), Lines(), Success(), ToResult() disponibles sobre la instancia. diff --git a/types/tui/base_model.go b/types/tui/base_model.go new file mode 100644 index 00000000..c1fd20b3 --- /dev/null +++ b/types/tui/base_model.go @@ -0,0 +1,11 @@ +package tui + +// BaseModel provee funcionalidad comun a todas las vistas TUI: +// dimensiones de terminal, estilos y manejo de errores. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type BaseModel struct { + Width int + Height int + Styles Styles + Err error +} diff --git a/types/tui/base_model.md b/types/tui/base_model.md new file mode 100644 index 00000000..d6d099d7 --- /dev/null +++ b/types/tui/base_model.md @@ -0,0 +1,13 @@ +--- +name: base_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type BaseModel struct { Width int; Height int; Styles Styles; Err error } +description: "Modelo base que provee dimensiones de terminal, estilos y manejo de errores comunes a todas las vistas TUI." +tags: [tui, base, model, component] +uses_types: [styles_go_tui] +file_path: "types/tui/base_model.go" +--- diff --git a/types/tui/confirm_model.go b/types/tui/confirm_model.go new file mode 100644 index 00000000..0af3a3eb --- /dev/null +++ b/types/tui/confirm_model.go @@ -0,0 +1,11 @@ +package tui + +// ConfirmModel es un dialogo de confirmacion Si/No interactivo. +// Implementa tea.Model del framework Bubble Tea. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type ConfirmModel struct { + BaseModel + prompt string + selected bool + done bool +} diff --git a/types/tui/confirm_model.md b/types/tui/confirm_model.md new file mode 100644 index 00000000..7678561a --- /dev/null +++ b/types/tui/confirm_model.md @@ -0,0 +1,13 @@ +--- +name: confirm_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type ConfirmModel struct { BaseModel; prompt string; selected bool; done bool } +description: "Dialogo de confirmacion Si/No interactivo. Embeds BaseModel. Implementa tea.Model." +tags: [tui, confirm, dialog, component, interactive] +uses_types: [base_model_go_tui] +file_path: "types/tui/confirm_model.go" +--- diff --git a/types/tui/filtered_list_model.go b/types/tui/filtered_list_model.go new file mode 100644 index 00000000..72cd9679 --- /dev/null +++ b/types/tui/filtered_list_model.go @@ -0,0 +1,10 @@ +package tui + +// FilteredListModel extiende ListModel con filtrado por texto en tiempo real. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type FilteredListModel struct { + ListModel + query string + allItems []ListItem + placeholder string +} diff --git a/types/tui/filtered_list_model.md b/types/tui/filtered_list_model.md new file mode 100644 index 00000000..4736eccf --- /dev/null +++ b/types/tui/filtered_list_model.md @@ -0,0 +1,13 @@ +--- +name: filtered_list_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type FilteredListModel struct { ListModel; query string; allItems []ListItem; placeholder string } +description: "Lista con filtrado por texto en tiempo real. Embeds ListModel y añade busqueda interactiva." +tags: [tui, list, filter, component, interactive] +uses_types: [list_model_go_tui, list_item_go_tui] +file_path: "types/tui/filtered_list_model.go" +--- diff --git a/types/tui/list_item.go b/types/tui/list_item.go new file mode 100644 index 00000000..639b7ab4 --- /dev/null +++ b/types/tui/list_item.go @@ -0,0 +1,9 @@ +package tui + +// ListItem representa un item individual en una lista TUI. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type ListItem struct { + Title string + Description string + Value interface{} +} diff --git a/types/tui/list_item.md b/types/tui/list_item.md new file mode 100644 index 00000000..abba26ff --- /dev/null +++ b/types/tui/list_item.md @@ -0,0 +1,13 @@ +--- +name: list_item +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type ListItem struct { Title string; Description string; Value interface{} } +description: "Item individual de una lista TUI con titulo, descripcion y valor arbitrario." +tags: [tui, list, component] +uses_types: [] +file_path: "types/tui/list_item.go" +--- diff --git a/types/tui/list_model.go b/types/tui/list_model.go new file mode 100644 index 00000000..431608d1 --- /dev/null +++ b/types/tui/list_model.go @@ -0,0 +1,15 @@ +package tui + +// ListModel es un componente lista seleccionable con cursor, scroll y seleccion. +// Implementa tea.Model del framework Bubble Tea. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type ListModel struct { + items []ListItem + cursor int + selected map[int]struct{} + multi bool + styles Styles + height int + width int + offset int +} diff --git a/types/tui/list_model.md b/types/tui/list_model.md new file mode 100644 index 00000000..ee5bee14 --- /dev/null +++ b/types/tui/list_model.md @@ -0,0 +1,13 @@ +--- +name: list_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type ListModel struct { items []ListItem; cursor int; selected map[int]struct{}; multi bool; styles Styles; height int; width int; offset int } +description: "Componente lista seleccionable con cursor, scroll y seleccion simple o multiple. Implementa tea.Model." +tags: [tui, list, component, interactive] +uses_types: [list_item_go_tui, styles_go_tui] +file_path: "types/tui/list_model.go" +--- diff --git a/types/tui/multi_progress_model.go b/types/tui/multi_progress_model.go new file mode 100644 index 00000000..739a55d5 --- /dev/null +++ b/types/tui/multi_progress_model.go @@ -0,0 +1,9 @@ +package tui + +// MultiProgressModel gestiona multiples barras de progreso simultaneas. +// Implementa tea.Model del framework Bubble Tea. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type MultiProgressModel struct { + bars []ProgressModel + styles Styles +} diff --git a/types/tui/multi_progress_model.md b/types/tui/multi_progress_model.md new file mode 100644 index 00000000..63eb507b --- /dev/null +++ b/types/tui/multi_progress_model.md @@ -0,0 +1,13 @@ +--- +name: multi_progress_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type MultiProgressModel struct { bars []ProgressModel; styles Styles } +description: "Gestor de multiples barras de progreso simultaneas. Implementa tea.Model." +tags: [tui, progress, multi, component] +uses_types: [progress_model_go_tui, styles_go_tui] +file_path: "types/tui/multi_progress_model.go" +--- diff --git a/types/tui/progress_model.go b/types/tui/progress_model.go new file mode 100644 index 00000000..ed3f31ea --- /dev/null +++ b/types/tui/progress_model.go @@ -0,0 +1,21 @@ +package tui + +import ( + "time" + + "github.com/charmbracelet/bubbles/progress" +) + +// ProgressModel es una barra de progreso con porcentaje, ETA y tiempo transcurrido. +// Implementa tea.Model del framework Bubble Tea. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type ProgressModel struct { + progress progress.Model + current float64 + total float64 + label string + styles Styles + showPct bool + showETA bool + started time.Time +} diff --git a/types/tui/progress_model.md b/types/tui/progress_model.md new file mode 100644 index 00000000..ab81521d --- /dev/null +++ b/types/tui/progress_model.md @@ -0,0 +1,13 @@ +--- +name: progress_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type ProgressModel struct { progress progress.Model; current float64; total float64; label string; styles Styles; showPct bool; showETA bool; started time.Time } +description: "Barra de progreso con porcentaje, ETA y tiempo transcurrido. Implementa tea.Model." +tags: [tui, progress, component, interactive] +uses_types: [styles_go_tui] +file_path: "types/tui/progress_model.go" +--- diff --git a/types/tui/spinner_model.go b/types/tui/spinner_model.go new file mode 100644 index 00000000..ae791e09 --- /dev/null +++ b/types/tui/spinner_model.go @@ -0,0 +1,16 @@ +package tui + +import ( + "github.com/charmbracelet/bubbles/spinner" + "github.com/charmbracelet/lipgloss" +) + +// SpinnerModel es un indicador de carga animado con mensaje personalizable. +// Implementa tea.Model del framework Bubble Tea. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type SpinnerModel struct { + spinner spinner.Model + message string + style lipgloss.Style + active bool +} diff --git a/types/tui/spinner_model.md b/types/tui/spinner_model.md new file mode 100644 index 00000000..90e961ed --- /dev/null +++ b/types/tui/spinner_model.md @@ -0,0 +1,13 @@ +--- +name: spinner_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type SpinnerModel struct { spinner spinner.Model; message string; style lipgloss.Style; active bool } +description: "Indicador de carga animado con mensaje personalizable. Implementa tea.Model." +tags: [tui, spinner, loading, component] +uses_types: [] +file_path: "types/tui/spinner_model.go" +--- diff --git a/types/tui/spinner_with_timeout_model.go b/types/tui/spinner_with_timeout_model.go new file mode 100644 index 00000000..6769c71f --- /dev/null +++ b/types/tui/spinner_with_timeout_model.go @@ -0,0 +1,12 @@ +package tui + +import "time" + +// SpinnerWithTimeoutModel es un spinner que se auto-detiene tras un timeout. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type SpinnerWithTimeoutModel struct { + SpinnerModel + timeout time.Duration + started time.Time + finished bool +} diff --git a/types/tui/spinner_with_timeout_model.md b/types/tui/spinner_with_timeout_model.md new file mode 100644 index 00000000..cc796d10 --- /dev/null +++ b/types/tui/spinner_with_timeout_model.md @@ -0,0 +1,13 @@ +--- +name: spinner_with_timeout_model +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type SpinnerWithTimeoutModel struct { SpinnerModel; timeout time.Duration; started time.Time; finished bool } +description: "Spinner que se auto-detiene tras un timeout configurable. Embeds SpinnerModel." +tags: [tui, spinner, timeout, component] +uses_types: [spinner_model_go_tui] +file_path: "types/tui/spinner_with_timeout_model.go" +--- diff --git a/types/tui/styles.go b/types/tui/styles.go new file mode 100644 index 00000000..e86b0a4b --- /dev/null +++ b/types/tui/styles.go @@ -0,0 +1,34 @@ +package tui + +import "github.com/charmbracelet/lipgloss" + +// Styles contiene todos los estilos lipgloss pre-configurados para una aplicacion TUI. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type Styles struct { + Theme Theme + Title lipgloss.Style + Subtitle lipgloss.Style + Header lipgloss.Style + Label lipgloss.Style + Text lipgloss.Style + Muted lipgloss.Style + Code lipgloss.Style + Success lipgloss.Style + Error lipgloss.Style + Warning lipgloss.Style + Info lipgloss.Style + Border lipgloss.Style + Box lipgloss.Style + List lipgloss.Style + ListItem lipgloss.Style + Selected lipgloss.Style + Unselected lipgloss.Style + Button lipgloss.Style + ButtonActive lipgloss.Style + Input lipgloss.Style + Cursor lipgloss.Style + Container lipgloss.Style + Section lipgloss.Style + Divider lipgloss.Style + StatusBar lipgloss.Style +} diff --git a/types/tui/styles.md b/types/tui/styles.md new file mode 100644 index 00000000..496aa8e2 --- /dev/null +++ b/types/tui/styles.md @@ -0,0 +1,13 @@ +--- +name: styles +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type Styles struct { Theme Theme; Title lipgloss.Style; Subtitle lipgloss.Style; Header lipgloss.Style; Label lipgloss.Style; Text lipgloss.Style; Muted lipgloss.Style; Code lipgloss.Style; Success lipgloss.Style; Error lipgloss.Style; Warning lipgloss.Style; Info lipgloss.Style; Border lipgloss.Style; Box lipgloss.Style; List lipgloss.Style; ListItem lipgloss.Style; Selected lipgloss.Style; Unselected lipgloss.Style; Button lipgloss.Style; ButtonActive lipgloss.Style; Input lipgloss.Style; Cursor lipgloss.Style; Container lipgloss.Style; Section lipgloss.Style; Divider lipgloss.Style; StatusBar lipgloss.Style } +description: "Coleccion completa de estilos lipgloss pre-configurados para tipografia, estados, componentes y layout." +tags: [tui, styles, lipgloss, theme] +uses_types: [theme_go_tui] +file_path: "types/tui/styles.go" +--- diff --git a/types/tui/theme.go b/types/tui/theme.go new file mode 100644 index 00000000..0c0108ae --- /dev/null +++ b/types/tui/theme.go @@ -0,0 +1,17 @@ +package tui + +import "github.com/charmbracelet/lipgloss" + +// Theme define una paleta de 9 colores semanticos para terminal. +// Implementation: github.com/lucasdataproyects/devfactory/tui +type Theme struct { + Primary lipgloss.Color + Secondary lipgloss.Color + Success lipgloss.Color + Error lipgloss.Color + Warning lipgloss.Color + Info lipgloss.Color + Muted lipgloss.Color + Text lipgloss.Color + Border lipgloss.Color +} diff --git a/types/tui/theme.md b/types/tui/theme.md new file mode 100644 index 00000000..def9e801 --- /dev/null +++ b/types/tui/theme.md @@ -0,0 +1,13 @@ +--- +name: theme +lang: go +domain: tui +version: "1.0.0" +algebraic: product +definition: | + type Theme struct { Primary lipgloss.Color; Secondary lipgloss.Color; Success lipgloss.Color; Error lipgloss.Color; Warning lipgloss.Color; Info lipgloss.Color; Muted lipgloss.Color; Text lipgloss.Color; Border lipgloss.Color } +description: "Paleta de colores para terminal con 9 colores semanticos. Base del sistema de estilos." +tags: [tui, theme, styles, colors] +uses_types: [] +file_path: "types/tui/theme.go" +---