Los 4 init pipelines (init_api_app, init_web_app, init_desktop_app, init_cli_app) estan implementados, verificados end-to-end con `fn run`, e indexados en registry.db como kind=pipeline + tag=launcher. Guia consolidada en docs/init-pipelines.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
22 KiB
0022 — Init Pipelines
Metadata
| Campo | Valor |
|---|---|
| ID | 0022 |
| Estado | pendiente |
| Prioridad | alta |
| Tipo | feature |
Dependencias
| ID | Titulo | Estado | Requerido |
|---|---|---|---|
| 0009 | HTTP Server Foundation | pendiente | si |
| 0010 | Auth System | pendiente | si |
| 0015 | Database Migrations | pendiente | si |
Bloqueada por: #0009 (http_serve, http_router, http_json_response, http_middleware_chain), #0010 (jwt_middleware, password_hash, session_create), #0015 (migration_create, migration_up, migration_status). Los pipelines de init generan boilerplate que importa y compone estas funciones — sin ellas, el codigo scaffoldeado no compilaria.
Desbloquea: cualquier app nueva del registry se puede crear con un solo comando en vez de copiar y adaptar una app existente.
Objetivo
Cuatro bash pipelines que scaffold apps completas en apps/ con un solo comando. Cada uno genera la estructura de directorios, archivos boilerplate, app.md con frontmatter correcto, y verifica que el resultado compila. Misma filosofia que init_jupyter_analysis_bash_pipelines: componer funciones atomicas del registry para producir un entorno listo para trabajar.
Contexto
- Existen tres init pipelines:
init_go_project_bash_pipelines(repo Go generico),init_go_module_bash_pipelines(modulo Go simple),init_jupyter_analysis_bash_pipelines(analysis Jupyter). Todos scaffoldean estructuras basicas. - No existe ningun pipeline para scaffoldear apps del registry con HTTP server, auth, DB, frontend, Wails o TUI. Cada app nueva se construye copiando otra y adaptando manualmente.
- Las apps existentes (
deploy_server,sqlite_api,rapid_dashboards,pipeline_launcher) comparten patrones repetitivos: main.go con graceful shutdown, config desde env vars, health check, migrations, app.md. - Con las funciones de 0009 (HTTP), 0010 (auth) y 0015 (migrations) disponibles, el boilerplate de una app API es predecible y automatizable.
- El registry ya tiene funciones Wails completas (
scaffold_wails_app_go_infra,install_wails_bash_infra,wails_build_go_infra, hooksuse_wails_*_ts_ui,wails_provider_ts_ui) y TUI (new_base_model_go_tui,run_fullscreen_go_tui, temas, spinners, listas).
Arquitectura
bash/functions/pipelines/
├── init_api_app.sh — NEW: scaffold Go HTTP API app
├── init_api_app.md — NEW
├── init_web_app.sh — NEW: scaffold full-stack app (Go API + React)
├── init_web_app.md — NEW
├── init_desktop_app.sh — NEW: scaffold Wails desktop app
├── init_desktop_app.md — NEW
├── init_cli_app.sh — NEW: scaffold Go CLI/TUI app
├── init_cli_app.md — NEW
Todas son kind: pipeline, purity: impure, lang: bash, domain: pipelines.
Patron de composicion
Cada pipeline sigue el mismo patron que init_jupyter_analysis:
- Source funciones atomicas del registry via
source "$REGISTRY_ROOT/bash/functions/..." - Parsear argumentos (nombre obligatorio, flags opcionales)
- Crear estructura de directorios con
mkdir -p - Escribir archivos boilerplate con heredocs
- Generar
app.mdcon frontmatter correcto - Ejecutar
fn indexpara registrar la app - Verificar con
go vet/pnpm build/wails buildsegun corresponda
Diseno
Pipeline 1: init_api_app
Scaffold de Go HTTP API app en apps/.
Uso:
fn run init_api_app my_service
fn run init_api_app my_service --port 8080 --with-auth --with-db
Archivos generados:
apps/{nombre}/
├── main.go — Entry point: config → router → middleware → http_serve con graceful shutdown
├── handlers.go — Handler GET /health + handler de ejemplo GET /api/v1/status
├── config.go — Struct Config con tags + carga desde .env / env vars
├── migrations/
│ └── 001_initial.sql — CREATE TABLE ejemplo con id, created_at, updated_at
├── app.md — Frontmatter con tag service, uses_functions, dir_path
├── Makefile — Targets: build, run, test, vet, clean
├── .env.example — Variables de entorno documentadas (PORT, DB_PATH, etc.)
└── .gitignore — Binario, .env, *.db-shm, *.db-wal
Funciones del registry compuestas:
| Funcion | Para que |
|---|---|
assert_command_exists_bash_shell |
Verificar que go esta instalado |
http_serve_go_infra (0009) |
Codigo de graceful shutdown en main.go |
http_router_go_infra (0009) |
Registro de rutas en main.go |
http_json_response_go_infra (0009) |
Helper en handlers.go |
http_error_response_go_infra (0009) |
Helper en handlers.go |
http_middleware_chain_go_infra (0009) |
Composicion de middlewares en main.go |
http_logger_middleware_go_infra (0009) |
Logging en main.go |
http_cors_middleware_go_infra (0009) |
CORS en main.go |
migration_up_go_infra (0015) |
Aplicar migrations en main.go al arrancar |
config_load_go_infra (0018) |
Carga de config en config.go (si existe) |
Flags opcionales:
| Flag | Efecto |
|---|---|
--port N |
Puerto por defecto en config y .env.example (default: 8080) |
--with-auth |
Anade jwt_middleware, handlers de login/register, tabla users en migration |
--with-db |
Anade operations.db setup, store.go con helpers CRUD basicos |
--with-ops |
Anade fn ops init para crear operations.db con schema completo |
main.go generado (esquema):
package main
import (
"context"
"log"
"os"
"os/signal"
"fn_registry/functions/infra"
)
func main() {
cfg := LoadConfig()
// Migrations
if err := infra.MigrationUp(cfg.DBPath, "migrations"); err != nil {
log.Fatal(err)
}
// Routes
routes := []infra.Route{
{Method: "GET", Path: "/health", Handler: healthHandler},
{Method: "GET", Path: "/api/v1/status", Handler: statusHandler},
}
mux := infra.HttpRouter(routes)
// Middleware
middleware := infra.HttpMiddlewareChain(
infra.HttpCorsMiddleware(cfg.CORSOrigins, []string{"GET", "POST", "PUT", "DELETE"}),
infra.HttpLoggerMiddleware(os.Stdout),
)
// Serve
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
log.Printf("starting %s on :%s", cfg.AppName, cfg.Port)
if err := infra.HttpServe(":"+cfg.Port, middleware(mux), ctx); err != nil {
log.Fatal(err)
}
}
Pipeline 2: init_web_app
Scaffold de full-stack app: Go API backend + React frontend con Mantine.
Uso:
fn run init_web_app my_dashboard
fn run init_web_app my_dashboard --port 8080 --with-auth
Archivos generados:
apps/{nombre}/
├── main.go — Igual que init_api_app + serve static files del frontend build
├── handlers.go — Health + API handlers de ejemplo
├── config.go — Config con FRONTEND_DIR
├── migrations/
│ └── 001_initial.sql
├── app.md — tag service, uses frontend
├── Makefile — Targets: build, build-frontend, run, dev, test, clean
├── .env.example
├── .gitignore
├── docker-compose.yml — Dev: Go API hot-reload + frontend dev server
└── frontend/
├── package.json — pnpm, vite, react, @mantine/core, @mantine/charts, @fn_library
├── vite.config.ts — API proxy a localhost:${port}
├── tsconfig.json
├── index.html
├── postcss.config.cjs
└── src/
├── main.tsx — FnMantineProvider + App mount
├── App.tsx — Router basico con pagina de ejemplo
├── theme.ts — createTheme() con colores del proyecto
└── pages/
└── Home.tsx — Pagina de ejemplo usando crud_page_ts_ui o dashboard_layout_ts_ui
Funciones adicionales compuestas (sobre init_api_app):
| Funcion | Para que |
|---|---|
mantine_provider_ts_ui |
Provider raiz en main.tsx |
crud_page_ts_ui |
Pagina de ejemplo funcional |
app_shell_ts_ui |
Layout con navbar y header |
data_table_ts_ui |
Tabla de datos en la pagina de ejemplo |
vite.config.ts generado:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@fn_library": path.resolve(__dirname, "../../frontend/functions/ui"),
},
},
server: {
proxy: {
"/api": {
target: "http://localhost:${PORT}",
changeOrigin: true,
},
"/health": {
target: "http://localhost:${PORT}",
},
},
},
});
docker-compose.yml generado:
services:
api:
build: .
ports:
- "${PORT}:${PORT}"
env_file: .env
volumes:
- ./migrations:/app/migrations
frontend:
image: node:20-alpine
working_dir: /app
command: sh -c "corepack enable && pnpm install && pnpm dev"
ports:
- "5173:5173"
volumes:
- ./frontend:/app
Pipeline 3: init_desktop_app
Scaffold de Wails desktop app con Go backend y React frontend con @fn_library.
Uso:
fn run init_desktop_app my_tool
fn run init_desktop_app my_tool --with-db
Archivos generados:
apps/{nombre}/
├── main.go — Wails entry point con embed del frontend
├── app.go — Struct App con bindings base (Greet, GetVersion)
├── wails.json — Config Wails apuntando a frontend/
├── go.mod
├── app.md — framework: wails, uses wails hooks
├── .gitignore
└── frontend/
├── package.json — pnpm, vite, react, @mantine/core, @fn_library
├── vite.config.ts
├── tsconfig.json
├── index.html
└── src/
├── main.tsx — WailsProvider + FnMantineProvider + App
├── App.tsx — Ejemplo usando useWailsQuery + data_table
└── theme.ts — createTheme()
Funciones del registry compuestas:
| Funcion | Para que |
|---|---|
scaffold_wails_app_go_infra |
Genera estructura base Wails (main.go, app.go, wails.json, go.mod) |
install_wails_bash_infra |
Verifica/instala Wails CLI y deps de sistema |
wails_provider_ts_ui |
Provider React para IPC cache |
use_wails_query_ts_ui |
Hook de ejemplo en App.tsx |
mantine_provider_ts_ui |
Provider Mantine |
wails_bind_crud_go_infra |
Genera bindings CRUD si --with-db |
Flags opcionales:
| Flag | Efecto |
|---|---|
--with-db |
Anade SQLite con migrations, bindings CRUD generados por wails_bind_crud_go_infra |
Pipeline 4: init_cli_app
Scaffold de Go CLI app con subcomandos y componentes TUI de Bubbletea.
Uso:
fn run init_cli_app my_cli
fn run init_cli_app my_cli --with-tui
Archivos generados:
apps/{nombre}/
├── main.go — Entry point con subcommand routing (os.Args)
├── cmd_version.go — Subcomando: version
├── cmd_status.go — Subcomando de ejemplo: status (imprime info)
├── app.md — framework vacio (CLI puro) o bubbletea (con --with-tui)
├── Makefile — Targets: build, run, install, test, clean
├── .gitignore
└── go.mod
Con --with-tui:
apps/{nombre}/
├── main.go — Entry point con run_fullscreen o run_model
├── model.go — BaseModel + Update + View con tema oscuro
├── cmd_version.go — Subcomando no-TUI
├── app.md — framework: bubbletea
├── Makefile
├── .gitignore
└── go.mod
Funciones del registry compuestas:
| Funcion | Para que |
|---|---|
assert_command_exists_bash_shell |
Verificar Go |
new_base_model_go_tui |
Modelo base en model.go |
dark_styles_go_tui |
Tema oscuro por defecto |
run_fullscreen_go_tui |
Arranque fullscreen en main.go |
new_spinner_go_tui |
Componente de ejemplo |
new_filtered_list_go_tui |
Componente de ejemplo |
main.go generado (sin TUI):
package main
import (
"fmt"
"os"
)
var version = "dev"
func main() {
if len(os.Args) < 2 {
printUsage()
os.Exit(1)
}
switch os.Args[1] {
case "version":
cmdVersion()
case "status":
cmdStatus()
default:
fmt.Fprintf(os.Stderr, "unknown command: %s\n", os.Args[1])
printUsage()
os.Exit(1)
}
}
func printUsage() {
fmt.Println("Usage: {nombre} <command>")
fmt.Println()
fmt.Println("Commands:")
fmt.Println(" version Print version")
fmt.Println(" status Show status")
}
Tareas
Fase 1: init_api_app (pipeline base)
- 1.1 Crear
bash/functions/pipelines/init_api_app.shcon source de funciones atomicas, parseo de argumentos, y generacion de estructura - 1.2 Escribir heredocs para
main.go,handlers.go,config.goque importen funciones de 0009 y 0015 - 1.3 Generar
app.mdcon frontmatter correcto (tagservice,uses_functionscon IDs reales,dir_path) - 1.4 Generar
Makefile,.env.example,.gitignore,migrations/001_initial.sql - 1.5 Flag
--with-auth: anadir imports de 0010, handlers de login/register, tabla users en migration - 1.6 Flag
--with-db: anadirstore.gocon helpers CRUD, setup de SQLite al arrancar - 1.7 Ejecutar
go vet -tags fts5al final como verificacion - 1.8 Crear
init_api_app.mdcon frontmatter de pipeline
Fase 2: init_web_app (extiende init_api_app)
- 2.1 Crear
bash/functions/pipelines/init_web_app.shque primero invoca la logica deinit_api_appy luego anade el frontend - 2.2 Generar
frontend/conpackage.json(pnpm, vite, react, mantine, @fn_library alias) - 2.3 Generar
vite.config.tscon proxy al backend y alias@fn_library - 2.4 Generar
src/main.tsxconFnMantineProvider,src/App.tsxconAppShell,src/pages/Home.tsxcon ejemplo - 2.5 Generar
docker-compose.ymlpara desarrollo - 2.6 Actualizar
main.gopara servir static files del frontend build - 2.7 Ejecutar
pnpm install && pnpm buildcomo verificacion del frontend - 2.8 Crear
init_web_app.mdcon frontmatter de pipeline
Fase 3: init_desktop_app
- 3.1 Crear
bash/functions/pipelines/init_desktop_app.shque invocascaffold_wails_app_go_infray anade frontend React - 3.2 Verificar/instalar Wails con
install_wails_bash_infra - 3.3 Generar frontend con
WailsProvider+FnMantineProvidery ejemplo conuseWailsQuery - 3.4 Flag
--with-db: invocarwails_bind_crud_go_infrapara generar bindings - 3.5 Ejecutar
wails buildcomo verificacion - 3.6 Crear
init_desktop_app.mdcon frontmatter de pipeline
Fase 4: init_cli_app
- 4.1 Crear
bash/functions/pipelines/init_cli_app.shcon generacion de estructura CLI basica - 4.2 Generar
main.gocon routing de subcomandos,cmd_version.go,cmd_status.go - 4.3 Flag
--with-tui: generarmodel.goconnew_base_model,dark_styles,run_fullscreen - 4.4 Ejecutar
go vetcomo verificacion - 4.5 Crear
init_cli_app.mdcon frontmatter de pipeline
Fase 5: Integracion
- 5.1
fn indexy verificar que los 4 pipelines aparecen en registry.db con kind=pipeline, purity=impure - 5.2 Verificar
fn run init_api_app test_append-to-end: genera, compila, limpia - 5.3 Verificar
fn run init_web_app test_webend-to-end - 5.4 Verificar
fn run init_desktop_app test_desktopend-to-end - 5.5 Verificar
fn run init_cli_app test_cliend-to-end
Fase 6: Documentacion de uso rapido
Cada pipeline debe ser usable sin leer el issue completo. La documentacion va en dos niveles: el .md de cada funcion (fuente de verdad para fn show) y una guia consolidada.
- 6.1 En cada
.mdde pipeline (init_api_app.md, etc.) documentar en la secciondocumentationdel frontmatter:- Sinopsis:
fn run init_api_app <nombre> [--port N] [--with-auth] [--with-db] - Descripcion de cada flag y su efecto concreto (que archivos anade, que imports genera)
- Listado de archivos generados con una linea de descripcion cada uno
- Post-setup: que comandos ejecutar despues (
make run,make dev,wails dev, etc.) - Ejemplo rapido: un bloque copy-paste de 3-4 lineas que crea la app y la arranca
- Sinopsis:
- 6.2 En el campo
paramsdel frontmatter de cada pipeline, documentar cada argumento y flag connameydescsemantico para quefn check paramspase y la info sea buscable via FTS5 - 6.3 En el campo
exampledel frontmatter, poner el caso de uso mas comun (una linea):init_api_app:fn run init_api_app my_service --with-dbinit_web_app:fn run init_web_app my_dashboard --with-authinit_desktop_app:fn run init_desktop_app my_toolinit_cli_app:fn run init_cli_app my_cli --with-tui
- 6.4 Crear
docs/init-pipelines.mdcomo guia consolidada de referencia rapida con:- Tabla resumen de los 4 pipelines (nombre, que genera, flags disponibles)
- Arbol de decision: "quiero una API" → init_api_app, "quiero frontend" → init_web_app, "quiero desktop" → init_desktop_app, "quiero CLI" → init_cli_app
- Seccion de combinaciones comunes (API + auth + DB, web dashboard, desktop con SQLite, CLI con TUI)
- FAQ: como anadir auth despues, como cambiar el puerto, como anadir operations.db, como agregar mas paginas al frontend
- 6.5 Verificar que
fn show init_api_app_bash_pipelines(y los otros 3) muestra la documentacion completa con params, ejemplo y notas de uso
Ejemplo de uso
# API service con auth y database
fn run init_api_app billing_api --port 8090 --with-auth --with-db
cd apps/billing_api
make run
# → starting billing_api on :8090
# → curl localhost:8090/health → {"status":"ok"}
# Full-stack dashboard
fn run init_web_app inventory_dashboard --with-auth
cd apps/inventory_dashboard
make dev
# → API en :8080, frontend en :5173 con proxy
# Desktop app con base de datos
fn run init_desktop_app data_explorer --with-db
cd apps/data_explorer
wails dev
# → App de escritorio con React + SQLite
# CLI con TUI
fn run init_cli_app deploy_helper --with-tui
cd apps/deploy_helper
make run -- status
# → TUI fullscreen con lista filtrable
Cada pipeline genera su app.md listo para fn index:
---
name: billing_api
lang: go
domain: tools
description: "API de facturacion."
tags: [service]
uses_functions:
- http_serve_go_infra
- http_router_go_infra
- http_middleware_chain_go_infra
- http_cors_middleware_go_infra
- http_logger_middleware_go_infra
- http_json_response_go_infra
- http_error_response_go_infra
- migration_up_go_infra
uses_types: []
framework: "net/http"
entry_point: "main.go"
dir_path: "apps/billing_api"
---
Decisiones de diseno
- Bash, no Go: los init pipelines generan archivos con heredocs — bash es el lenguaje natural para esto. Go seria overengineering para scaffolding de texto. Coherente con
init_jupyter_analysisy los demas init existentes. - Composicion sobre monolito: cada pipeline sourcea funciones atomicas del registry (
assert_command_exists,scaffold_wails_app, etc.) en vez de reimplementar. Si una funcion atomica mejora, todos los pipelines se benefician. - init_web_app extiende init_api_app: el pipeline web reutiliza la logica del API (misma estructura backend) y anade la capa frontend encima. No duplica codigo.
- Verificacion al final: cada pipeline termina con
go vet,pnpm build, owails buildpara garantizar que el scaffold compila. Si falla, el pipeline reporta el error antes de declarar exito. - Flags opcionales con defaults sensatos: el caso base (sin flags) genera una app funcional minima.
--with-auth,--with-db,--with-tuianaden capas incrementales. El usuario no necesita decidir todo upfront. - @fn_library como alias, no copia: el frontend generado referencia
@fn_libraryvia alias envite.config.tsapuntando afrontend/functions/ui/del registry. Los componentes se comparten, no se duplican. - app.md generado automaticamente: el frontmatter incluye
uses_functionscon los IDs reales de las funciones que el boilerplate importa.fn indexlos valida al registrar la app. - Sin framework CLI externo para init_cli_app: routing de subcomandos con
os.Argsy switch — consistente con las apps existentes del registry que no usan cobra/urfave. Para TUI se usa Bubbletea que ya esta en el registry.
Riesgos
- Dependencias no implementadas: los tres issues de dependencia (0009, 0010, 0015) estan pendientes. Si alguna funcion cambia de firma durante su implementacion, los heredocs de los pipelines necesitaran ajuste. Mitigacion: implementar los pipelines despues de que las dependencias esten merged, o mantener los heredocs parametricos para absorber cambios menores.
- Heredocs fragiles: generar Go/TS/YAML con heredocs bash es propenso a errores de indentacion, escape de variables y quoting. Mitigacion: cada pipeline incluye verificacion final (
go vet/pnpm build) que detecta errores de sintaxis inmediatamente. Tests end-to-end en fase 5. - Frontend desactualizado respecto a @fn_library: si los componentes de
frontend/functions/ui/evolucionan, el boilerplate generado puede quedar desactualizado. Mitigacion: el boilerplate es minimo (un Provider, un AppShell, una pagina de ejemplo) — el usuario lo extiende con los componentes actuales del registry. - Wails como dependencia de sistema:
init_desktop_apprequiere GTK3 + WebKit2GTK instalados en Linux.install_wails_bash_infralo maneja, pero puede fallar en distros no soportadas. Mitigacion: el pipeline verifica la instalacion al inicio y falla rapido con mensaje descriptivo. - Colision de nombres: si el usuario elige un nombre que ya existe en
apps/, el pipeline sobreescribiria archivos. Mitigacion: verificar siapps/{nombre}/existe al inicio y abortar con error si ya existe.