omni-catalyst 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1137 -0
- package/core/bin/core +85 -0
- package/core/bin/omni +21 -0
- package/core/cli/commands/--version.sh +8 -0
- package/core/cli/commands/brain.sh +1549 -0
- package/core/cli/commands/doctor.sh +834 -0
- package/core/cli/commands/env.sh +226 -0
- package/core/cli/commands/init.sh +1266 -0
- package/core/cli/commands/install.sh +759 -0
- package/core/cli/commands/list.sh +397 -0
- package/core/cli/commands/open.sh +71 -0
- package/core/cli/commands/pg.sh +761 -0
- package/core/cli/commands/reinstall.sh +694 -0
- package/core/cli/commands/show.sh +90 -0
- package/core/cli/commands/uninstall.sh +700 -0
- package/core/cli/commands/update.sh +754 -0
- package/core/cli/commands/voice.sh +170 -0
- package/core/cli/core.sh +82 -0
- package/core/cli/omni.sh +634 -0
- package/core/modules/ai.sh +152 -0
- package/core/modules/auto.sh +90 -0
- package/core/modules/db.sh +94 -0
- package/core/modules/deploy.sh +50 -0
- package/core/modules/dev.sh +126 -0
- package/core/modules/editor.sh +101 -0
- package/core/modules/lang.sh +100 -0
- package/core/modules/npm.sh +122 -0
- package/core/modules/shell.sh +312 -0
- package/core/modules/ui.sh +115 -0
- package/core/tools/ai/all.sh +63 -0
- package/core/tools/ai/antigravity-cli/README.md +45 -0
- package/core/tools/ai/antigravity-cli/bin/agy +28 -0
- package/core/tools/ai/antigravity-cli/helper/agy_helper.c +39 -0
- package/core/tools/ai/antigravity-cli/install.sh +469 -0
- package/core/tools/ai/claude-code/README.md +45 -0
- package/core/tools/ai/claude-code/bin/claude +29 -0
- package/core/tools/ai/claude-code/helper/claude_helper.c +42 -0
- package/core/tools/ai/claude-code/install.sh +278 -0
- package/core/tools/ai/codegraph/README.md +43 -0
- package/core/tools/ai/codegraph/bin/codegraph +3 -0
- package/core/tools/ai/codegraph/install.sh +149 -0
- package/core/tools/ai/codex/README.md +44 -0
- package/core/tools/ai/codex/install.sh +104 -0
- package/core/tools/ai/command-code/README.md +62 -0
- package/core/tools/ai/command-code/install.sh +136 -0
- package/core/tools/ai/engram/README.md +44 -0
- package/core/tools/ai/engram/install.sh +127 -0
- package/core/tools/ai/freebuff/README.md +52 -0
- package/core/tools/ai/freebuff/bin/freebuff +28 -0
- package/core/tools/ai/freebuff/helper/freebuff_helper.c +47 -0
- package/core/tools/ai/freebuff/install.sh +301 -0
- package/core/tools/ai/gemini-cli/README.md +46 -0
- package/core/tools/ai/gemini-cli/install.sh +111 -0
- package/core/tools/ai/gentle-ai/README.md +42 -0
- package/core/tools/ai/gentle-ai/install.sh +253 -0
- package/core/tools/ai/gentle-ai/termux-patches.go +256 -0
- package/core/tools/ai/gga/README.md +49 -0
- package/core/tools/ai/gga/install.sh +134 -0
- package/core/tools/ai/hermes-agent/README.md +50 -0
- package/core/tools/ai/hermes-agent/install.sh +80 -0
- package/core/tools/ai/heygen/README.md +24 -0
- package/core/tools/ai/heygen/install.sh +126 -0
- package/core/tools/ai/kilocode-cli/README.md +45 -0
- package/core/tools/ai/kilocode-cli/bin/kilocode +21 -0
- package/core/tools/ai/kilocode-cli/helper/kilocode_helper.c +47 -0
- package/core/tools/ai/kilocode-cli/install.sh +179 -0
- package/core/tools/ai/kimchi-code/README.md +8 -0
- package/core/tools/ai/kimchi-code/install.sh +120 -0
- package/core/tools/ai/kimi-code/README.md +45 -0
- package/core/tools/ai/kimi-code/install.sh +111 -0
- package/core/tools/ai/kiro-cli/README.md +23 -0
- package/core/tools/ai/kiro-cli/install.sh +127 -0
- package/core/tools/ai/mimocode/README.md +43 -0
- package/core/tools/ai/mimocode/bin/mimo +28 -0
- package/core/tools/ai/mimocode/helper/mimocode_helper.c +47 -0
- package/core/tools/ai/mimocode/install.sh +287 -0
- package/core/tools/ai/minimax-cli/README.md +45 -0
- package/core/tools/ai/minimax-cli/install.sh +111 -0
- package/core/tools/ai/mistral-vibe/README.md +46 -0
- package/core/tools/ai/mistral-vibe/install.sh +119 -0
- package/core/tools/ai/odysseus/README.md +35 -0
- package/core/tools/ai/odysseus/install.sh +163 -0
- package/core/tools/ai/ollama/README.md +44 -0
- package/core/tools/ai/ollama/install.sh +78 -0
- package/core/tools/ai/openclaude/README.md +46 -0
- package/core/tools/ai/openclaude/install.sh +110 -0
- package/core/tools/ai/openclaw/README.md +47 -0
- package/core/tools/ai/openclaw/install.sh +112 -0
- package/core/tools/ai/opencode/README.md +51 -0
- package/core/tools/ai/opencode/bin/opencode +28 -0
- package/core/tools/ai/opencode/helper/opencode_helper.c +57 -0
- package/core/tools/ai/opencode/install.sh +290 -0
- package/core/tools/ai/pi/README.md +46 -0
- package/core/tools/ai/pi/install.sh +104 -0
- package/core/tools/ai/qwen-code/README.md +45 -0
- package/core/tools/ai/qwen-code/install.sh +111 -0
- package/core/tools/ai/seedance/README.md +22 -0
- package/core/tools/ai/seedance/install.sh +134 -0
- package/core/tools/ai/veo3/README.md +36 -0
- package/core/tools/ai/veo3/install.sh +151 -0
- package/core/tools/auto/all.sh +57 -0
- package/core/tools/auto/n8n/README.md +47 -0
- package/core/tools/auto/n8n/install.sh +102 -0
- package/core/tools/db/all.sh +60 -0
- package/core/tools/db/mariadb/README.md +43 -0
- package/core/tools/db/mariadb/install.sh +65 -0
- package/core/tools/db/mongodb/README.md +42 -0
- package/core/tools/db/mongodb/install.sh +73 -0
- package/core/tools/db/postgresql/README.md +45 -0
- package/core/tools/db/postgresql/install.sh +65 -0
- package/core/tools/db/sqlite/README.md +44 -0
- package/core/tools/db/sqlite/install.sh +65 -0
- package/core/tools/deploy/all.sh +39 -0
- package/core/tools/deploy/netlify/install.sh +41 -0
- package/core/tools/deploy/railway/install.sh +47 -0
- package/core/tools/deploy/vercel/install.sh +43 -0
- package/core/tools/dev/all.sh +75 -0
- package/core/tools/dev/bat/README.md +44 -0
- package/core/tools/dev/bat/install.sh +82 -0
- package/core/tools/dev/bc/README.md +44 -0
- package/core/tools/dev/bc/install.sh +82 -0
- package/core/tools/dev/cloudflared/README.md +43 -0
- package/core/tools/dev/cloudflared/install.sh +82 -0
- package/core/tools/dev/curl/README.md +43 -0
- package/core/tools/dev/curl/install.sh +82 -0
- package/core/tools/dev/fzf/README.md +44 -0
- package/core/tools/dev/fzf/install.sh +82 -0
- package/core/tools/dev/gh/README.md +43 -0
- package/core/tools/dev/gh/install.sh +82 -0
- package/core/tools/dev/html2text/README.md +44 -0
- package/core/tools/dev/html2text/install.sh +82 -0
- package/core/tools/dev/imagemagick/README.md +44 -0
- package/core/tools/dev/imagemagick/install.sh +82 -0
- package/core/tools/dev/jq/README.md +44 -0
- package/core/tools/dev/jq/install.sh +82 -0
- package/core/tools/dev/lsd/README.md +44 -0
- package/core/tools/dev/lsd/install.sh +82 -0
- package/core/tools/dev/make/README.md +44 -0
- package/core/tools/dev/make/install.sh +82 -0
- package/core/tools/dev/ncurses/README.md +42 -0
- package/core/tools/dev/ncurses/install.sh +82 -0
- package/core/tools/dev/proot/README.md +43 -0
- package/core/tools/dev/proot/install.sh +82 -0
- package/core/tools/dev/shfmt/README.md +44 -0
- package/core/tools/dev/shfmt/install.sh +82 -0
- package/core/tools/dev/tmate/README.md +44 -0
- package/core/tools/dev/tmate/install.sh +82 -0
- package/core/tools/dev/translate/README.md +44 -0
- package/core/tools/dev/translate/install.sh +82 -0
- package/core/tools/dev/tree/README.md +44 -0
- package/core/tools/dev/tree/install.sh +82 -0
- package/core/tools/dev/udocker/README.md +44 -0
- package/core/tools/dev/udocker/install.sh +82 -0
- package/core/tools/dev/wget/README.md +44 -0
- package/core/tools/dev/wget/install.sh +82 -0
- package/core/tools/editor/all.sh +58 -0
- package/core/tools/editor/neovim/README.md +43 -0
- package/core/tools/editor/neovim/install.sh +66 -0
- package/core/tools/editor/nvchad/README.md +45 -0
- package/core/tools/editor/nvchad/install.sh +110 -0
- package/core/tools/lang/all.sh +63 -0
- package/core/tools/lang/clang/README.md +43 -0
- package/core/tools/lang/clang/install.sh +79 -0
- package/core/tools/lang/golang/README.md +43 -0
- package/core/tools/lang/golang/install.sh +79 -0
- package/core/tools/lang/nodejs/README.md +43 -0
- package/core/tools/lang/nodejs/install.sh +79 -0
- package/core/tools/lang/perl/README.md +43 -0
- package/core/tools/lang/perl/install.sh +79 -0
- package/core/tools/lang/php/README.md +43 -0
- package/core/tools/lang/php/install.sh +79 -0
- package/core/tools/lang/python/README.md +43 -0
- package/core/tools/lang/python/install.sh +79 -0
- package/core/tools/lang/rust/README.md +43 -0
- package/core/tools/lang/rust/install.sh +79 -0
- package/core/tools/npm/all.sh +67 -0
- package/core/tools/npm/live-server/README.md +43 -0
- package/core/tools/npm/live-server/install.sh +95 -0
- package/core/tools/npm/localtunnel/README.md +43 -0
- package/core/tools/npm/localtunnel/install.sh +111 -0
- package/core/tools/npm/markserv/README.md +43 -0
- package/core/tools/npm/markserv/install.sh +94 -0
- package/core/tools/npm/ncu/README.md +43 -0
- package/core/tools/npm/ncu/install.sh +94 -0
- package/core/tools/npm/nestjs/README.md +43 -0
- package/core/tools/npm/nestjs/install.sh +94 -0
- package/core/tools/npm/ngrok/README.md +44 -0
- package/core/tools/npm/ngrok/install.sh +94 -0
- package/core/tools/npm/prettier/README.md +43 -0
- package/core/tools/npm/prettier/install.sh +94 -0
- package/core/tools/npm/psqlformat/README.md +43 -0
- package/core/tools/npm/psqlformat/install.sh +94 -0
- package/core/tools/npm/turbopack/README.md +8 -0
- package/core/tools/npm/turbopack/install.sh +41 -0
- package/core/tools/npm/typescript/README.md +43 -0
- package/core/tools/npm/typescript/install.sh +94 -0
- package/core/tools/npm/vercel/README.md +43 -0
- package/core/tools/npm/vercel/install.sh +94 -0
- package/core/tools/shell/all.sh +67 -0
- package/core/tools/shell/better-npm/README.md +43 -0
- package/core/tools/shell/better-npm/install.sh +85 -0
- package/core/tools/shell/fzf-tab/README.md +44 -0
- package/core/tools/shell/fzf-tab/install.sh +85 -0
- package/core/tools/shell/history-substring/README.md +43 -0
- package/core/tools/shell/history-substring/install.sh +85 -0
- package/core/tools/shell/powerlevel10k/README.md +43 -0
- package/core/tools/shell/powerlevel10k/install.sh +85 -0
- package/core/tools/shell/you-should-use/README.md +43 -0
- package/core/tools/shell/you-should-use/install.sh +85 -0
- package/core/tools/shell/zsh-autopair/README.md +44 -0
- package/core/tools/shell/zsh-autopair/install.sh +85 -0
- package/core/tools/shell/zsh-autosuggestions/README.md +43 -0
- package/core/tools/shell/zsh-autosuggestions/install.sh +85 -0
- package/core/tools/shell/zsh-completions/README.md +43 -0
- package/core/tools/shell/zsh-completions/install.sh +85 -0
- package/core/tools/shell/zsh-defer/README.md +43 -0
- package/core/tools/shell/zsh-defer/install.sh +85 -0
- package/core/tools/shell/zsh-syntax-highlighting/README.md +43 -0
- package/core/tools/shell/zsh-syntax-highlighting/install.sh +72 -0
- package/core/tools/ui/all.sh +61 -0
- package/core/tools/ui/banner/README.md +42 -0
- package/core/tools/ui/banner/install.sh +151 -0
- package/core/tools/ui/cursor/README.md +42 -0
- package/core/tools/ui/cursor/install.sh +58 -0
- package/core/tools/ui/extra-keys/README.md +43 -0
- package/core/tools/ui/extra-keys/install.sh +62 -0
- package/core/tools/ui/font/README.md +43 -0
- package/core/tools/ui/font/install.sh +63 -0
- package/core/utils/banner.sh +519 -0
- package/core/utils/bootstrap.sh +25 -0
- package/core/utils/colors.sh +31 -0
- package/core/utils/dialogrc +30 -0
- package/core/utils/env.sh +53 -0
- package/core/utils/log.sh +598 -0
- package/install.sh +272 -0
- package/package.json +43 -0
|
@@ -0,0 +1,1266 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
import "@/utils/log"
|
|
4
|
+
import "@/utils/colors"
|
|
5
|
+
|
|
6
|
+
LOG_FILE="$OMNI_CACHE/init_project.log"
|
|
7
|
+
|
|
8
|
+
init_help() {
|
|
9
|
+
echo
|
|
10
|
+
box "Omni Project Initializer"
|
|
11
|
+
echo
|
|
12
|
+
log_info "Usage: omni init <template>"
|
|
13
|
+
echo
|
|
14
|
+
log_info "Run this inside an existing project to configure it."
|
|
15
|
+
echo
|
|
16
|
+
separator_section "Available Templates"
|
|
17
|
+
echo
|
|
18
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "next" "Configure Next.js project"
|
|
19
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "react" "Configure React + Vite project"
|
|
20
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "nest" "Configure NestJS project"
|
|
21
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "express" "Configure Express.js API"
|
|
22
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "python" "Configure FastAPI project"
|
|
23
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "go" "Configure Go (Gin) project"
|
|
24
|
+
printf " ${D_CYAN}%-12s${NC} %s\n" "rust" "Configure Rust (Axum) project"
|
|
25
|
+
echo
|
|
26
|
+
separator_section "Examples"
|
|
27
|
+
echo
|
|
28
|
+
printf " ${D_CYAN}cd my-next-app && omni init next${NC}\n"
|
|
29
|
+
printf " ${D_CYAN}cd my-python-app && omni init python${NC}\n"
|
|
30
|
+
printf " ${D_CYAN}cd my-go-app && omni init go${NC}\n"
|
|
31
|
+
printf " ${D_CYAN}cd my-rust-app && omni init rust${NC}\n"
|
|
32
|
+
echo
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
check_project_exists() {
|
|
36
|
+
if [[ ! -f "package.json" ]]; then
|
|
37
|
+
log_error "No project found in current directory"
|
|
38
|
+
log_info "Make sure you're inside a project directory"
|
|
39
|
+
return 1
|
|
40
|
+
fi
|
|
41
|
+
return 0
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# ===== NEXT.JS =====
|
|
45
|
+
configure_next() {
|
|
46
|
+
separator
|
|
47
|
+
box "Configuring Next.js Project"
|
|
48
|
+
separator
|
|
49
|
+
echo
|
|
50
|
+
check_project_exists || return 1
|
|
51
|
+
|
|
52
|
+
if ! grep -q "next" package.json 2>/dev/null; then
|
|
53
|
+
log_warn "This doesn't appear to be a Next.js project"
|
|
54
|
+
read_confirm "Continue anyway?" CONFIRM
|
|
55
|
+
[[ "$CONFIRM" != "y" ]] && { log_warn "Cancelled"; return 0; }
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
log_info "Installing dependencies..."
|
|
59
|
+
if loading "Installing dependencies" _install_next_deps; then
|
|
60
|
+
log_success "Dependencies installed"
|
|
61
|
+
echo
|
|
62
|
+
list_item "axios, lucide-react, framer-motion, sonner, zod"
|
|
63
|
+
list_item "react-hook-form, @hookform/resolvers"
|
|
64
|
+
list_item "@tanstack/react-query, zustand, tailwindcss"
|
|
65
|
+
list_item "prettier, prettier-plugin-tailwindcss"
|
|
66
|
+
echo
|
|
67
|
+
else
|
|
68
|
+
log_warn "Some dependencies failed to install"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
log_info "Setting up structure..."
|
|
72
|
+
mkdir -p src/components/ui src/lib src/hooks src/types src/config src/store 2>/dev/null
|
|
73
|
+
|
|
74
|
+
# Crear .prettierrc
|
|
75
|
+
cat >.prettierrc <<'EOF'
|
|
76
|
+
{
|
|
77
|
+
"plugins": ["prettier-plugin-tailwindcss"]
|
|
78
|
+
}
|
|
79
|
+
EOF
|
|
80
|
+
log_success "Created .prettierrc"
|
|
81
|
+
|
|
82
|
+
log_info "Creating omni landing page..."
|
|
83
|
+
[[ -f "src/app/page.tsx" ]] && cat >src/app/page.tsx <<'EOF'
|
|
84
|
+
"use client"
|
|
85
|
+
import { Button } from "@/components/ui/button"
|
|
86
|
+
import { motion } from "framer-motion"
|
|
87
|
+
import { Terminal, Code2, Rocket } from "lucide-react"
|
|
88
|
+
import { Toaster } from "sonner"
|
|
89
|
+
|
|
90
|
+
export default function Home() {
|
|
91
|
+
return (
|
|
92
|
+
<main className="min-h-screen bg-gradient-to-b from-black via-slate-950 to-slate-900">
|
|
93
|
+
<Toaster position="top-center" richColors />
|
|
94
|
+
<div className="container mx-auto px-4 py-20">
|
|
95
|
+
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="text-center">
|
|
96
|
+
<motion.div initial={{ scale: 0 }} animate={{ scale: 1 }} transition={{ delay: 0.2, type: "spring" }} className="mb-8 flex justify-center">
|
|
97
|
+
<div className="p-4 bg-gradient-to-br from-blue-500 to-purple-600 rounded-2xl shadow-2xl">
|
|
98
|
+
<Terminal className="w-16 h-16 text-white" />
|
|
99
|
+
</div>
|
|
100
|
+
</motion.div>
|
|
101
|
+
<motion.h1 initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.3 }} className="text-5xl md:text-7xl font-bold mb-6 bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">
|
|
102
|
+
omni
|
|
103
|
+
</motion.h1>
|
|
104
|
+
<motion.p initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.4 }} className="text-xl md:text-2xl text-slate-400 mb-4">
|
|
105
|
+
Comunidad de Desarrollo y Tecnología
|
|
106
|
+
</motion.p>
|
|
107
|
+
<motion.p initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.5 }} className="text-lg text-slate-500 mb-12 max-w-2xl mx-auto">
|
|
108
|
+
Este proyecto fue creado con herramientas de la comunidad omni.
|
|
109
|
+
</motion.p>
|
|
110
|
+
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.6 }} className="grid md:grid-cols-3 gap-6 mb-12 max-w-4xl mx-auto">
|
|
111
|
+
<div className="p-6 rounded-xl bg-slate-900/50 border border-slate-800"><Code2 className="w-12 h-12 text-blue-400 mb-4 mx-auto" /><h3 className="text-lg font-semibold text-white mb-2">Código de Calidad</h3></div>
|
|
112
|
+
<div className="p-6 rounded-xl bg-slate-900/50 border border-slate-800"><Rocket className="w-12 h-12 text-purple-400 mb-4 mx-auto" /><h3 className="text-lg font-semibold text-white mb-2">Proyectos Reales</h3></div>
|
|
113
|
+
<div className="p-6 rounded-xl bg-slate-900/50 border border-slate-800"><Terminal className="w-12 h-12 text-pink-400 mb-4 mx-auto" /><h3 className="text-lg font-semibold text-white mb-2">Comunidad Activa</h3></div>
|
|
114
|
+
</motion.div>
|
|
115
|
+
<motion.div initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.7 }} className="w-full max-w-sm mx-auto">
|
|
116
|
+
<Button size="lg" onClick={() => window.open("https://youtube.com/@devcorex", "_blank")} className="w-full bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-8 py-6 text-lg font-semibold">
|
|
117
|
+
<Rocket className="w-5 h-5 mr-2" /> Únete a omni en YouTube
|
|
118
|
+
</Button>
|
|
119
|
+
</motion.div>
|
|
120
|
+
<motion.p initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.8 }} className="mt-16 text-sm text-slate-600">Built with ❤️ using omni tools</motion.p>
|
|
121
|
+
</motion.div>
|
|
122
|
+
</div>
|
|
123
|
+
</main>
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
EOF
|
|
127
|
+
|
|
128
|
+
# Actualizar package.json para usar --webpack
|
|
129
|
+
if [[ -f "package.json" ]]; then
|
|
130
|
+
log_info "Updating package.json scripts..."
|
|
131
|
+
local temp=$(mktemp)
|
|
132
|
+
jq '.scripts.dev = "next dev --webpack" | .scripts.build = "next build --webpack" | .scripts.start = "next start"' package.json > "$temp" && mv "$temp" package.json
|
|
133
|
+
log_success "Added --webpack flag to dev and build scripts"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
[[ -f "src/app/layout.tsx" ]] && cat >src/app/layout.tsx <<'EOF'
|
|
137
|
+
import type { Metadata } from "next"
|
|
138
|
+
import { Inter } from "next/font/google"
|
|
139
|
+
import "./globals.css"
|
|
140
|
+
const inter = Inter({ subsets: ["latin"] })
|
|
141
|
+
export const metadata: Metadata = {
|
|
142
|
+
title: "omni - Comunidad de Desarrollo",
|
|
143
|
+
description: "Únete a la comunidad omni",
|
|
144
|
+
}
|
|
145
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
146
|
+
return (<html lang="es"><body className={inter.className}>{children}</body></html>)
|
|
147
|
+
}
|
|
148
|
+
EOF
|
|
149
|
+
|
|
150
|
+
echo
|
|
151
|
+
separator
|
|
152
|
+
log_success "Next.js configured!"
|
|
153
|
+
separator
|
|
154
|
+
echo
|
|
155
|
+
list_item "Dependencies installed"
|
|
156
|
+
list_item "omni landing page created"
|
|
157
|
+
list_item "Prettier configured"
|
|
158
|
+
echo
|
|
159
|
+
log_info "Next steps:"
|
|
160
|
+
echo
|
|
161
|
+
list_item "Initialize shadcn: ${D_CYAN}npx shadcn@latest init${NC}"
|
|
162
|
+
list_item "Add button: ${D_CYAN}npx shadcn@latest add button${NC}"
|
|
163
|
+
list_item "Start: ${D_CYAN}npm run dev${NC} (with --webpack)"
|
|
164
|
+
echo
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
_install_next_deps() {
|
|
168
|
+
npm install axios lucide-react framer-motion sonner zod react-hook-form @hookform/resolvers @tanstack/react-query zustand tailwindcss &>"$LOG_FILE"
|
|
169
|
+
npm install -D prettier prettier-plugin-tailwindcss &>>"$LOG_FILE"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
# ===== REACT + VITE =====
|
|
173
|
+
configure_react() {
|
|
174
|
+
separator
|
|
175
|
+
box "Configuring React + Vite Project"
|
|
176
|
+
separator
|
|
177
|
+
echo
|
|
178
|
+
check_project_exists || return 1
|
|
179
|
+
|
|
180
|
+
if ! grep -q "vite" package.json 2>/dev/null; then
|
|
181
|
+
log_warn "This doesn't appear to be a Vite project"
|
|
182
|
+
read_confirm "Continue anyway?" CONFIRM
|
|
183
|
+
[[ "$CONFIRM" != "y" ]] && { log_warn "Cancelled"; return 0; }
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
log_info "Installing dependencies..."
|
|
187
|
+
if loading "Installing dependencies" _install_react_deps; then
|
|
188
|
+
log_success "Dependencies installed"
|
|
189
|
+
echo
|
|
190
|
+
list_item "axios, lucide-react, framer-motion, sonner, zod"
|
|
191
|
+
list_item "react-hook-form, @hookform/resolvers"
|
|
192
|
+
list_item "@tanstack/react-query, zustand, tailwindcss"
|
|
193
|
+
list_item "prettier, prettier-plugin-tailwindcss"
|
|
194
|
+
echo
|
|
195
|
+
else
|
|
196
|
+
log_warn "Some dependencies failed to install"
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
log_info "Setting up structure..."
|
|
200
|
+
mkdir -p src/components/ui src/lib src/hooks src/types src/config src/store src/pages 2>/dev/null
|
|
201
|
+
|
|
202
|
+
# Crear .prettierrc
|
|
203
|
+
cat >.prettierrc <<'EOF'
|
|
204
|
+
{
|
|
205
|
+
"plugins": ["prettier-plugin-tailwindcss"]
|
|
206
|
+
}
|
|
207
|
+
EOF
|
|
208
|
+
log_success "Created .prettierrc"
|
|
209
|
+
|
|
210
|
+
log_info "Creating omni landing page..."
|
|
211
|
+
if [[ -f "src/App.tsx" ]]; then
|
|
212
|
+
cat >src/App.tsx <<'EOF'
|
|
213
|
+
import { Button } from "./components/ui/Button"
|
|
214
|
+
import { motion } from "framer-motion"
|
|
215
|
+
import { Terminal, Code2, Rocket } from "lucide-react"
|
|
216
|
+
import { Toaster } from "sonner"
|
|
217
|
+
|
|
218
|
+
function App() {
|
|
219
|
+
return (
|
|
220
|
+
<main className="min-h-screen bg-gradient-to-b from-black via-slate-950 to-slate-900">
|
|
221
|
+
<Toaster position="top-center" richColors />
|
|
222
|
+
<div className="container mx-auto px-4 py-20">
|
|
223
|
+
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="text-center">
|
|
224
|
+
<motion.div initial={{ scale: 0 }} animate={{ scale: 1 }} transition={{ delay: 0.2, type: "spring" }} className="mb-8 flex justify-center">
|
|
225
|
+
<div className="p-4 bg-gradient-to-br from-blue-500 to-purple-600 rounded-2xl shadow-2xl">
|
|
226
|
+
<Terminal className="w-16 h-16 text-white" />
|
|
227
|
+
</div>
|
|
228
|
+
</motion.div>
|
|
229
|
+
<motion.h1 initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.3 }} className="text-5xl md:text-7xl font-bold mb-6 bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">omni</motion.h1>
|
|
230
|
+
<motion.p initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.4 }} className="text-xl md:text-2xl text-slate-400 mb-4">Comunidad de Desarrollo y Tecnología</motion.p>
|
|
231
|
+
<motion.p initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.5 }} className="text-lg text-slate-500 mb-12 max-w-2xl mx-auto">Este proyecto fue creado con herramientas de la comunidad omni.</motion.p>
|
|
232
|
+
<motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.6 }} className="grid md:grid-cols-3 gap-6 mb-12 max-w-4xl mx-auto">
|
|
233
|
+
<div className="p-6 rounded-xl bg-slate-900/50 border border-slate-800"><Code2 className="w-12 h-12 text-blue-400 mb-4 mx-auto" /><h3 className="text-lg font-semibold text-white mb-2">Código de Calidad</h3></div>
|
|
234
|
+
<div className="p-6 rounded-xl bg-slate-900/50 border border-slate-800"><Rocket className="w-12 h-12 text-purple-400 mb-4 mx-auto" /><h3 className="text-lg font-semibold text-white mb-2">Proyectos Reales</h3></div>
|
|
235
|
+
<div className="p-6 rounded-xl bg-slate-900/50 border border-slate-800"><Terminal className="w-12 h-12 text-pink-400 mb-4 mx-auto" /><h3 className="text-lg font-semibold text-white mb-2">Comunidad Activa</h3></div>
|
|
236
|
+
</motion.div>
|
|
237
|
+
<motion.div initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: 0.7 }} className="w-full max-w-sm mx-auto">
|
|
238
|
+
<Button size="lg" onClick={() => window.open("https://youtube.com/@devcorex", "_blank")} className="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white px-8 py-6 text-lg">
|
|
239
|
+
<Rocket className="w-5 h-5 mr-2" /> Únete a omni en YouTube
|
|
240
|
+
</Button>
|
|
241
|
+
</motion.div>
|
|
242
|
+
<motion.p initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.8 }} className="mt-16 text-sm text-slate-600">Built with ❤️ using omni tools</motion.p>
|
|
243
|
+
</motion.div>
|
|
244
|
+
</div>
|
|
245
|
+
</main>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
export default App
|
|
249
|
+
EOF
|
|
250
|
+
log_success "Created landing page"
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
if [[ ! -f "src/components/ui/Button.tsx" ]]; then
|
|
254
|
+
mkdir -p src/components/ui
|
|
255
|
+
cat >src/components/ui/Button.tsx <<'EOF'
|
|
256
|
+
import { ButtonHTMLAttributes, forwardRef } from 'react'
|
|
257
|
+
import { clsx } from 'clsx'
|
|
258
|
+
import { twMerge } from 'tailwind-merge'
|
|
259
|
+
function cn(...inputs: any[]) { return twMerge(clsx(inputs)) }
|
|
260
|
+
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
261
|
+
variant?: 'default' | 'outline' | 'ghost'
|
|
262
|
+
size?: 'sm' | 'md' | 'lg'
|
|
263
|
+
}
|
|
264
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
265
|
+
({ className, variant = 'default', size = 'md', children, ...props }, ref) => {
|
|
266
|
+
return (
|
|
267
|
+
<button className={cn('inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
268
|
+
{ 'bg-primary text-primary-foreground hover:bg-primary/90': variant === 'default',
|
|
269
|
+
'border border-input hover:bg-accent hover:text-accent-foreground': variant === 'outline',
|
|
270
|
+
'hover:bg-accent hover:text-accent-foreground': variant === 'ghost',
|
|
271
|
+
'h-9 px-3 text-sm': size === 'sm', 'h-10 px-4': size === 'md', 'h-11 px-8': size === 'lg' },
|
|
272
|
+
className)} ref={ref} {...props}>{children}</button>
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
Button.displayName = 'Button'
|
|
277
|
+
EOF
|
|
278
|
+
log_success "Created Button component"
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
echo
|
|
282
|
+
separator
|
|
283
|
+
log_success "React + Vite configured!"
|
|
284
|
+
separator
|
|
285
|
+
echo
|
|
286
|
+
list_item "Dependencies installed"
|
|
287
|
+
list_item "Prettier configured"
|
|
288
|
+
echo
|
|
289
|
+
list_item "Start: ${D_CYAN}npm run dev${NC}"
|
|
290
|
+
echo
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
_install_react_deps() {
|
|
294
|
+
npm install axios lucide-react framer-motion sonner zod react-hook-form @hookform/resolvers @tanstack/react-query zustand tailwindcss &>"$LOG_FILE"
|
|
295
|
+
npm install -D prettier prettier-plugin-tailwindcss &>>"$LOG_FILE"
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
# ===== EXPRESS.JS =====
|
|
299
|
+
configure_express() {
|
|
300
|
+
separator
|
|
301
|
+
box "Configuring Express.js Project"
|
|
302
|
+
separator
|
|
303
|
+
echo
|
|
304
|
+
check_project_exists || return 1
|
|
305
|
+
|
|
306
|
+
if ! grep -q "express" package.json 2>/dev/null; then
|
|
307
|
+
log_warn "This doesn't appear to be an Express project"
|
|
308
|
+
read_confirm "Continue anyway?" CONFIRM
|
|
309
|
+
[[ "$CONFIRM" != "y" ]] && { log_warn "Cancelled"; return 0; }
|
|
310
|
+
fi
|
|
311
|
+
|
|
312
|
+
log_info "Installing dependencies..."
|
|
313
|
+
if loading "Installing dependencies" _install_express_deps; then
|
|
314
|
+
log_success "Dependencies installed"
|
|
315
|
+
echo
|
|
316
|
+
list_item "express, pg, typeorm, reflect-metadata"
|
|
317
|
+
list_item "jsonwebtoken, cookie-parser, morgan, cors"
|
|
318
|
+
list_item "bcryptjs, helmet, cloudinary, multer"
|
|
319
|
+
list_item "express-rate-limit, zod"
|
|
320
|
+
echo
|
|
321
|
+
else
|
|
322
|
+
log_warn "Some dependencies failed to install"
|
|
323
|
+
fi
|
|
324
|
+
|
|
325
|
+
log_info "Installing devDependencies..."
|
|
326
|
+
if loading "Installing devDependencies" _install_express_dev; then
|
|
327
|
+
log_success "devDependencies installed"
|
|
328
|
+
echo
|
|
329
|
+
list_item "typescript, ts-node-dev, tsconfig-paths, tsc-alias"
|
|
330
|
+
list_item "@types/* (all type definitions)"
|
|
331
|
+
echo
|
|
332
|
+
else
|
|
333
|
+
log_warn "Some devDependencies failed to install"
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
log_info "Creating folder structure..."
|
|
337
|
+
_setup_express_structure
|
|
338
|
+
|
|
339
|
+
log_info "Creating configuration files..."
|
|
340
|
+
_create_express_config
|
|
341
|
+
|
|
342
|
+
echo
|
|
343
|
+
separator
|
|
344
|
+
log_success "Express.js configured!"
|
|
345
|
+
separator
|
|
346
|
+
echo
|
|
347
|
+
list_item "Start: ${D_CYAN}npm run dev${NC}"
|
|
348
|
+
list_item "Build: ${D_CYAN}npm run build${NC}"
|
|
349
|
+
list_item "Migrations: ${D_CYAN}npm run mg:run${NC}"
|
|
350
|
+
echo
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
_install_express_deps() {
|
|
354
|
+
npm install express pg typeorm reflect-metadata jsonwebtoken cookie-parser morgan cors bcryptjs helmet cloudinary multer express-rate-limit tsconfig-paths zod &>"$LOG_FILE"
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
_install_express_dev() {
|
|
358
|
+
npm install -D typescript ts-node-dev tsconfig-paths tsc-alias @types/node @types/multer @types/morgan @types/jsonwebtoken @types/helmet @types/express @types/cors @types/cookie-parser @types/bcryptjs &>>"$LOG_FILE"
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
_setup_express_structure() {
|
|
362
|
+
mkdir -p src/controllers 2>/dev/null
|
|
363
|
+
mkdir -p src/middlewares 2>/dev/null
|
|
364
|
+
mkdir -p src/repositories 2>/dev/null
|
|
365
|
+
mkdir -p src/routes 2>/dev/null
|
|
366
|
+
mkdir -p src/schemas 2>/dev/null
|
|
367
|
+
mkdir -p src/services 2>/dev/null
|
|
368
|
+
mkdir -p src/types 2>/dev/null
|
|
369
|
+
mkdir -p src/utils 2>/dev/null
|
|
370
|
+
mkdir -p src/config 2>/dev/null
|
|
371
|
+
mkdir -p src/database/migrations 2>/dev/null
|
|
372
|
+
mkdir -p src/database/seeds 2>/dev/null
|
|
373
|
+
mkdir -p src/entities 2>/dev/null
|
|
374
|
+
log_success "Created folder structure"
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
_create_express_config() {
|
|
378
|
+
cat >tsconfig.json <<'EOF'
|
|
379
|
+
{
|
|
380
|
+
"compilerOptions": {
|
|
381
|
+
"target": "ES2020",
|
|
382
|
+
"module": "commonjs",
|
|
383
|
+
"lib": ["ES2020"],
|
|
384
|
+
"outDir": "./dist",
|
|
385
|
+
"rootDir": "./src",
|
|
386
|
+
"strict": true,
|
|
387
|
+
"esModuleInterop": true,
|
|
388
|
+
"skipLibCheck": true,
|
|
389
|
+
"forceConsistentCasingInFileNames": true,
|
|
390
|
+
"resolveJsonModule": true,
|
|
391
|
+
"moduleResolution": "node",
|
|
392
|
+
"baseUrl": ".",
|
|
393
|
+
"paths": { "@/*": ["src/*"] },
|
|
394
|
+
"experimentalDecorators": true,
|
|
395
|
+
"emitDecoratorMetadata": true,
|
|
396
|
+
"strictPropertyInitialization": false
|
|
397
|
+
},
|
|
398
|
+
"include": ["src/**/*"],
|
|
399
|
+
"exclude": ["node_modules", "dist"]
|
|
400
|
+
}
|
|
401
|
+
EOF
|
|
402
|
+
log_success "Created tsconfig.json"
|
|
403
|
+
|
|
404
|
+
cat >.env.example <<'EOF'
|
|
405
|
+
NODE_ENV=development
|
|
406
|
+
PORT=4000
|
|
407
|
+
DB_NAME=postgres
|
|
408
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
|
|
409
|
+
JWT_SECRET=your-super-secret-jwt-key
|
|
410
|
+
FRONTEND_URL=http://localhost:3000
|
|
411
|
+
CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME
|
|
412
|
+
EOF
|
|
413
|
+
log_success "Created .env.example"
|
|
414
|
+
|
|
415
|
+
cat >src/config/env.ts <<'EOF'
|
|
416
|
+
export const NODE_ENV = process.env.NODE_ENV || "development";
|
|
417
|
+
export const PORT = Number(process.env.PORT) || 4000;
|
|
418
|
+
export const DB_NAME = process.env.DB_NAME || "postgres";
|
|
419
|
+
export const DATABASE_URL = process.env.DATABASE_URL;
|
|
420
|
+
export const JWT_SECRET = process.env.JWT_SECRET as string;
|
|
421
|
+
export const FRONTEND_URL = (process.env.FRONTEND_URL as string) || "http://localhost:3000";
|
|
422
|
+
EOF
|
|
423
|
+
log_success "Created src/config/env.ts"
|
|
424
|
+
|
|
425
|
+
cat >src/database/data-source.ts <<'EOF'
|
|
426
|
+
import "reflect-metadata";
|
|
427
|
+
import { DataSource } from "typeorm";
|
|
428
|
+
import { DATABASE_URL, NODE_ENV } from "@/config/env";
|
|
429
|
+
import { ExampleEntity1 } from "@/entities/ExampleEntity1";
|
|
430
|
+
import { ExampleEntity2 } from "@/entities/ExampleEntity2";
|
|
431
|
+
|
|
432
|
+
const isDevelopment = NODE_ENV === "development";
|
|
433
|
+
const isProduction = NODE_ENV === "production";
|
|
434
|
+
|
|
435
|
+
export const AppDataSource = new DataSource({
|
|
436
|
+
type: "postgres",
|
|
437
|
+
url: DATABASE_URL,
|
|
438
|
+
ssl: isDevelopment ? false : { rejectUnauthorized: false },
|
|
439
|
+
synchronize: isDevelopment,
|
|
440
|
+
logging: isDevelopment ? ["query", "error"] : false,
|
|
441
|
+
entities: [ExampleEntity1, ExampleEntity2],
|
|
442
|
+
migrations: isDevelopment
|
|
443
|
+
? [__dirname + "/migrations/*.ts"]
|
|
444
|
+
: [__dirname + "/migrations/*.js"],
|
|
445
|
+
migrationsRun: isDevelopment,
|
|
446
|
+
extra: {
|
|
447
|
+
max: isProduction ? 10 : 20,
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
EOF
|
|
451
|
+
log_success "Created src/database/data-source.ts"
|
|
452
|
+
|
|
453
|
+
cat >src/app.ts <<'EOF'
|
|
454
|
+
import express from "express";
|
|
455
|
+
import rateLimit from "express-rate-limit";
|
|
456
|
+
import helmet from "helmet";
|
|
457
|
+
import morgan from "morgan";
|
|
458
|
+
import cors from "cors";
|
|
459
|
+
import cookieParser from "cookie-parser";
|
|
460
|
+
import { FRONTEND_URL } from "@/config/env";
|
|
461
|
+
import exampleRoutes1 from "@/routes/example1.routes";
|
|
462
|
+
import exampleRoutes2 from "@/routes/example2.routes";
|
|
463
|
+
|
|
464
|
+
const app = express();
|
|
465
|
+
|
|
466
|
+
// monitorear peticiones HTTP (logger)
|
|
467
|
+
app.use(morgan("dev"));
|
|
468
|
+
|
|
469
|
+
// proteger cabeceras HTTP (seguridad)
|
|
470
|
+
app.use(helmet());
|
|
471
|
+
|
|
472
|
+
// habilitar acceso desde otros orígenes
|
|
473
|
+
app.use(
|
|
474
|
+
cors({
|
|
475
|
+
origin: FRONTEND_URL,
|
|
476
|
+
credentials: true,
|
|
477
|
+
}),
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
// limitar número de peticiones
|
|
481
|
+
const limiter = rateLimit({
|
|
482
|
+
windowMs: 15 * 60 * 1000,
|
|
483
|
+
max: 100,
|
|
484
|
+
standardHeaders: true,
|
|
485
|
+
legacyHeaders: false,
|
|
486
|
+
});
|
|
487
|
+
app.use(limiter);
|
|
488
|
+
|
|
489
|
+
// parsear JSON en el body
|
|
490
|
+
app.use(express.json());
|
|
491
|
+
|
|
492
|
+
// manejar cookies
|
|
493
|
+
app.use(cookieParser());
|
|
494
|
+
|
|
495
|
+
// endpoints
|
|
496
|
+
app.use("/api/example1", exampleRoutes1);
|
|
497
|
+
app.use("/api/example2", exampleRoutes2);
|
|
498
|
+
|
|
499
|
+
export default app;
|
|
500
|
+
EOF
|
|
501
|
+
log_success "Created src/app.ts"
|
|
502
|
+
|
|
503
|
+
cat >src/index.ts <<'EOF'
|
|
504
|
+
import app from "@/app";
|
|
505
|
+
import { DB_NAME, PORT } from "@/config/env";
|
|
506
|
+
import { AppDataSource } from "@/database/data-source";
|
|
507
|
+
|
|
508
|
+
async function main() {
|
|
509
|
+
try {
|
|
510
|
+
await AppDataSource.initialize();
|
|
511
|
+
console.log(" Connected to:", DB_NAME);
|
|
512
|
+
app.listen(PORT, () => {
|
|
513
|
+
console.log(" http://localhost:" + PORT);
|
|
514
|
+
});
|
|
515
|
+
} catch (error) {
|
|
516
|
+
console.error("Internal server error:", error);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
main();
|
|
521
|
+
EOF
|
|
522
|
+
log_success "Created src/index.ts"
|
|
523
|
+
|
|
524
|
+
# Agregar scripts al package.json
|
|
525
|
+
if [[ -f "package.json" ]]; then
|
|
526
|
+
log_info "Adding scripts to package.json..."
|
|
527
|
+
local temp=$(mktemp)
|
|
528
|
+
jq '.scripts += {
|
|
529
|
+
"dev": "ts-node-dev --require tsconfig-paths/register --env-file=.env --respawn src/index.ts",
|
|
530
|
+
"build": "tsc && tsc-alias -p tsconfig.json",
|
|
531
|
+
"start": "node dist/index.js",
|
|
532
|
+
"typeorm": "ts-node-dev --require tsconfig-paths/register --env-file=.env ./node_modules/typeorm/cli.js",
|
|
533
|
+
"mg:gen": "npm run typeorm -- migration:generate -d src/database/data-source.ts",
|
|
534
|
+
"mg:create": "npm run typeorm -- migration:create",
|
|
535
|
+
"mg:run": "npm run typeorm -- migration:run -d src/database/data-source.ts",
|
|
536
|
+
"mg:revert": "npm run typeorm -- migration:revert -d src/database/data-source.ts",
|
|
537
|
+
"mg:show": "npm run typeorm -- migration:show -d src/database/data-source.ts"
|
|
538
|
+
}' package.json > "$temp" && mv "$temp" package.json
|
|
539
|
+
log_success "Added scripts to package.json"
|
|
540
|
+
fi
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
# ===== NESTJS =====
|
|
544
|
+
configure_nest() {
|
|
545
|
+
separator
|
|
546
|
+
box "Configuring NestJS Project"
|
|
547
|
+
separator
|
|
548
|
+
echo
|
|
549
|
+
check_project_exists || return 1
|
|
550
|
+
|
|
551
|
+
if ! grep -q "@nestjs" package.json 2>/dev/null; then
|
|
552
|
+
log_warn "This doesn't appear to be a NestJS project"
|
|
553
|
+
read_confirm "Continue anyway?" CONFIRM
|
|
554
|
+
[[ "$CONFIRM" != "y" ]] && { log_warn "Cancelled"; return 0; }
|
|
555
|
+
fi
|
|
556
|
+
|
|
557
|
+
log_info "Installing NestJS dependencies..."
|
|
558
|
+
if loading "Installing dependencies" _install_nest_deps; then
|
|
559
|
+
log_success "Dependencies installed"
|
|
560
|
+
echo
|
|
561
|
+
list_item "@nestjs/typeorm, typeorm, pg"
|
|
562
|
+
list_item "@nestjs/jwt, @nestjs/passport"
|
|
563
|
+
list_item "class-validator, class-transformer"
|
|
564
|
+
list_item "bcryptjs, helmet, cloudinary"
|
|
565
|
+
echo
|
|
566
|
+
else
|
|
567
|
+
log_warn "Some dependencies failed to install"
|
|
568
|
+
fi
|
|
569
|
+
|
|
570
|
+
echo
|
|
571
|
+
separator
|
|
572
|
+
log_success "NestJS configured!"
|
|
573
|
+
separator
|
|
574
|
+
echo
|
|
575
|
+
list_item "Start: ${D_CYAN}npm run start:dev${NC}"
|
|
576
|
+
echo
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
_install_nest_deps() {
|
|
580
|
+
npm install @nestjs/typeorm typeorm pg @nestjs/jwt @nestjs/passport passport passport-jwt passport-local class-validator class-transformer bcryptjs helmet cloudinary &>>"$LOG_FILE"
|
|
581
|
+
npm install -D @types/passport-jwt @types/passport-local @types/bcryptjs &>>"$LOG_FILE"
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
configure_python() {
|
|
585
|
+
separator
|
|
586
|
+
box "Configuring Python (FastAPI) Project"
|
|
587
|
+
separator
|
|
588
|
+
echo
|
|
589
|
+
|
|
590
|
+
local orm_choice db_choice docker_choice
|
|
591
|
+
read_select "Select database ORM" orm_choice "SQLModel" "SQLAlchemy" "None"
|
|
592
|
+
read_select "Select database provider" db_choice "SQLite" "PostgreSQL"
|
|
593
|
+
read_select "Enable Docker & Udocker support?" docker_choice "Yes" "No"
|
|
594
|
+
|
|
595
|
+
log_info "Creating folder structure..."
|
|
596
|
+
mkdir -p app/api/v1/endpoints app/core app/models app/schemas scripts 2>/dev/null
|
|
597
|
+
|
|
598
|
+
# Create app/core/config.py
|
|
599
|
+
cat >app/core/config.py <<'EOF'
|
|
600
|
+
import os
|
|
601
|
+
from pydantic_settings import BaseSettings
|
|
602
|
+
|
|
603
|
+
class Settings(BaseSettings):
|
|
604
|
+
APP_NAME: str = "Omni FastAPI"
|
|
605
|
+
DATABASE_URL: str = os.getenv("DATABASE_URL", "sqlite:///./sql_app.db")
|
|
606
|
+
API_V1_STR: str = "/api/v1"
|
|
607
|
+
|
|
608
|
+
settings = Settings()
|
|
609
|
+
EOF
|
|
610
|
+
log_success "Created app/core/config.py"
|
|
611
|
+
|
|
612
|
+
# Create app/models/item.py
|
|
613
|
+
if [[ "$orm_choice" == "SQLModel" ]]; then
|
|
614
|
+
cat >app/models/item.py <<'EOF'
|
|
615
|
+
from typing import Optional
|
|
616
|
+
from sqlmodel import Field, SQLModel
|
|
617
|
+
|
|
618
|
+
class Item(SQLModel, table=True):
|
|
619
|
+
id: Optional[int] = Field(default=None, primary_key=True)
|
|
620
|
+
title: str
|
|
621
|
+
description: Optional[str] = None
|
|
622
|
+
EOF
|
|
623
|
+
elif [[ "$orm_choice" == "SQLAlchemy" ]]; then
|
|
624
|
+
cat >app/models/item.py <<'EOF'
|
|
625
|
+
from sqlalchemy import Column, Integer, String
|
|
626
|
+
from app.core.db import Base
|
|
627
|
+
|
|
628
|
+
class Item(Base):
|
|
629
|
+
__tablename__ = "items"
|
|
630
|
+
|
|
631
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
632
|
+
title = Column(String, index=True)
|
|
633
|
+
description = Column(String, nullable=True)
|
|
634
|
+
EOF
|
|
635
|
+
fi
|
|
636
|
+
log_success "Created app/models/item.py"
|
|
637
|
+
|
|
638
|
+
# Create app/core/db.py
|
|
639
|
+
if [[ "$orm_choice" == "SQLModel" ]]; then
|
|
640
|
+
cat >app/core/db.py <<'EOF'
|
|
641
|
+
from sqlmodel import create_engine, Session, SQLModel
|
|
642
|
+
from app.core.config import settings
|
|
643
|
+
|
|
644
|
+
engine = create_engine(settings.DATABASE_URL, echo=True)
|
|
645
|
+
|
|
646
|
+
def get_session():
|
|
647
|
+
with Session(engine) as session:
|
|
648
|
+
yield session
|
|
649
|
+
EOF
|
|
650
|
+
elif [[ "$orm_choice" == "SQLAlchemy" ]]; then
|
|
651
|
+
cat >app/core/db.py <<'EOF'
|
|
652
|
+
from sqlalchemy import create_engine
|
|
653
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
654
|
+
from sqlalchemy.orm import sessionmaker
|
|
655
|
+
from app.core.config import settings
|
|
656
|
+
|
|
657
|
+
engine = create_engine(settings.DATABASE_URL)
|
|
658
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
659
|
+
Base = declarative_base()
|
|
660
|
+
|
|
661
|
+
def get_session():
|
|
662
|
+
db = SessionLocal()
|
|
663
|
+
try:
|
|
664
|
+
yield db
|
|
665
|
+
finally:
|
|
666
|
+
db.close()
|
|
667
|
+
EOF
|
|
668
|
+
else
|
|
669
|
+
cat >app/core/db.py <<'EOF'
|
|
670
|
+
# No ORM configured
|
|
671
|
+
EOF
|
|
672
|
+
fi
|
|
673
|
+
log_success "Created app/core/db.py"
|
|
674
|
+
|
|
675
|
+
# Create app/api/v1/endpoints/items.py
|
|
676
|
+
cat >app/api/v1/endpoints/items.py <<'EOF'
|
|
677
|
+
from fastapi import APIRouter, Depends
|
|
678
|
+
from typing import List
|
|
679
|
+
|
|
680
|
+
router = APIRouter()
|
|
681
|
+
|
|
682
|
+
@router.get("/")
|
|
683
|
+
def get_items():
|
|
684
|
+
return [{"id": 1, "title": "First Item", "description": "Omni template item"}]
|
|
685
|
+
EOF
|
|
686
|
+
log_success "Created app/api/v1/endpoints/items.py"
|
|
687
|
+
|
|
688
|
+
# Create app/main.py
|
|
689
|
+
cat >app/main.py <<'EOF'
|
|
690
|
+
from fastapi import FastAPI
|
|
691
|
+
from app.core.config import settings
|
|
692
|
+
from app.api.v1.endpoints import items
|
|
693
|
+
|
|
694
|
+
app = FastAPI(title=settings.APP_NAME, version="0.1.0")
|
|
695
|
+
|
|
696
|
+
app.include_router(items.router, prefix=f"{settings.API_V1_STR}/items", tags=["items"])
|
|
697
|
+
|
|
698
|
+
@app.get("/")
|
|
699
|
+
def read_root():
|
|
700
|
+
return {"message": "Welcome to Omni FastAPI!", "status": "healthy"}
|
|
701
|
+
EOF
|
|
702
|
+
log_success "Created app/main.py"
|
|
703
|
+
|
|
704
|
+
# Create requirements.txt
|
|
705
|
+
if [[ ! -f "requirements.txt" ]]; then
|
|
706
|
+
cat >requirements.txt <<EOF
|
|
707
|
+
fastapi>=0.100.0
|
|
708
|
+
uvicorn[standard]>=0.22.0
|
|
709
|
+
pydantic>=2.0
|
|
710
|
+
pydantic-settings>=2.0
|
|
711
|
+
EOF
|
|
712
|
+
if [[ "$orm_choice" == "SQLModel" ]]; then
|
|
713
|
+
echo "sqlmodel>=0.0.8" >>requirements.txt
|
|
714
|
+
elif [[ "$orm_choice" == "SQLAlchemy" ]]; then
|
|
715
|
+
echo "sqlalchemy>=2.0" >>requirements.txt
|
|
716
|
+
fi
|
|
717
|
+
if [[ "$db_choice" == "PostgreSQL" ]]; then
|
|
718
|
+
echo "psycopg2-binary>=2.9" >>requirements.txt
|
|
719
|
+
fi
|
|
720
|
+
log_success "Created requirements.txt"
|
|
721
|
+
fi
|
|
722
|
+
|
|
723
|
+
# Create .env
|
|
724
|
+
if [[ ! -f ".env" ]]; then
|
|
725
|
+
if [[ "$db_choice" == "SQLite" ]]; then
|
|
726
|
+
echo "DATABASE_URL=sqlite:///./sql_app.db" >.env
|
|
727
|
+
else
|
|
728
|
+
echo "DATABASE_URL=postgresql://postgres:postgres@localhost:5432/mydb" >.env
|
|
729
|
+
fi
|
|
730
|
+
log_success "Created .env"
|
|
731
|
+
fi
|
|
732
|
+
|
|
733
|
+
# Create Dockerfile
|
|
734
|
+
if [[ "$docker_choice" == "Yes" ]]; then
|
|
735
|
+
cat >Dockerfile <<'EOF'
|
|
736
|
+
FROM python:3.11-slim
|
|
737
|
+
|
|
738
|
+
WORKDIR /app
|
|
739
|
+
|
|
740
|
+
COPY requirements.txt .
|
|
741
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
742
|
+
|
|
743
|
+
COPY . .
|
|
744
|
+
|
|
745
|
+
EXPOSE 8000
|
|
746
|
+
|
|
747
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
748
|
+
EOF
|
|
749
|
+
cat >docker-compose.yml <<'EOF'
|
|
750
|
+
version: '3.8'
|
|
751
|
+
|
|
752
|
+
services:
|
|
753
|
+
web:
|
|
754
|
+
build: .
|
|
755
|
+
ports:
|
|
756
|
+
- "8000:8000"
|
|
757
|
+
volumes:
|
|
758
|
+
- .:/app
|
|
759
|
+
environment:
|
|
760
|
+
- DATABASE_URL=postgresql://postgres:postgres@db:5432/mydb
|
|
761
|
+
depends_on:
|
|
762
|
+
- db
|
|
763
|
+
|
|
764
|
+
db:
|
|
765
|
+
image: postgres:15-alpine
|
|
766
|
+
ports:
|
|
767
|
+
- "5432:5432"
|
|
768
|
+
environment:
|
|
769
|
+
- POSTGRES_USER=postgres
|
|
770
|
+
- POSTGRES_PASSWORD=postgres
|
|
771
|
+
- POSTGRES_DB=mydb
|
|
772
|
+
volumes:
|
|
773
|
+
- postgres_data:/var/lib/postgresql/data
|
|
774
|
+
|
|
775
|
+
volumes:
|
|
776
|
+
postgres_data:
|
|
777
|
+
EOF
|
|
778
|
+
# Udocker runner helper for Termux
|
|
779
|
+
cat >scripts/run_udocker.sh <<'EOF'
|
|
780
|
+
#!/usr/bin/bash
|
|
781
|
+
if ! command -v udocker &>/dev/null; then
|
|
782
|
+
echo "udocker is not installed. Run: omni install dev --udocker"
|
|
783
|
+
exit 1
|
|
784
|
+
fi
|
|
785
|
+
echo "Building container with udocker..."
|
|
786
|
+
udocker create --name=fastapi_app python:3.11-slim
|
|
787
|
+
# Additional setup could be scripted here.
|
|
788
|
+
EOF
|
|
789
|
+
chmod +x scripts/run_udocker.sh
|
|
790
|
+
log_success "Created Docker, docker-compose and Udocker scripts"
|
|
791
|
+
fi
|
|
792
|
+
|
|
793
|
+
# Create run.sh
|
|
794
|
+
cat >scripts/run.sh <<'EOF'
|
|
795
|
+
#!/usr/bin/bash
|
|
796
|
+
uvicorn app.main:app --reload
|
|
797
|
+
EOF
|
|
798
|
+
chmod +x scripts/run.sh
|
|
799
|
+
|
|
800
|
+
# Create README.md
|
|
801
|
+
cat >README.md <<EOF
|
|
802
|
+
# $orm_choice FastAPI Project
|
|
803
|
+
|
|
804
|
+
Este projeto foi inicializado pelo **Omni** utilizando boas práticas de desenvolvimento.
|
|
805
|
+
|
|
806
|
+
## Estrutura do Projeto
|
|
807
|
+
- \`app/main.py\`: Ponto de entrada do FastAPI.
|
|
808
|
+
- \`app/core/\`: Configurações globais e banco de dados.
|
|
809
|
+
- \`app/api/\`: Endpoints divididos por versão.
|
|
810
|
+
- \`app/models/\`: Definição dos modelos ORM ($orm_choice).
|
|
811
|
+
- \`scripts/\`: Scripts utilitários de execução.
|
|
812
|
+
|
|
813
|
+
## Como Executar
|
|
814
|
+
1. Instale as dependências:
|
|
815
|
+
\`\`\`bash
|
|
816
|
+
pip install -r requirements.txt
|
|
817
|
+
\`\`\`
|
|
818
|
+
2. Execute a aplicação:
|
|
819
|
+
\`\`\`bash
|
|
820
|
+
./scripts/run.sh
|
|
821
|
+
\`\`\`
|
|
822
|
+
EOF
|
|
823
|
+
log_success "Created README.md"
|
|
824
|
+
|
|
825
|
+
log_success "Python (FastAPI) project configured!"
|
|
826
|
+
log_info "Run: pip install -r requirements.txt && ./scripts/run.sh"
|
|
827
|
+
echo
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
configure_go() {
|
|
831
|
+
separator
|
|
832
|
+
box "Configuring Go Project"
|
|
833
|
+
separator
|
|
834
|
+
echo
|
|
835
|
+
|
|
836
|
+
local framework_choice db_choice
|
|
837
|
+
read_select "Select Go web framework" framework_choice "Gin" "Fiber"
|
|
838
|
+
read_select "Select database provider" db_choice "PostgreSQL" "SQLite" "None"
|
|
839
|
+
|
|
840
|
+
log_info "Initializing Go modules if needed..."
|
|
841
|
+
if [[ ! -f "go.mod" ]]; then
|
|
842
|
+
local mod_name
|
|
843
|
+
mod_name=$(basename "$(pwd)")
|
|
844
|
+
go mod init "$mod_name" 2>/dev/null || go mod init project
|
|
845
|
+
log_success "Created go.mod"
|
|
846
|
+
fi
|
|
847
|
+
|
|
848
|
+
log_info "Creating folder structure..."
|
|
849
|
+
mkdir -p cmd/api internal/config internal/db internal/handlers internal/models scripts 2>/dev/null
|
|
850
|
+
|
|
851
|
+
# Create internal/config/config.go
|
|
852
|
+
cat >internal/config/config.go <<'EOF'
|
|
853
|
+
package config
|
|
854
|
+
|
|
855
|
+
import "os"
|
|
856
|
+
|
|
857
|
+
type Config struct {
|
|
858
|
+
Port string
|
|
859
|
+
DatabaseURL string
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
func LoadConfig() Config {
|
|
863
|
+
port := os.Getenv("PORT")
|
|
864
|
+
if port == "" {
|
|
865
|
+
port = "8080"
|
|
866
|
+
}
|
|
867
|
+
dbURL := os.Getenv("DATABASE_URL")
|
|
868
|
+
if dbURL == "" {
|
|
869
|
+
dbURL = "postgres://postgres:postgres@localhost:5432/mydb"
|
|
870
|
+
}
|
|
871
|
+
return Config{
|
|
872
|
+
Port: port,
|
|
873
|
+
DatabaseURL: dbURL,
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
EOF
|
|
877
|
+
log_success "Created internal/config/config.go"
|
|
878
|
+
|
|
879
|
+
# Create main.go based on framework
|
|
880
|
+
if [[ "$framework_choice" == "Gin" ]]; then
|
|
881
|
+
cat >cmd/api/main.go <<'EOF'
|
|
882
|
+
package main
|
|
883
|
+
|
|
884
|
+
import (
|
|
885
|
+
"fmt"
|
|
886
|
+
"net/http"
|
|
887
|
+
"project/internal/config"
|
|
888
|
+
"project/internal/handlers"
|
|
889
|
+
"github.com/gin-gonic/gin"
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
func main() {
|
|
893
|
+
cfg := config.LoadConfig()
|
|
894
|
+
r := gin.Default()
|
|
895
|
+
|
|
896
|
+
r.GET("/", func(c *gin.Context) {
|
|
897
|
+
c.JSON(http.StatusOK, gin.H{
|
|
898
|
+
"message": "Welcome to Omni Go (Gin)!",
|
|
899
|
+
"status": "healthy",
|
|
900
|
+
})
|
|
901
|
+
})
|
|
902
|
+
|
|
903
|
+
r.GET("/items", handlers.GetItems)
|
|
904
|
+
|
|
905
|
+
fmt.Printf("Server starting on port %s...\n", cfg.Port)
|
|
906
|
+
r.Run(":" + cfg.Port)
|
|
907
|
+
}
|
|
908
|
+
EOF
|
|
909
|
+
else
|
|
910
|
+
cat >cmd/api/main.go <<'EOF'
|
|
911
|
+
package main
|
|
912
|
+
|
|
913
|
+
import (
|
|
914
|
+
"fmt"
|
|
915
|
+
"project/internal/config"
|
|
916
|
+
"project/internal/handlers"
|
|
917
|
+
"github.com/gofiber/fiber/v2"
|
|
918
|
+
)
|
|
919
|
+
|
|
920
|
+
func main() {
|
|
921
|
+
cfg := config.LoadConfig()
|
|
922
|
+
app := fiber.New()
|
|
923
|
+
|
|
924
|
+
app.Get("/", func(c *fiber.Ctx) error {
|
|
925
|
+
return c.JSON(fiber.Map{
|
|
926
|
+
"message": "Welcome to Omni Go (Fiber)!",
|
|
927
|
+
"status": "healthy",
|
|
928
|
+
})
|
|
929
|
+
})
|
|
930
|
+
|
|
931
|
+
app.Get("/items", handlers.GetItems)
|
|
932
|
+
|
|
933
|
+
fmt.Printf("Server starting on port %s...\n", cfg.Port)
|
|
934
|
+
app.Listen(":" + cfg.Port)
|
|
935
|
+
}
|
|
936
|
+
EOF
|
|
937
|
+
fi
|
|
938
|
+
log_success "Created cmd/api/main.go"
|
|
939
|
+
|
|
940
|
+
# Create internal/handlers/handlers.go
|
|
941
|
+
cat >internal/handlers/handlers.go <<'EOF'
|
|
942
|
+
package handlers
|
|
943
|
+
|
|
944
|
+
import (
|
|
945
|
+
"net/http"
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
func GetItems(w interface{}) {
|
|
949
|
+
// Abstracted handler returning static list for structure demonstration
|
|
950
|
+
}
|
|
951
|
+
EOF
|
|
952
|
+
# Fix GetItems signature depending on framework
|
|
953
|
+
if [[ "$framework_choice" == "Gin" ]]; then
|
|
954
|
+
cat >internal/handlers/handlers.go <<'EOF'
|
|
955
|
+
package handlers
|
|
956
|
+
|
|
957
|
+
import (
|
|
958
|
+
"net/http"
|
|
959
|
+
"github.com/gin-gonic/gin"
|
|
960
|
+
)
|
|
961
|
+
|
|
962
|
+
func GetItems(c *gin.Context) {
|
|
963
|
+
c.JSON(http.StatusOK, gin.H{
|
|
964
|
+
"items": []map[string]interface{}{
|
|
965
|
+
{"id": 1, "title": "Item 1", "description": "Go Gin boilerplate item"},
|
|
966
|
+
},
|
|
967
|
+
})
|
|
968
|
+
}
|
|
969
|
+
EOF
|
|
970
|
+
else
|
|
971
|
+
cat >internal/handlers/handlers.go <<'EOF'
|
|
972
|
+
package handlers
|
|
973
|
+
|
|
974
|
+
import (
|
|
975
|
+
"github.com/gofiber/fiber/v2"
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
func GetItems(c *fiber.Ctx) error {
|
|
979
|
+
return c.JSON(fiber.Map{
|
|
980
|
+
"items": []fiber.Map{
|
|
981
|
+
{"id": 1, "title": "Item 1", "description": "Go Fiber boilerplate item"},
|
|
982
|
+
},
|
|
983
|
+
})
|
|
984
|
+
}
|
|
985
|
+
EOF
|
|
986
|
+
fi
|
|
987
|
+
log_success "Created internal/handlers/handlers.go"
|
|
988
|
+
|
|
989
|
+
# Create .env
|
|
990
|
+
if [[ ! -f ".env" ]]; then
|
|
991
|
+
cat >.env <<'EOF'
|
|
992
|
+
PORT=8080
|
|
993
|
+
DATABASE_URL=postgres://postgres:postgres@localhost:5432/mydb
|
|
994
|
+
EOF
|
|
995
|
+
log_success "Created .env"
|
|
996
|
+
fi
|
|
997
|
+
|
|
998
|
+
# Create scripts/run.sh
|
|
999
|
+
cat >scripts/run.sh <<'EOF'
|
|
1000
|
+
#!/usr/bin/bash
|
|
1001
|
+
go run cmd/api/main.go
|
|
1002
|
+
EOF
|
|
1003
|
+
chmod +x scripts/run.sh
|
|
1004
|
+
|
|
1005
|
+
# Install dependencies
|
|
1006
|
+
log_info "Installing dependencies..."
|
|
1007
|
+
if command -v go &>/dev/null; then
|
|
1008
|
+
if [[ "$framework_choice" == "Gin" ]]; then
|
|
1009
|
+
go get github.com/gin-gonic/gin 2>/dev/null || true
|
|
1010
|
+
else
|
|
1011
|
+
go get github.com/gofiber/fiber/v2 2>/dev/null || true
|
|
1012
|
+
fi
|
|
1013
|
+
go mod tidy 2>/dev/null || true
|
|
1014
|
+
fi
|
|
1015
|
+
|
|
1016
|
+
# Create Dockerfile
|
|
1017
|
+
cat >Dockerfile <<'EOF'
|
|
1018
|
+
FROM golang:1.20-alpine AS builder
|
|
1019
|
+
WORKDIR /app
|
|
1020
|
+
COPY go.mod go.sum ./
|
|
1021
|
+
RUN go mod download
|
|
1022
|
+
COPY . .
|
|
1023
|
+
RUN CGO_ENABLED=0 GOOS=linux go build -o /api-server cmd/api/main.go
|
|
1024
|
+
|
|
1025
|
+
FROM alpine:latest
|
|
1026
|
+
WORKDIR /
|
|
1027
|
+
COPY --from=builder /api-server /api-server
|
|
1028
|
+
EXPOSE 8080
|
|
1029
|
+
CMD ["/api-server"]
|
|
1030
|
+
EOF
|
|
1031
|
+
log_success "Created Dockerfile"
|
|
1032
|
+
|
|
1033
|
+
# Create README.md
|
|
1034
|
+
cat >README.md <<EOF
|
|
1035
|
+
# Go ($framework_choice) API
|
|
1036
|
+
|
|
1037
|
+
Projeto inicializado via **Omni** utilizando Arquitetura Limpa.
|
|
1038
|
+
|
|
1039
|
+
## Como Executar
|
|
1040
|
+
1. Instale o Go.
|
|
1041
|
+
2. Execute o servidor de desenvolvimento:
|
|
1042
|
+
\`\`\`bash
|
|
1043
|
+
./scripts/run.sh
|
|
1044
|
+
\`\`\`
|
|
1045
|
+
EOF
|
|
1046
|
+
log_success "Created README.md"
|
|
1047
|
+
|
|
1048
|
+
log_success "Go ($framework_choice) project configured!"
|
|
1049
|
+
log_info "Run: ./scripts/run.sh"
|
|
1050
|
+
echo
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
configure_rust() {
|
|
1054
|
+
separator
|
|
1055
|
+
box "Configuring Rust Project"
|
|
1056
|
+
separator
|
|
1057
|
+
echo
|
|
1058
|
+
|
|
1059
|
+
local framework_choice db_choice
|
|
1060
|
+
read_select "Select Rust web framework" framework_choice "Axum" "Actix Web"
|
|
1061
|
+
read_select "Select database driver" db_choice "SQLx (PostgreSQL)" "Diesel" "None"
|
|
1062
|
+
|
|
1063
|
+
log_info "Initializing Cargo project if needed..."
|
|
1064
|
+
if [[ ! -f "Cargo.toml" ]]; then
|
|
1065
|
+
cargo init --bin 2>/dev/null
|
|
1066
|
+
log_success "Initialized Cargo project"
|
|
1067
|
+
fi
|
|
1068
|
+
|
|
1069
|
+
# Append dependencies to Cargo.toml
|
|
1070
|
+
if [[ -f "Cargo.toml" ]]; then
|
|
1071
|
+
# Reset dependencies block
|
|
1072
|
+
sed -i '/\[dependencies\]/q' Cargo.toml
|
|
1073
|
+
cat >>Cargo.toml <<EOF
|
|
1074
|
+
tokio = { version = "1.0", features = ["full"] }
|
|
1075
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
1076
|
+
serde_json = "1.0"
|
|
1077
|
+
dotenvy = "0.15"
|
|
1078
|
+
EOF
|
|
1079
|
+
if [[ "$framework_choice" == "Axum" ]]; then
|
|
1080
|
+
cat >>Cargo.toml <<EOF
|
|
1081
|
+
axum = "0.7"
|
|
1082
|
+
EOF
|
|
1083
|
+
else
|
|
1084
|
+
cat >>Cargo.toml <<EOF
|
|
1085
|
+
actix-web = "4.0"
|
|
1086
|
+
EOF
|
|
1087
|
+
fi
|
|
1088
|
+
if [[ "$db_choice" == "SQLx (PostgreSQL)" ]]; then
|
|
1089
|
+
cat >>Cargo.toml <<EOF
|
|
1090
|
+
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "macros"] }
|
|
1091
|
+
EOF
|
|
1092
|
+
fi
|
|
1093
|
+
log_success "Configured Cargo.toml"
|
|
1094
|
+
fi
|
|
1095
|
+
|
|
1096
|
+
# Create src/main.rs
|
|
1097
|
+
mkdir -p src scripts 2>/dev/null
|
|
1098
|
+
if [[ "$framework_choice" == "Axum" ]]; then
|
|
1099
|
+
cat >src/main.rs <<'EOF'
|
|
1100
|
+
use axum::{routing::get, Json, Router};
|
|
1101
|
+
use serde::Serialize;
|
|
1102
|
+
use std::net::SocketAddr;
|
|
1103
|
+
|
|
1104
|
+
#[derive(Serialize)]
|
|
1105
|
+
struct Status {
|
|
1106
|
+
message: String,
|
|
1107
|
+
status: String,
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
#[tokio::main]
|
|
1111
|
+
async fn main() {
|
|
1112
|
+
dotenvy::dotenv().ok();
|
|
1113
|
+
|
|
1114
|
+
let app = Router::new().route("/", get(handler));
|
|
1115
|
+
|
|
1116
|
+
let port = std::env::var("PORT").unwrap_or_else(|_| "3000".to_string());
|
|
1117
|
+
let addr_str = format!("127.0.0.1:{}", port);
|
|
1118
|
+
let addr: SocketAddr = addr_str.parse().unwrap();
|
|
1119
|
+
println!("Listening on {}", addr);
|
|
1120
|
+
|
|
1121
|
+
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
|
1122
|
+
axum::serve(listener, app).await.unwrap();
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
async fn handler() -> Json<Status> {
|
|
1126
|
+
Json(Status {
|
|
1127
|
+
message: "Welcome to Omni Rust (Axum)!".to_string(),
|
|
1128
|
+
status: "healthy".to_string(),
|
|
1129
|
+
})
|
|
1130
|
+
}
|
|
1131
|
+
EOF
|
|
1132
|
+
else
|
|
1133
|
+
cat >src/main.rs <<'EOF'
|
|
1134
|
+
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
|
|
1135
|
+
use serde::Serialize;
|
|
1136
|
+
|
|
1137
|
+
#[derive(Serialize)]
|
|
1138
|
+
struct Status {
|
|
1139
|
+
message: String,
|
|
1140
|
+
status: String,
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
#[get("/")]
|
|
1144
|
+
async fn index() -> impl Responder {
|
|
1145
|
+
HttpResponse::Ok().json(Status {
|
|
1146
|
+
message: "Welcome to Omni Rust (Actix Web)!".to_string(),
|
|
1147
|
+
status: "healthy".to_string(),
|
|
1148
|
+
})
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
#[actix_web::main]
|
|
1152
|
+
async fn main() -> std::io::Result<()> {
|
|
1153
|
+
dotenvy::dotenv().ok();
|
|
1154
|
+
let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string());
|
|
1155
|
+
println!("Server running on 127.0.0.1:{}", port);
|
|
1156
|
+
|
|
1157
|
+
HttpServer::new(|| {
|
|
1158
|
+
App::new().service(index)
|
|
1159
|
+
})
|
|
1160
|
+
.bind(format!("127.0.0.1:{}", port))?
|
|
1161
|
+
.run()
|
|
1162
|
+
.await
|
|
1163
|
+
}
|
|
1164
|
+
EOF
|
|
1165
|
+
fi
|
|
1166
|
+
log_success "Created src/main.rs"
|
|
1167
|
+
|
|
1168
|
+
# Create .env
|
|
1169
|
+
if [[ ! -f ".env" ]]; then
|
|
1170
|
+
cat >.env <<'EOF'
|
|
1171
|
+
PORT=3000
|
|
1172
|
+
DATABASE_URL=postgres://postgres:postgres@localhost:5432/mydb
|
|
1173
|
+
EOF
|
|
1174
|
+
log_success "Created .env"
|
|
1175
|
+
fi
|
|
1176
|
+
|
|
1177
|
+
# Create scripts/run.sh
|
|
1178
|
+
cat >scripts/run.sh <<'EOF'
|
|
1179
|
+
#!/usr/bin/bash
|
|
1180
|
+
cargo run
|
|
1181
|
+
EOF
|
|
1182
|
+
chmod +x scripts/run.sh
|
|
1183
|
+
|
|
1184
|
+
# Create Dockerfile
|
|
1185
|
+
cat >Dockerfile <<'EOF'
|
|
1186
|
+
FROM rust:1.70 AS builder
|
|
1187
|
+
WORKDIR /app
|
|
1188
|
+
COPY . .
|
|
1189
|
+
RUN cargo build --release
|
|
1190
|
+
|
|
1191
|
+
FROM debian:bullseye-slim
|
|
1192
|
+
WORKDIR /app
|
|
1193
|
+
COPY --from=builder /app/target/release/project .
|
|
1194
|
+
EXPOSE 3000
|
|
1195
|
+
CMD ["./project"]
|
|
1196
|
+
EOF
|
|
1197
|
+
log_success "Created Dockerfile"
|
|
1198
|
+
|
|
1199
|
+
# Create README.md
|
|
1200
|
+
cat >README.md <<EOF
|
|
1201
|
+
# Rust ($framework_choice) API
|
|
1202
|
+
|
|
1203
|
+
Projeto inicializado via **Omni** utilizando Rust.
|
|
1204
|
+
|
|
1205
|
+
## Como Executar
|
|
1206
|
+
1. Execute o servidor de desenvolvimento:
|
|
1207
|
+
\`\`\`bash
|
|
1208
|
+
./scripts/run.sh
|
|
1209
|
+
\`\`\`
|
|
1210
|
+
EOF
|
|
1211
|
+
log_success "Created README.md"
|
|
1212
|
+
|
|
1213
|
+
log_success "Rust ($framework_choice) project configured!"
|
|
1214
|
+
log_info "Run: ./scripts/run.sh"
|
|
1215
|
+
echo
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
# ===== MAIN =====
|
|
1219
|
+
init_main() {
|
|
1220
|
+
local template="$1"
|
|
1221
|
+
|
|
1222
|
+
case "$template" in
|
|
1223
|
+
next | nextjs) configure_next ;;
|
|
1224
|
+
react | vite) configure_react ;;
|
|
1225
|
+
nest | nestjs) configure_nest ;;
|
|
1226
|
+
express | exp) configure_express ;;
|
|
1227
|
+
python | fastapi) configure_python ;;
|
|
1228
|
+
go | gin) configure_go ;;
|
|
1229
|
+
rust | axum) configure_rust ;;
|
|
1230
|
+
"")
|
|
1231
|
+
local detected=$(detect_project_type)
|
|
1232
|
+
if [[ "$detected" != "unknown" ]]; then
|
|
1233
|
+
log_info "Detected project type: $detected"
|
|
1234
|
+
echo
|
|
1235
|
+
case "$detected" in
|
|
1236
|
+
next) configure_next ;;
|
|
1237
|
+
react) configure_react ;;
|
|
1238
|
+
nest) configure_nest ;;
|
|
1239
|
+
express) configure_express ;;
|
|
1240
|
+
python) configure_python ;;
|
|
1241
|
+
go) configure_go ;;
|
|
1242
|
+
rust) configure_rust ;;
|
|
1243
|
+
esac
|
|
1244
|
+
else
|
|
1245
|
+
init_help
|
|
1246
|
+
fi
|
|
1247
|
+
;;
|
|
1248
|
+
*)
|
|
1249
|
+
log_error "Unknown template: $template"
|
|
1250
|
+
init_help
|
|
1251
|
+
exit 1
|
|
1252
|
+
;;
|
|
1253
|
+
esac
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
detect_project_type() {
|
|
1257
|
+
[[ -f "requirements.txt" ]] && { echo "python"; return; }
|
|
1258
|
+
[[ -f "go.mod" ]] && { echo "go"; return; }
|
|
1259
|
+
[[ -f "Cargo.toml" ]] && { echo "rust"; return; }
|
|
1260
|
+
[[ ! -f "package.json" ]] && { echo "unknown"; return; }
|
|
1261
|
+
grep -q "next" package.json 2>/dev/null && { echo "next"; return; }
|
|
1262
|
+
grep -q "vite" package.json 2>/dev/null && { echo "react"; return; }
|
|
1263
|
+
grep -q "@nestjs" package.json 2>/dev/null && { echo "nest"; return; }
|
|
1264
|
+
grep -q "express" package.json 2>/dev/null && { echo "express"; return; }
|
|
1265
|
+
echo "unknown"
|
|
1266
|
+
}
|