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.
Files changed (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1137 -0
  3. package/core/bin/core +85 -0
  4. package/core/bin/omni +21 -0
  5. package/core/cli/commands/--version.sh +8 -0
  6. package/core/cli/commands/brain.sh +1549 -0
  7. package/core/cli/commands/doctor.sh +834 -0
  8. package/core/cli/commands/env.sh +226 -0
  9. package/core/cli/commands/init.sh +1266 -0
  10. package/core/cli/commands/install.sh +759 -0
  11. package/core/cli/commands/list.sh +397 -0
  12. package/core/cli/commands/open.sh +71 -0
  13. package/core/cli/commands/pg.sh +761 -0
  14. package/core/cli/commands/reinstall.sh +694 -0
  15. package/core/cli/commands/show.sh +90 -0
  16. package/core/cli/commands/uninstall.sh +700 -0
  17. package/core/cli/commands/update.sh +754 -0
  18. package/core/cli/commands/voice.sh +170 -0
  19. package/core/cli/core.sh +82 -0
  20. package/core/cli/omni.sh +634 -0
  21. package/core/modules/ai.sh +152 -0
  22. package/core/modules/auto.sh +90 -0
  23. package/core/modules/db.sh +94 -0
  24. package/core/modules/deploy.sh +50 -0
  25. package/core/modules/dev.sh +126 -0
  26. package/core/modules/editor.sh +101 -0
  27. package/core/modules/lang.sh +100 -0
  28. package/core/modules/npm.sh +122 -0
  29. package/core/modules/shell.sh +312 -0
  30. package/core/modules/ui.sh +115 -0
  31. package/core/tools/ai/all.sh +63 -0
  32. package/core/tools/ai/antigravity-cli/README.md +45 -0
  33. package/core/tools/ai/antigravity-cli/bin/agy +28 -0
  34. package/core/tools/ai/antigravity-cli/helper/agy_helper.c +39 -0
  35. package/core/tools/ai/antigravity-cli/install.sh +469 -0
  36. package/core/tools/ai/claude-code/README.md +45 -0
  37. package/core/tools/ai/claude-code/bin/claude +29 -0
  38. package/core/tools/ai/claude-code/helper/claude_helper.c +42 -0
  39. package/core/tools/ai/claude-code/install.sh +278 -0
  40. package/core/tools/ai/codegraph/README.md +43 -0
  41. package/core/tools/ai/codegraph/bin/codegraph +3 -0
  42. package/core/tools/ai/codegraph/install.sh +149 -0
  43. package/core/tools/ai/codex/README.md +44 -0
  44. package/core/tools/ai/codex/install.sh +104 -0
  45. package/core/tools/ai/command-code/README.md +62 -0
  46. package/core/tools/ai/command-code/install.sh +136 -0
  47. package/core/tools/ai/engram/README.md +44 -0
  48. package/core/tools/ai/engram/install.sh +127 -0
  49. package/core/tools/ai/freebuff/README.md +52 -0
  50. package/core/tools/ai/freebuff/bin/freebuff +28 -0
  51. package/core/tools/ai/freebuff/helper/freebuff_helper.c +47 -0
  52. package/core/tools/ai/freebuff/install.sh +301 -0
  53. package/core/tools/ai/gemini-cli/README.md +46 -0
  54. package/core/tools/ai/gemini-cli/install.sh +111 -0
  55. package/core/tools/ai/gentle-ai/README.md +42 -0
  56. package/core/tools/ai/gentle-ai/install.sh +253 -0
  57. package/core/tools/ai/gentle-ai/termux-patches.go +256 -0
  58. package/core/tools/ai/gga/README.md +49 -0
  59. package/core/tools/ai/gga/install.sh +134 -0
  60. package/core/tools/ai/hermes-agent/README.md +50 -0
  61. package/core/tools/ai/hermes-agent/install.sh +80 -0
  62. package/core/tools/ai/heygen/README.md +24 -0
  63. package/core/tools/ai/heygen/install.sh +126 -0
  64. package/core/tools/ai/kilocode-cli/README.md +45 -0
  65. package/core/tools/ai/kilocode-cli/bin/kilocode +21 -0
  66. package/core/tools/ai/kilocode-cli/helper/kilocode_helper.c +47 -0
  67. package/core/tools/ai/kilocode-cli/install.sh +179 -0
  68. package/core/tools/ai/kimchi-code/README.md +8 -0
  69. package/core/tools/ai/kimchi-code/install.sh +120 -0
  70. package/core/tools/ai/kimi-code/README.md +45 -0
  71. package/core/tools/ai/kimi-code/install.sh +111 -0
  72. package/core/tools/ai/kiro-cli/README.md +23 -0
  73. package/core/tools/ai/kiro-cli/install.sh +127 -0
  74. package/core/tools/ai/mimocode/README.md +43 -0
  75. package/core/tools/ai/mimocode/bin/mimo +28 -0
  76. package/core/tools/ai/mimocode/helper/mimocode_helper.c +47 -0
  77. package/core/tools/ai/mimocode/install.sh +287 -0
  78. package/core/tools/ai/minimax-cli/README.md +45 -0
  79. package/core/tools/ai/minimax-cli/install.sh +111 -0
  80. package/core/tools/ai/mistral-vibe/README.md +46 -0
  81. package/core/tools/ai/mistral-vibe/install.sh +119 -0
  82. package/core/tools/ai/odysseus/README.md +35 -0
  83. package/core/tools/ai/odysseus/install.sh +163 -0
  84. package/core/tools/ai/ollama/README.md +44 -0
  85. package/core/tools/ai/ollama/install.sh +78 -0
  86. package/core/tools/ai/openclaude/README.md +46 -0
  87. package/core/tools/ai/openclaude/install.sh +110 -0
  88. package/core/tools/ai/openclaw/README.md +47 -0
  89. package/core/tools/ai/openclaw/install.sh +112 -0
  90. package/core/tools/ai/opencode/README.md +51 -0
  91. package/core/tools/ai/opencode/bin/opencode +28 -0
  92. package/core/tools/ai/opencode/helper/opencode_helper.c +57 -0
  93. package/core/tools/ai/opencode/install.sh +290 -0
  94. package/core/tools/ai/pi/README.md +46 -0
  95. package/core/tools/ai/pi/install.sh +104 -0
  96. package/core/tools/ai/qwen-code/README.md +45 -0
  97. package/core/tools/ai/qwen-code/install.sh +111 -0
  98. package/core/tools/ai/seedance/README.md +22 -0
  99. package/core/tools/ai/seedance/install.sh +134 -0
  100. package/core/tools/ai/veo3/README.md +36 -0
  101. package/core/tools/ai/veo3/install.sh +151 -0
  102. package/core/tools/auto/all.sh +57 -0
  103. package/core/tools/auto/n8n/README.md +47 -0
  104. package/core/tools/auto/n8n/install.sh +102 -0
  105. package/core/tools/db/all.sh +60 -0
  106. package/core/tools/db/mariadb/README.md +43 -0
  107. package/core/tools/db/mariadb/install.sh +65 -0
  108. package/core/tools/db/mongodb/README.md +42 -0
  109. package/core/tools/db/mongodb/install.sh +73 -0
  110. package/core/tools/db/postgresql/README.md +45 -0
  111. package/core/tools/db/postgresql/install.sh +65 -0
  112. package/core/tools/db/sqlite/README.md +44 -0
  113. package/core/tools/db/sqlite/install.sh +65 -0
  114. package/core/tools/deploy/all.sh +39 -0
  115. package/core/tools/deploy/netlify/install.sh +41 -0
  116. package/core/tools/deploy/railway/install.sh +47 -0
  117. package/core/tools/deploy/vercel/install.sh +43 -0
  118. package/core/tools/dev/all.sh +75 -0
  119. package/core/tools/dev/bat/README.md +44 -0
  120. package/core/tools/dev/bat/install.sh +82 -0
  121. package/core/tools/dev/bc/README.md +44 -0
  122. package/core/tools/dev/bc/install.sh +82 -0
  123. package/core/tools/dev/cloudflared/README.md +43 -0
  124. package/core/tools/dev/cloudflared/install.sh +82 -0
  125. package/core/tools/dev/curl/README.md +43 -0
  126. package/core/tools/dev/curl/install.sh +82 -0
  127. package/core/tools/dev/fzf/README.md +44 -0
  128. package/core/tools/dev/fzf/install.sh +82 -0
  129. package/core/tools/dev/gh/README.md +43 -0
  130. package/core/tools/dev/gh/install.sh +82 -0
  131. package/core/tools/dev/html2text/README.md +44 -0
  132. package/core/tools/dev/html2text/install.sh +82 -0
  133. package/core/tools/dev/imagemagick/README.md +44 -0
  134. package/core/tools/dev/imagemagick/install.sh +82 -0
  135. package/core/tools/dev/jq/README.md +44 -0
  136. package/core/tools/dev/jq/install.sh +82 -0
  137. package/core/tools/dev/lsd/README.md +44 -0
  138. package/core/tools/dev/lsd/install.sh +82 -0
  139. package/core/tools/dev/make/README.md +44 -0
  140. package/core/tools/dev/make/install.sh +82 -0
  141. package/core/tools/dev/ncurses/README.md +42 -0
  142. package/core/tools/dev/ncurses/install.sh +82 -0
  143. package/core/tools/dev/proot/README.md +43 -0
  144. package/core/tools/dev/proot/install.sh +82 -0
  145. package/core/tools/dev/shfmt/README.md +44 -0
  146. package/core/tools/dev/shfmt/install.sh +82 -0
  147. package/core/tools/dev/tmate/README.md +44 -0
  148. package/core/tools/dev/tmate/install.sh +82 -0
  149. package/core/tools/dev/translate/README.md +44 -0
  150. package/core/tools/dev/translate/install.sh +82 -0
  151. package/core/tools/dev/tree/README.md +44 -0
  152. package/core/tools/dev/tree/install.sh +82 -0
  153. package/core/tools/dev/udocker/README.md +44 -0
  154. package/core/tools/dev/udocker/install.sh +82 -0
  155. package/core/tools/dev/wget/README.md +44 -0
  156. package/core/tools/dev/wget/install.sh +82 -0
  157. package/core/tools/editor/all.sh +58 -0
  158. package/core/tools/editor/neovim/README.md +43 -0
  159. package/core/tools/editor/neovim/install.sh +66 -0
  160. package/core/tools/editor/nvchad/README.md +45 -0
  161. package/core/tools/editor/nvchad/install.sh +110 -0
  162. package/core/tools/lang/all.sh +63 -0
  163. package/core/tools/lang/clang/README.md +43 -0
  164. package/core/tools/lang/clang/install.sh +79 -0
  165. package/core/tools/lang/golang/README.md +43 -0
  166. package/core/tools/lang/golang/install.sh +79 -0
  167. package/core/tools/lang/nodejs/README.md +43 -0
  168. package/core/tools/lang/nodejs/install.sh +79 -0
  169. package/core/tools/lang/perl/README.md +43 -0
  170. package/core/tools/lang/perl/install.sh +79 -0
  171. package/core/tools/lang/php/README.md +43 -0
  172. package/core/tools/lang/php/install.sh +79 -0
  173. package/core/tools/lang/python/README.md +43 -0
  174. package/core/tools/lang/python/install.sh +79 -0
  175. package/core/tools/lang/rust/README.md +43 -0
  176. package/core/tools/lang/rust/install.sh +79 -0
  177. package/core/tools/npm/all.sh +67 -0
  178. package/core/tools/npm/live-server/README.md +43 -0
  179. package/core/tools/npm/live-server/install.sh +95 -0
  180. package/core/tools/npm/localtunnel/README.md +43 -0
  181. package/core/tools/npm/localtunnel/install.sh +111 -0
  182. package/core/tools/npm/markserv/README.md +43 -0
  183. package/core/tools/npm/markserv/install.sh +94 -0
  184. package/core/tools/npm/ncu/README.md +43 -0
  185. package/core/tools/npm/ncu/install.sh +94 -0
  186. package/core/tools/npm/nestjs/README.md +43 -0
  187. package/core/tools/npm/nestjs/install.sh +94 -0
  188. package/core/tools/npm/ngrok/README.md +44 -0
  189. package/core/tools/npm/ngrok/install.sh +94 -0
  190. package/core/tools/npm/prettier/README.md +43 -0
  191. package/core/tools/npm/prettier/install.sh +94 -0
  192. package/core/tools/npm/psqlformat/README.md +43 -0
  193. package/core/tools/npm/psqlformat/install.sh +94 -0
  194. package/core/tools/npm/turbopack/README.md +8 -0
  195. package/core/tools/npm/turbopack/install.sh +41 -0
  196. package/core/tools/npm/typescript/README.md +43 -0
  197. package/core/tools/npm/typescript/install.sh +94 -0
  198. package/core/tools/npm/vercel/README.md +43 -0
  199. package/core/tools/npm/vercel/install.sh +94 -0
  200. package/core/tools/shell/all.sh +67 -0
  201. package/core/tools/shell/better-npm/README.md +43 -0
  202. package/core/tools/shell/better-npm/install.sh +85 -0
  203. package/core/tools/shell/fzf-tab/README.md +44 -0
  204. package/core/tools/shell/fzf-tab/install.sh +85 -0
  205. package/core/tools/shell/history-substring/README.md +43 -0
  206. package/core/tools/shell/history-substring/install.sh +85 -0
  207. package/core/tools/shell/powerlevel10k/README.md +43 -0
  208. package/core/tools/shell/powerlevel10k/install.sh +85 -0
  209. package/core/tools/shell/you-should-use/README.md +43 -0
  210. package/core/tools/shell/you-should-use/install.sh +85 -0
  211. package/core/tools/shell/zsh-autopair/README.md +44 -0
  212. package/core/tools/shell/zsh-autopair/install.sh +85 -0
  213. package/core/tools/shell/zsh-autosuggestions/README.md +43 -0
  214. package/core/tools/shell/zsh-autosuggestions/install.sh +85 -0
  215. package/core/tools/shell/zsh-completions/README.md +43 -0
  216. package/core/tools/shell/zsh-completions/install.sh +85 -0
  217. package/core/tools/shell/zsh-defer/README.md +43 -0
  218. package/core/tools/shell/zsh-defer/install.sh +85 -0
  219. package/core/tools/shell/zsh-syntax-highlighting/README.md +43 -0
  220. package/core/tools/shell/zsh-syntax-highlighting/install.sh +72 -0
  221. package/core/tools/ui/all.sh +61 -0
  222. package/core/tools/ui/banner/README.md +42 -0
  223. package/core/tools/ui/banner/install.sh +151 -0
  224. package/core/tools/ui/cursor/README.md +42 -0
  225. package/core/tools/ui/cursor/install.sh +58 -0
  226. package/core/tools/ui/extra-keys/README.md +43 -0
  227. package/core/tools/ui/extra-keys/install.sh +62 -0
  228. package/core/tools/ui/font/README.md +43 -0
  229. package/core/tools/ui/font/install.sh +63 -0
  230. package/core/utils/banner.sh +519 -0
  231. package/core/utils/bootstrap.sh +25 -0
  232. package/core/utils/colors.sh +31 -0
  233. package/core/utils/dialogrc +30 -0
  234. package/core/utils/env.sh +53 -0
  235. package/core/utils/log.sh +598 -0
  236. package/install.sh +272 -0
  237. 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
+ }