c36aa18c67
Nuevas skills para crear TUIs, inicializar frontends React y módulos Go. Incluye binario parallel-executor y utilidades de soporte. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
439 lines
12 KiB
Bash
Executable File
439 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# =============================================================================
|
|
# setup-frontend.sh — Inicializa proyecto React/Vite o Wails desktop
|
|
# Coherente con Frontend_Library + DevFactory + build-wails agent
|
|
# =============================================================================
|
|
|
|
# --- Colores ---
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
log_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
|
|
|
|
# --- Parámetros ---
|
|
PROJECT_NAME=""
|
|
WAILS_MODE=false
|
|
TARGET_PATH="."
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--wails) WAILS_MODE=true; shift ;;
|
|
--path) TARGET_PATH="$2"; shift 2 ;;
|
|
-*) log_error "Flag desconocido: $1"; echo "STATUS: ERROR"; exit 1 ;;
|
|
*) PROJECT_NAME="$1"; shift ;;
|
|
esac
|
|
done
|
|
|
|
# --- Rutas de librerías ---
|
|
FRONTEND_LIB="$HOME/.local_agentes/frontend/frontend"
|
|
DEVFACTORY_PATH="$HOME/.local_agentes/backend"
|
|
TEMPLATES_DIR="$HOME/.local_agentes/frontend/templates/base"
|
|
WAILS_TEMPLATES="$HOME/.claude/agents/build-wails/templates"
|
|
|
|
# --- Validar nombre ---
|
|
if [[ -z "$PROJECT_NAME" ]]; then
|
|
log_error "Uso: setup-frontend.sh <nombre> [--wails] [--path /ruta]"
|
|
echo "STATUS: ERROR"
|
|
exit 1
|
|
fi
|
|
|
|
# Normalizar
|
|
PROJECT_NAME=$(echo "$PROJECT_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
|
|
PROJECT_DIR="$TARGET_PATH/$PROJECT_NAME"
|
|
|
|
# --- Check estado existente ---
|
|
if [[ -f "$PROJECT_DIR/package.json" ]] || [[ -f "$PROJECT_DIR/wails.json" ]]; then
|
|
log_warn "El proyecto $PROJECT_NAME ya existe en $PROJECT_DIR"
|
|
echo "STATUS: CONFIGURED"
|
|
exit 0
|
|
fi
|
|
|
|
# --- Verificar dependencias ---
|
|
log_step "Verificando dependencias..."
|
|
|
|
if ! command -v pnpm &>/dev/null; then
|
|
log_error "pnpm no está instalado. Instala con: npm install -g pnpm"
|
|
echo "STATUS: ERROR"
|
|
exit 1
|
|
fi
|
|
log_ok "pnpm $(pnpm --version) encontrado"
|
|
|
|
if ! command -v node &>/dev/null; then
|
|
log_error "Node.js no encontrado"
|
|
echo "STATUS: ERROR"
|
|
exit 1
|
|
fi
|
|
log_ok "Node $(node --version) encontrado"
|
|
|
|
if [[ "$WAILS_MODE" == true ]]; then
|
|
if ! command -v wails &>/dev/null; then
|
|
log_error "Wails no está instalado. Instala con: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
|
|
echo "STATUS: ERROR"
|
|
exit 1
|
|
fi
|
|
log_ok "Wails $(wails version 2>/dev/null | head -1 || echo 'v2.x') encontrado"
|
|
|
|
if ! command -v go &>/dev/null; then
|
|
log_error "Go no encontrado (requerido para Wails)"
|
|
echo "STATUS: ERROR"
|
|
exit 1
|
|
fi
|
|
log_ok "Go $(go version | grep -oP '\d+\.\d+' | head -1) encontrado"
|
|
fi
|
|
|
|
if [[ ! -d "$FRONTEND_LIB" ]]; then
|
|
log_warn "Frontend_Library no encontrada en $FRONTEND_LIB — se creará sin link"
|
|
HAS_FRONTEND_LIB=false
|
|
else
|
|
log_ok "Frontend_Library encontrada"
|
|
HAS_FRONTEND_LIB=true
|
|
fi
|
|
|
|
# ============================================================================
|
|
# MODO WAILS — Desktop app (Go + React)
|
|
# ============================================================================
|
|
if [[ "$WAILS_MODE" == true ]]; then
|
|
log_step "Creando proyecto Wails '$PROJECT_NAME'..."
|
|
|
|
# Usar wails init con template react-ts
|
|
wails init -n "$PROJECT_NAME" -t react-ts -d "$TARGET_PATH" 2>/dev/null
|
|
|
|
cd "$PROJECT_DIR"
|
|
|
|
# --- go.work con DevFactory ---
|
|
if [[ -d "$DEVFACTORY_PATH" ]]; then
|
|
log_step "Configurando go.work con DevFactory..."
|
|
cat > go.work << EOF
|
|
go 1.22
|
|
|
|
use (
|
|
.
|
|
$DEVFACTORY_PATH
|
|
)
|
|
EOF
|
|
log_ok "DevFactory enlazado via go.work"
|
|
fi
|
|
|
|
# --- Configurar frontend con pnpm ---
|
|
log_step "Configurando frontend con pnpm..."
|
|
cd frontend
|
|
|
|
# Reemplazar npm por pnpm en wails.json
|
|
cd ..
|
|
if [[ -f "wails.json" ]]; then
|
|
sed -i 's/"npm install"/"pnpm install"/g' wails.json
|
|
sed -i 's/"npm run dev"/"pnpm dev"/g' wails.json
|
|
sed -i 's/"npm run build"/"pnpm build"/g' wails.json
|
|
fi
|
|
cd frontend
|
|
|
|
# Instalar con pnpm
|
|
rm -f package-lock.json 2>/dev/null || true
|
|
pnpm install
|
|
|
|
# --- Linkear Frontend_Library ---
|
|
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
log_step "Linkeando Frontend_Library..."
|
|
pnpm add "@anthropic/frontend-lib@link:$FRONTEND_LIB"
|
|
log_ok "@anthropic/frontend-lib linkeada"
|
|
fi
|
|
|
|
# --- Instalar Tailwind CSS 4 ---
|
|
log_step "Instalando Tailwind CSS 4..."
|
|
pnpm add -D tailwindcss @tailwindcss/vite
|
|
|
|
# --- Configurar vite.config.ts con dedupe y tailwind ---
|
|
log_step "Configurando Vite (dedupe + tailwind)..."
|
|
cat > vite.config.ts << 'VEOF'
|
|
import { defineConfig } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import { resolve } from 'path'
|
|
|
|
export default defineConfig({
|
|
plugins: [react(), tailwindcss()],
|
|
resolve: {
|
|
alias: {
|
|
'@': resolve(__dirname, './src'),
|
|
'@wails': resolve(__dirname, './wailsjs'),
|
|
},
|
|
dedupe: ['react', 'react-dom'],
|
|
},
|
|
})
|
|
VEOF
|
|
|
|
# --- CSS base con Tailwind ---
|
|
cat > src/style.css << 'CSSEOF'
|
|
@import "tailwindcss";
|
|
CSSEOF
|
|
|
|
# --- Instalar Phosphor Icons ---
|
|
pnpm add @phosphor-icons/react
|
|
|
|
cd ..
|
|
|
|
# --- Makefile (basado en build-wails agent) ---
|
|
log_step "Generando Makefile..."
|
|
cat > Makefile << 'MKEOF'
|
|
.PHONY: dev dev-debug build build-prod build-linux build-windows build-all clean generate doctor
|
|
|
|
APP_NAME := $(shell basename $(CURDIR))
|
|
|
|
## dev: Desarrollo con hot reload
|
|
dev:
|
|
wails dev
|
|
|
|
## dev-debug: Desarrollo con DevTools
|
|
dev-debug:
|
|
wails dev -devtools
|
|
|
|
## build: Build para plataforma actual
|
|
build:
|
|
wails build
|
|
|
|
## build-prod: Build optimizado para producción
|
|
build-prod:
|
|
wails build -clean -trimpath -ldflags="-s -w"
|
|
|
|
## build-linux: Build para Linux AMD64
|
|
build-linux:
|
|
wails build -platform linux/amd64
|
|
|
|
## build-windows: Cross-compile para Windows
|
|
build-windows:
|
|
wails build -platform windows/amd64
|
|
|
|
## build-all: Linux + Windows
|
|
build-all: build-linux build-windows
|
|
|
|
## generate: Regenerar bindings TypeScript
|
|
generate:
|
|
wails generate module
|
|
|
|
## clean: Limpiar artefactos
|
|
clean:
|
|
rm -rf build/bin frontend/dist
|
|
|
|
## doctor: Verificar instalación
|
|
doctor:
|
|
wails doctor
|
|
|
|
## help: Muestra esta ayuda
|
|
help:
|
|
@grep -E '^## ' Makefile | sed 's/## //' | column -t -s ':'
|
|
MKEOF
|
|
|
|
# --- .gitignore ---
|
|
cat >> .gitignore << 'EOF'
|
|
node_modules/
|
|
frontend/dist/
|
|
build/bin/
|
|
*.exe
|
|
EOF
|
|
|
|
# --- Resumen Wails ---
|
|
echo ""
|
|
log_ok "Proyecto Wails '$PROJECT_NAME' creado en $PROJECT_DIR"
|
|
echo ""
|
|
echo -e "${CYAN}Estructura:${NC}"
|
|
echo " $PROJECT_NAME/"
|
|
echo " ├── main.go, app.go — Backend Go"
|
|
echo " ├── go.work — Enlace a DevFactory"
|
|
echo " ├── frontend/ — React + TypeScript + Vite"
|
|
echo " │ ├── src/ — Componentes React"
|
|
echo " │ └── wailsjs/ — Bindings auto-generados"
|
|
echo " ├── Makefile — dev, build, build-all"
|
|
echo " └── wails.json — Configuración Wails"
|
|
echo ""
|
|
echo -e "${CYAN}Comandos:${NC}"
|
|
echo " make dev — Desarrollo con hot reload"
|
|
echo " make build — Compilar app desktop"
|
|
echo " make build-all — Linux + Windows"
|
|
echo " make generate — Regenerar bindings TS"
|
|
echo ""
|
|
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
echo -e "${CYAN}Frontend_Library:${NC}"
|
|
echo " import { Button, Card } from '@anthropic/frontend-lib'"
|
|
echo " import { useTheme } from '@anthropic/frontend-lib/hooks'"
|
|
echo ""
|
|
fi
|
|
echo "STATUS: READY"
|
|
exit 0
|
|
fi
|
|
|
|
# ============================================================================
|
|
# MODO WEBAPP — React + Vite (sin Wails)
|
|
# ============================================================================
|
|
log_step "Creando proyecto webapp '$PROJECT_NAME'..."
|
|
|
|
mkdir -p "$PROJECT_DIR"
|
|
cd "$PROJECT_DIR"
|
|
|
|
# --- Usar template de Frontend_Library si existe ---
|
|
if [[ -d "$TEMPLATES_DIR" ]]; then
|
|
log_step "Usando template de Frontend_Library..."
|
|
cp -r "$TEMPLATES_DIR"/* .
|
|
cp -r "$TEMPLATES_DIR"/.[!.]* . 2>/dev/null || true
|
|
else
|
|
log_step "Creando desde cero con Vite..."
|
|
|
|
# package.json
|
|
cat > package.json << PKGEOF
|
|
{
|
|
"name": "$PROJECT_NAME",
|
|
"private": true,
|
|
"version": "0.1.0",
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "tsc -b && vite build",
|
|
"preview": "vite preview"
|
|
}
|
|
}
|
|
PKGEOF
|
|
|
|
# Instalar dependencias base
|
|
pnpm add react react-dom
|
|
pnpm add -D typescript @types/react @types/react-dom
|
|
pnpm add -D vite @vitejs/plugin-react
|
|
pnpm add -D tailwindcss @tailwindcss/vite
|
|
|
|
# tsconfig.json
|
|
cat > tsconfig.json << 'TSEOF'
|
|
{
|
|
"compilerOptions": {
|
|
"target": "ES2023",
|
|
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
"module": "ESNext",
|
|
"moduleResolution": "bundler",
|
|
"jsx": "react-jsx",
|
|
"strict": true,
|
|
"noUnusedLocals": true,
|
|
"noUnusedParameters": true,
|
|
"paths": { "@/*": ["./src/*"] },
|
|
"skipLibCheck": true
|
|
},
|
|
"include": ["src"]
|
|
}
|
|
TSEOF
|
|
|
|
# vite.config.ts
|
|
cat > vite.config.ts << 'VEOF'
|
|
import { defineConfig } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import { resolve } from 'path'
|
|
|
|
export default defineConfig({
|
|
plugins: [react(), tailwindcss()],
|
|
resolve: {
|
|
alias: { '@': resolve(__dirname, './src') },
|
|
dedupe: ['react', 'react-dom'],
|
|
},
|
|
})
|
|
VEOF
|
|
|
|
# index.html
|
|
cat > index.html << HTMLEOF
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>$PROJECT_NAME</title>
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
<script type="module" src="/src/main.tsx"></script>
|
|
</body>
|
|
</html>
|
|
HTMLEOF
|
|
|
|
# src/
|
|
mkdir -p src
|
|
|
|
cat > src/main.tsx << 'TSXEOF'
|
|
import { StrictMode } from 'react'
|
|
import { createRoot } from 'react-dom/client'
|
|
import App from './App'
|
|
import './app.css'
|
|
|
|
createRoot(document.getElementById('root')!).render(
|
|
<StrictMode>
|
|
<App />
|
|
</StrictMode>,
|
|
)
|
|
TSXEOF
|
|
|
|
cat > src/App.tsx << 'TSXEOF'
|
|
function App() {
|
|
return (
|
|
<div className="min-h-screen bg-surface text-foreground flex items-center justify-center">
|
|
<h1 className="text-3xl font-bold">Ready</h1>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default App
|
|
TSXEOF
|
|
|
|
cat > src/app.css << 'CSSEOF'
|
|
@import "tailwindcss";
|
|
CSSEOF
|
|
fi
|
|
|
|
# --- Linkear Frontend_Library ---
|
|
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
log_step "Linkeando Frontend_Library..."
|
|
pnpm add "@anthropic/frontend-lib@link:$FRONTEND_LIB"
|
|
log_ok "@anthropic/frontend-lib linkeada"
|
|
fi
|
|
|
|
# --- Phosphor Icons ---
|
|
pnpm add @phosphor-icons/react
|
|
|
|
# --- .gitignore ---
|
|
cat > .gitignore << 'EOF'
|
|
node_modules/
|
|
dist/
|
|
.vite/
|
|
*.local
|
|
EOF
|
|
|
|
# --- Resumen Webapp ---
|
|
echo ""
|
|
log_ok "Proyecto webapp '$PROJECT_NAME' creado en $PROJECT_DIR"
|
|
echo ""
|
|
echo -e "${CYAN}Estructura:${NC}"
|
|
echo " $PROJECT_NAME/"
|
|
echo " ├── src/"
|
|
echo " │ ├── App.tsx — Componente principal"
|
|
echo " │ ├── main.tsx — Entry point"
|
|
echo " │ └── app.css — Tailwind CSS"
|
|
echo " ├── vite.config.ts — Vite + Tailwind + dedupe"
|
|
echo " ├── tsconfig.json — TypeScript strict"
|
|
echo " └── package.json — pnpm"
|
|
echo ""
|
|
echo -e "${CYAN}Comandos:${NC}"
|
|
echo " pnpm dev — Servidor de desarrollo"
|
|
echo " pnpm build — Build de producción"
|
|
echo " pnpm preview — Preview del build"
|
|
echo ""
|
|
if [[ "$HAS_FRONTEND_LIB" == true ]]; then
|
|
echo -e "${CYAN}Frontend_Library:${NC}"
|
|
echo " import { Button, Card } from '@anthropic/frontend-lib'"
|
|
echo " import { useTheme } from '@anthropic/frontend-lib/hooks'"
|
|
echo ""
|
|
fi
|
|
echo "STATUS: READY"
|