introduce a spec driven cli-main

master
jem 4 years ago
parent 9a15dc9bb8
commit 22aa6ba39b

@ -3,7 +3,7 @@
:dependencies [[orchestra "2018.12.06-2"]] :dependencies [[orchestra "2018.12.06-2"]]
:builds {:dev {:target :node-library :builds {:dev {:target :node-library
:output-to "target/node-lib.js" :output-to "target/node-lib.js"
:exports {:infra mastodon-bot.core/-main} :exports {:infra mastodon-bot.core/main}
:repl-pprint true} :repl-pprint true}
:test {:target :node-test :test {:target :node-test
:output-to "target/node-tests.js" :output-to "target/node-tests.js"
@ -11,5 +11,5 @@
:autorun true} :autorun true}
:app {:target :node-script :app {:target :node-script
:output-to "target/mastodon-bot.js" :output-to "target/mastodon-bot.js"
:main mastodon-bot.core/-main :main mastodon-bot.core/main
:compiler-options {:optimizations :simple}}}} :compiler-options {:optimizations :simple}}}}

@ -1,16 +1,14 @@
#!/usr/bin/env lumo
(ns mastodon-bot.core (ns mastodon-bot.core
(:require (:require
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[clojure.spec.test.alpha :as st] [clojure.spec.test.alpha :as st]
[clojure.string :as cs]
[orchestra.core :refer-macros [defn-spec]] [orchestra.core :refer-macros [defn-spec]]
[mastodon-bot.infra :as infra] [mastodon-bot.infra :as infra]
[mastodon-bot.transform :as transform] [mastodon-bot.transform :as transform]
[mastodon-bot.mastodon-api :as masto] [mastodon-bot.mastodon-api :as masto]
[mastodon-bot.twitter-api :as twitter] [mastodon-bot.twitter-api :as twitter]
[mastodon-bot.tumblr-api :as tumblr] [mastodon-bot.tumblr-api :as tumblr]))
[cljs.core :refer [*command-line-args*]]))
(s/def ::mastodon masto/mastodon-auth?) (s/def ::mastodon masto/mastodon-auth?)
(s/def ::twitter twitter/twitter-auth?) (s/def ::twitter twitter/twitter-auth?)
@ -20,6 +18,12 @@
(def config? (def config?
(s/keys :req-un [::auth ::transform])) (s/keys :req-un [::auth ::transform]))
(s/def ::options (s/* #{"-h"}))
(s/def ::config-location (s/? (s/and string?
#(not (cs/starts-with? % "-")))))
(s/def ::args (s/cat :options ::options
:config-location ::config-location))
(defn-spec mastodon-auth ::mastodon (defn-spec mastodon-auth ::mastodon
[config config?] [config config?]
(get-in config [:auth :mastodon])) (get-in config [:auth :mastodon]))
@ -36,10 +40,9 @@
[config config?] [config config?]
(:transform config)) (:transform config))
(def config (infra/load-config)) (defn -main [{:keys [options config-location] :as args}]
(let [config (infra/load-config config-location)
(defn -main [] mastodon-auth (mastodon-auth config)]
(let [mastodon-auth (mastodon-auth config)]
(masto/get-mastodon-timeline (masto/get-mastodon-timeline
mastodon-auth mastodon-auth
(fn [timeline] (fn [timeline]
@ -77,7 +80,13 @@
)))) ))))
))))) )))))
(set! *main-cli-fn* -main) (defn main [& args]
(let [parsed-args (s/conform ::args args)]
(if (= ::s/invalid parsed-args)
(do (s/explain ::args args)
(infra/exit-with-error "Bad commandline arguments"))
(-main parsed-args))))
(st/instrument 'mastodon-auth) (st/instrument 'mastodon-auth)
(st/instrument 'twitter-auth) (st/instrument 'twitter-auth)
(st/instrument 'transform) (st/instrument 'transform)

@ -10,13 +10,16 @@
(js/console.error error) (js/console.error error)
(js/process.exit 1)) (js/process.exit 1))
(defn find-config [] (defn find-config [config-location]
(let [config (or (first *command-line-args*) (let [config (or config-location
(-> js/process .-env .-MASTODON_BOT_CONFIG) (-> js/process .-env .-MASTODON_BOT_CONFIG)
"config.edn")] "config.edn")]
(if (fs/existsSync config) (if (fs/existsSync config)
config config
(exit-with-error (str "failed to read config: " config))))) (exit-with-error (str "failed to read config: " config)))))
(defn load-config [] (defn load-config [config-location]
(-> (find-config) (fs/readFileSync #js {:encoding "UTF-8"}) edn/read-string)) (-> config-location
(find-config)
(fs/readFileSync #js {:encoding "UTF-8"})
edn/read-string))