mirror of
https://github.com/edufeed-org/amb-api.git
synced 2025-12-07 23:34:33 +00:00
Add build options and docker, make relay info available through env
This commit is contained in:
parent
e5ff9265b4
commit
a34d07d365
10 changed files with 158 additions and 67 deletions
1
.env
Normal file
1
.env
Normal file
|
|
@ -0,0 +1 @@
|
|||
RELAY="huhuhaha"
|
||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Use a minimal OpenJDK runtime image
|
||||
FROM openjdk:17-jdk-slim
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the Uberjar into the image
|
||||
COPY target/app.jar .
|
||||
COPY resources ./resources
|
||||
|
||||
# Expose the application's port
|
||||
EXPOSE 8890
|
||||
|
||||
# Run the Uberjar
|
||||
CMD ["java", "-jar", "app.jar"]
|
||||
|
||||
|
||||
14
README.md
Normal file
14
README.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Edufeed To AMB Transformer
|
||||
|
||||
Run with: `clj -M -m app.core`
|
||||
|
||||
Runs on port `8890`.
|
||||
|
||||
Sets up an endpoint `/resources` which accepts `pk` for an actory public key as a query parameter.
|
||||
|
||||
Results are validated against the metadata profile [Allgemeines Metadatenprofil für Bildungsressourcen](https://w3id.org/kim/amb/latest/) before being returned.
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] Add aero for configuration
|
||||
|
||||
39
build.clj
Normal file
39
build.clj
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
(ns build
|
||||
(:require [clojure.tools.build.api :as b]))
|
||||
|
||||
(def lib 'app)
|
||||
(def version (format "1.2.%s" (b/git-count-revs nil)))
|
||||
(def class-dir "target/classes")
|
||||
(def jar-file (format "target/%s-%s.jar" (name lib) version))
|
||||
(def uber-file "target/app.jar")
|
||||
|
||||
;; delay to defer side effects (artifact downloads)
|
||||
(def basis (delay (b/create-basis {:project "deps.edn"})))
|
||||
|
||||
(defn clean [_]
|
||||
(b/delete {:path "target"}))
|
||||
|
||||
(defn jar [_]
|
||||
(b/write-pom {:class-dir class-dir
|
||||
:lib lib
|
||||
:version version
|
||||
:basis @basis
|
||||
:src-dirs ["src"]})
|
||||
(b/copy-dir {:src-dirs ["src" "resources"]
|
||||
:target-dir class-dir})
|
||||
(b/jar {:class-dir class-dir
|
||||
:jar-file jar-file}))
|
||||
|
||||
|
||||
(defn uber [_]
|
||||
(clean nil)
|
||||
(b/copy-dir {:src-dirs ["src" "resources"]
|
||||
:target-dir class-dir})
|
||||
(b/compile-clj {:basis @basis
|
||||
:ns-compile '[app.core]
|
||||
:class-dir class-dir})
|
||||
(b/uber {:class-dir class-dir
|
||||
:uber-file uber-file
|
||||
:basis @basis
|
||||
:main 'app.core}))
|
||||
|
||||
6
deps.edn
6
deps.edn
|
|
@ -5,10 +5,14 @@
|
|||
io.pedestal/pedestal.jetty {:mvn/version "0.7.1"}
|
||||
org.slf4j/slf4j-simple {:mvn/version "2.0.10"}
|
||||
luposlip/json-schema {:mvn/version "0.4.6"}
|
||||
aero/aero {:mvn/version "1.1.6"}
|
||||
net.clojars.laoc/nostr {:local/root "/home/laoc/coding/nostr-clj"}}
|
||||
|
||||
:aliases
|
||||
{:nrepl
|
||||
{:run {:main-opts ["-m" "app.core"]}
|
||||
:build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.9.3"}}
|
||||
:ns-default build}
|
||||
:nrepl
|
||||
{:extra-deps
|
||||
{nrepl/nrepl {:mvn/version "1.3.0"}}
|
||||
:main-opts ["-m" "nrepl.cmdline"
|
||||
|
|
|
|||
14
docker-compose.yml
Normal file
14
docker-compose.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8890:8890"
|
||||
# env_file:
|
||||
# - .env # Pass variables from the .env file to the container
|
||||
# or via environment variables
|
||||
environment:
|
||||
RELAY: "ws:localhost:7778"
|
||||
restart: always
|
||||
|
||||
1
resources/config.edn
Normal file
1
resources/config.edn
Normal file
|
|
@ -0,0 +1 @@
|
|||
{:web {:relay #or [#env RELAY "ws://localhost:7778"]}}
|
||||
|
|
@ -8,32 +8,32 @@
|
|||
[json-schema.core :as json-schema]
|
||||
[clojure.core.async :refer [go chan >! <!]]))
|
||||
|
||||
(defn validate [resources]
|
||||
(let [schema (json-schema/prepare-schema
|
||||
(-> "resources/schema.json"
|
||||
slurp
|
||||
(cheshire.core/parse-string true)))]
|
||||
(try
|
||||
(let [validation-results
|
||||
(map (fn [resource]
|
||||
(try
|
||||
(when (json-schema/validate schema resource)
|
||||
{:valid true :resource resource})
|
||||
(catch Exception e
|
||||
{:valid false :error e :resource resource})))
|
||||
resources)]
|
||||
(do
|
||||
;; Log invalid resources
|
||||
(doseq [{:keys [error resource]} (filter #(not (:valid %)) validation-results)]
|
||||
(println "Invalid resource:" resource "Error:" error))
|
||||
;; Return only valid resources
|
||||
(->> validation-results
|
||||
(filter :valid)
|
||||
(map :resource))))
|
||||
(catch Exception e
|
||||
(println "Unexpected error during validation" e)
|
||||
[]))))
|
||||
(def schema (json-schema/prepare-schema
|
||||
(-> "resources/schema.json"
|
||||
slurp
|
||||
(cheshire.core/parse-string true))))
|
||||
|
||||
(defn validate [resources]
|
||||
(try
|
||||
(let [validation-results
|
||||
(map (fn [resource]
|
||||
(try
|
||||
(when (json-schema/validate schema resource)
|
||||
{:valid true :resource resource})
|
||||
(catch Exception e
|
||||
{:valid false :error e :resource resource})))
|
||||
resources)]
|
||||
(do
|
||||
;; Log invalid resources
|
||||
(doseq [{:keys [error resource]} (filter #(not (:valid %)) validation-results)]
|
||||
#_(println "Invalid resource:" resource "Error:" error))
|
||||
;; Return only valid resources
|
||||
(->> validation-results
|
||||
(filter :valid)
|
||||
(map :resource))))
|
||||
(catch Exception e
|
||||
#_(println "Unexpected error during validation" e)
|
||||
nil)))
|
||||
|
||||
(defn ok [body]
|
||||
{:status 200 :body body})
|
||||
|
|
@ -44,10 +44,11 @@
|
|||
(go
|
||||
(let [npub (get-in request [:query-params :npub])
|
||||
pk (get-in request [:query-params :pk])
|
||||
relay (get-in request [:relay])
|
||||
filter (if pk
|
||||
{:kinds [30142] :authors [pk]}
|
||||
{:kinds [30142]})
|
||||
resources (nostr/fetch-events "ws://localhost:7778" filter)
|
||||
resources (nostr/fetch-events relay filter)
|
||||
transformed (map #(edufeed/convert-30142-to-nostr-amb % true true) resources)
|
||||
validate (validate transformed)
|
||||
resp (if validate
|
||||
|
|
@ -60,34 +61,37 @@
|
|||
{:name ::resources-by-user
|
||||
:enter (fn [context]
|
||||
(go
|
||||
(let [result (<! (get-resources (:request context)))
|
||||
;; TODO check against amb schema
|
||||
]
|
||||
(let [result (<! (get-resources (:request context)))]
|
||||
(assoc context :response (ok result)))))})
|
||||
|
||||
(def routes
|
||||
;; Interceptor to add the WebSocket port to the request context
|
||||
(defn add-relay [relay]
|
||||
{:name ::add-ws-port
|
||||
:enter (fn [context]
|
||||
(assoc-in context [:request :relay] relay))})
|
||||
|
||||
(defn routes
|
||||
[relay]
|
||||
(route/expand-routes
|
||||
#{["/resources" :get resources-by-user :route-name :resources]}))
|
||||
#{["/resources" :get [(add-relay relay) resources-by-user] :route-name :resources]}))
|
||||
|
||||
(def service-map
|
||||
{::http/routes routes
|
||||
::http/type :jetty
|
||||
::http/port 8890})
|
||||
|
||||
(defn create-service []
|
||||
(http/create-server service-map))
|
||||
(defn create-service [relay]
|
||||
(http/create-server
|
||||
(assoc service-map
|
||||
::http/routes (routes relay)
|
||||
::http/port 8890)))
|
||||
|
||||
(defn start []
|
||||
(http/start (create-service)))
|
||||
|
||||
(comment
|
||||
(http/stop (create-service)))
|
||||
|
||||
(defrecord WebServer []
|
||||
(defrecord WebServer [relay]
|
||||
component/Lifecycle
|
||||
(start [this]
|
||||
(println ";; Starting Web server...")
|
||||
(let [server (create-service)]
|
||||
(println ";; Starting Webserver")
|
||||
(println ";; Using Relay: " relay)
|
||||
(let [server (create-service relay)]
|
||||
(assoc this :server (http/start server))))
|
||||
(stop [this]
|
||||
(println ";; Stopping Web server...")
|
||||
|
|
@ -98,22 +102,3 @@
|
|||
(defn new-web-server []
|
||||
(map->WebServer {}))
|
||||
|
||||
;; For interactive development
|
||||
(defonce server (atom nil))
|
||||
|
||||
(defn start-dev []
|
||||
(reset! server
|
||||
(http/start (http/create-server
|
||||
(assoc service-map
|
||||
::http/join? false)))))
|
||||
|
||||
(defn stop-dev []
|
||||
(http/stop @server))
|
||||
|
||||
(defn restart []
|
||||
(stop-dev)
|
||||
(start-dev))
|
||||
|
||||
(comment
|
||||
(start-dev)
|
||||
(restart))
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
(ns app.core
|
||||
(:require [com.stuartsierra.component :as component]
|
||||
[app.system :as system]))
|
||||
[app.system :as system])
|
||||
(:gen-class))
|
||||
|
||||
(defn main []
|
||||
(component/start (system/system )))
|
||||
(defn -main []
|
||||
(component/start (system/new-system )))
|
||||
|
||||
(comment
|
||||
(component/stop (system/system))
|
||||
(component/stop (system/new-system))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,22 @@
|
|||
(ns app.system
|
||||
(:require [com.stuartsierra.component :as component]
|
||||
[aero.core :as aero]
|
||||
[app.components.webserver :refer [new-web-server]]))
|
||||
|
||||
(defn system []
|
||||
(defn new-system-map []
|
||||
(component/system-map
|
||||
:web (new-web-server)))
|
||||
|
||||
(defn configure [system]
|
||||
(let [config (aero/read-config "resources/config.edn")]
|
||||
(merge-with merge system config)))
|
||||
|
||||
(defn new-dependency-map [] {})
|
||||
|
||||
(defn new-system
|
||||
"Create the production system"
|
||||
[]
|
||||
(println ";; Setting up new system")
|
||||
(-> (new-system-map)
|
||||
(configure)
|
||||
(component/system-using (new-dependency-map))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue