init commit

This commit is contained in:
2026-09-19 05:42:17 -09:00
commit b57e1a406d
19 changed files with 754 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
(ns vibe.core
(:require [ring.adapter.jetty :as jetty]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[ring.middleware.head :refer [wrap-head]]
[reitit.ring :as ring]
[reitit.swagger :as swagger]
[reitit.swagger-ui :as swagger-ui]
[reitit.ring.middleware.muuntaja :as muuntaja-middleware]
[muuntaja.core :as m]
[vibe.health.routes :as health]
[vibe.math.routes :as math]))
;; Each logical group (health, users, orders, ...) owns a `vibe.<group>.routes`
;; namespace that returns its own route subtree; they're concatenated here.
(def router
(ring/router
[["/swagger.json"
{:get {:no-doc true
:swagger {:info {:title "vibe API" :version "1.0.0"}}
:handler (swagger/create-swagger-handler)}}]
["/" {:get {:no-doc true
:handler (fn [_req]
{:status 200
:headers {"Content-Type" "text/plain; charset=utf-8"}
:body "vibe API — see /api-docs for documentation, /swagger.json for the spec"})}}]
(health/routes)
(math/routes)]
{:data {:muuntaja m/instance
:middleware [muuntaja-middleware/format-middleware]}}))
(def app
(-> (ring/ring-handler
router
(ring/routes
(swagger-ui/create-swagger-ui-handler {:path "/api-docs"})
(ring/create-default-handler)))
wrap-head))
(defn add-shutdown-hook [server]
(.addShutdownHook
(Runtime/getRuntime)
(Thread. (fn [] (.stop server 1000)))))
(defn start-server [& [_ opts]]
(let [port (Integer/parseInt (str (or (System/getenv "PORT")
(get opts :port 3000))))]
(println (format "[vibe] starting server on port %d..." port))
(try
(let [server (jetty/run-jetty (wrap-defaults app api-defaults)
{:port port
:join? false})]
(println (format "vibe server running on http://localhost:%d" port))
(add-shutdown-hook server))
(catch Throwable t
(println "[vibe] FAILED to start server:" (.getMessage t))
(.printStackTrace t)
(throw t)))))
(defn -main [& [_ port]]
(start-server))
+10
View File
@@ -0,0 +1,10 @@
(ns vibe.health.routes)
(defn routes []
["/api/ping"
{:get {:tags ["health"]
:summary "Ping the server"
:handler (fn [_req]
{:status 200
:headers {"Content-Type" "text/plain; charset=utf-8"}
:body "pong"})}}])
+5
View File
@@ -0,0 +1,5 @@
(ns vibe.math.core
"Business logic for the math group. No HTTP concerns in here.")
(defn add [x y]
(+ x y))
+24
View File
@@ -0,0 +1,24 @@
(ns vibe.math.routes
(:require [vibe.math.core :as math]))
(defn- parse-num [s]
(when s
(or (parse-long s) (parse-double s))))
(defn- edn-response [status body]
{:status status
:headers {"Content-Type" "application/edn; charset=utf-8"}
:body (pr-str body)})
(defn- add-handler [{:keys [query-params]}]
(let [x (parse-num (get query-params "x"))
y (parse-num (get query-params "y"))]
(if (and x y)
(edn-response 200 {:result (math/add x y)})
(edn-response 400 {:error "x and y query params are required and must be numbers"}))))
(defn routes []
["/api/add"
{:get {:tags ["math"]
:summary "Add two numbers (?x=2&y=3 => {:result 5})"
:handler add-handler}}])