mirror of
https://github.com/edufeed-org/amb-api.git
synced 2025-12-09 16:24: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"}
|
io.pedestal/pedestal.jetty {:mvn/version "0.7.1"}
|
||||||
org.slf4j/slf4j-simple {:mvn/version "2.0.10"}
|
org.slf4j/slf4j-simple {:mvn/version "2.0.10"}
|
||||||
luposlip/json-schema {:mvn/version "0.4.6"}
|
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"}}
|
net.clojars.laoc/nostr {:local/root "/home/laoc/coding/nostr-clj"}}
|
||||||
|
|
||||||
:aliases
|
: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
|
{:extra-deps
|
||||||
{nrepl/nrepl {:mvn/version "1.3.0"}}
|
{nrepl/nrepl {:mvn/version "1.3.0"}}
|
||||||
:main-opts ["-m" "nrepl.cmdline"
|
: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,11 +8,12 @@
|
||||||
[json-schema.core :as json-schema]
|
[json-schema.core :as json-schema]
|
||||||
[clojure.core.async :refer [go chan >! <!]]))
|
[clojure.core.async :refer [go chan >! <!]]))
|
||||||
|
|
||||||
(defn validate [resources]
|
(def schema (json-schema/prepare-schema
|
||||||
(let [schema (json-schema/prepare-schema
|
|
||||||
(-> "resources/schema.json"
|
(-> "resources/schema.json"
|
||||||
slurp
|
slurp
|
||||||
(cheshire.core/parse-string true)))]
|
(cheshire.core/parse-string true))))
|
||||||
|
|
||||||
|
(defn validate [resources]
|
||||||
(try
|
(try
|
||||||
(let [validation-results
|
(let [validation-results
|
||||||
(map (fn [resource]
|
(map (fn [resource]
|
||||||
|
|
@ -25,15 +26,14 @@
|
||||||
(do
|
(do
|
||||||
;; Log invalid resources
|
;; Log invalid resources
|
||||||
(doseq [{:keys [error resource]} (filter #(not (:valid %)) validation-results)]
|
(doseq [{:keys [error resource]} (filter #(not (:valid %)) validation-results)]
|
||||||
(println "Invalid resource:" resource "Error:" error))
|
#_(println "Invalid resource:" resource "Error:" error))
|
||||||
;; Return only valid resources
|
;; Return only valid resources
|
||||||
(->> validation-results
|
(->> validation-results
|
||||||
(filter :valid)
|
(filter :valid)
|
||||||
(map :resource))))
|
(map :resource))))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(println "Unexpected error during validation" e)
|
#_(println "Unexpected error during validation" e)
|
||||||
[]))))
|
nil)))
|
||||||
|
|
||||||
|
|
||||||
(defn ok [body]
|
(defn ok [body]
|
||||||
{:status 200 :body body})
|
{:status 200 :body body})
|
||||||
|
|
@ -44,10 +44,11 @@
|
||||||
(go
|
(go
|
||||||
(let [npub (get-in request [:query-params :npub])
|
(let [npub (get-in request [:query-params :npub])
|
||||||
pk (get-in request [:query-params :pk])
|
pk (get-in request [:query-params :pk])
|
||||||
|
relay (get-in request [:relay])
|
||||||
filter (if pk
|
filter (if pk
|
||||||
{:kinds [30142] :authors [pk]}
|
{:kinds [30142] :authors [pk]}
|
||||||
{:kinds [30142]})
|
{: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)
|
transformed (map #(edufeed/convert-30142-to-nostr-amb % true true) resources)
|
||||||
validate (validate transformed)
|
validate (validate transformed)
|
||||||
resp (if validate
|
resp (if validate
|
||||||
|
|
@ -60,34 +61,37 @@
|
||||||
{:name ::resources-by-user
|
{:name ::resources-by-user
|
||||||
:enter (fn [context]
|
:enter (fn [context]
|
||||||
(go
|
(go
|
||||||
(let [result (<! (get-resources (:request context)))
|
(let [result (<! (get-resources (:request context)))]
|
||||||
;; TODO check against amb schema
|
|
||||||
]
|
|
||||||
(assoc context :response (ok result)))))})
|
(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
|
(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
|
(def service-map
|
||||||
{::http/routes routes
|
{::http/routes routes
|
||||||
::http/type :jetty
|
::http/type :jetty
|
||||||
::http/port 8890})
|
::http/port 8890})
|
||||||
|
|
||||||
(defn create-service []
|
(defn create-service [relay]
|
||||||
(http/create-server service-map))
|
(http/create-server
|
||||||
|
(assoc service-map
|
||||||
|
::http/routes (routes relay)
|
||||||
|
::http/port 8890)))
|
||||||
|
|
||||||
(defn start []
|
(defrecord WebServer [relay]
|
||||||
(http/start (create-service)))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(http/stop (create-service)))
|
|
||||||
|
|
||||||
(defrecord WebServer []
|
|
||||||
component/Lifecycle
|
component/Lifecycle
|
||||||
(start [this]
|
(start [this]
|
||||||
(println ";; Starting Web server...")
|
(println ";; Starting Webserver")
|
||||||
(let [server (create-service)]
|
(println ";; Using Relay: " relay)
|
||||||
|
(let [server (create-service relay)]
|
||||||
(assoc this :server (http/start server))))
|
(assoc this :server (http/start server))))
|
||||||
(stop [this]
|
(stop [this]
|
||||||
(println ";; Stopping Web server...")
|
(println ";; Stopping Web server...")
|
||||||
|
|
@ -98,22 +102,3 @@
|
||||||
(defn new-web-server []
|
(defn new-web-server []
|
||||||
(map->WebServer {}))
|
(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
|
(ns app.core
|
||||||
(:require [com.stuartsierra.component :as component]
|
(:require [com.stuartsierra.component :as component]
|
||||||
[app.system :as system]))
|
[app.system :as system])
|
||||||
|
(:gen-class))
|
||||||
|
|
||||||
(defn main []
|
(defn -main []
|
||||||
(component/start (system/system )))
|
(component/start (system/new-system )))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(component/stop (system/system))
|
(component/stop (system/new-system))
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,22 @@
|
||||||
(ns app.system
|
(ns app.system
|
||||||
(:require [com.stuartsierra.component :as component]
|
(:require [com.stuartsierra.component :as component]
|
||||||
|
[aero.core :as aero]
|
||||||
[app.components.webserver :refer [new-web-server]]))
|
[app.components.webserver :refer [new-web-server]]))
|
||||||
|
|
||||||
(defn system []
|
(defn new-system-map []
|
||||||
(component/system-map
|
(component/system-map
|
||||||
:web (new-web-server)))
|
: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