karnel-termux 0.0.1

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