Created
August 10, 2018 17:07
-
-
Save emidln/c413dfd4301786393523204a47ae0968 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns spec.settings | |
"Organizes and validates your settings with clojure.spec and spec-tools." | |
(:require [clojure.string :as str] | |
[clojure.spec.alpha :as s] | |
[spec-tools.spec :as spec] | |
[spec-tools.core :as st] | |
[spec-tools.data-spec :as ds])) | |
(defmacro for-map | |
"Like for, but returns a map. Expects the result to be a pair or map." | |
{:style/indent 1 | |
:private true} | |
[& body] | |
`(->> (for ~@body) | |
(into {}))) | |
(defn env | |
"SampleAPI settings from the environment" | |
[& [filter-prefix]] | |
(for-map [[s v] (System/getenv) | |
:when (and filter-prefix (str/starts-with? s filter-prefix))] | |
{(-> (str/lower-case s) | |
(str/replace "sampleapi_" "") | |
(str/replace "_" "-") | |
keyword) | |
v})) | |
(defn props | |
"SampleAPI settings from properties" | |
[& [filter-prefix]] | |
(for-map [[s v] (System/getProperties) | |
:when (and filter-prefix (str/starts-with? s filter-prefix))] | |
{(-> (str/lower-case s) | |
(str/replace-first "sampleapi." "") | |
(str/replace "." "-") | |
keyword) | |
v})) | |
(defn defaults | |
"SampleAPI settings defaults" | |
[] | |
(for-map [[setting {:keys [default] :as config}] settings-config | |
:when (not= (config :default ::not-set) ::not-set)] | |
{setting default})) | |
(defn all-settings | |
"SampleAPI settings. If given a filter prefix" | |
[& [filter-prefix]] | |
(merge (env (when filter-prefix (str/upper-case filter-prefix))) | |
(props (when filter-prefix (str/lower-case filter-prefix))) | |
(defaults))) | |
(defn validate-settings-fn | |
"Validates all-settings meet the settings-spec. Exits the process with explanation on failure." | |
[settings-spec all-settings] | |
(st/decode settings-spec all-settings st/string-transformer)) | |
(defn validate-settings! | |
([settings-spec] | |
(validate-settings! settings-spec (all-settings))) | |
([settings-spec all-settings] | |
(let [settings (validate-settings-fn settings-spec all-settings)] | |
(if (= ::s/invalid settings) | |
(do | |
(println "Invalid settings configuration. See spec output:") | |
(println | |
(with-out-str | |
(st/explain settings-spec all-settings st/string-transformer))) | |
(System/exit 1)) | |
settings)))) | |
(defn settings-spec | |
[spec-name settings-config] | |
(->> {:spec ~(for-map [[setting {:keys [spec]}] settings-config] | |
{setting spec}) | |
:name ::settings} | |
ds/spec)) | |
(comment | |
(require '[clojure.spec.alpha :as s]) | |
(require '[spec-tools.spec :as spec]) | |
(require '[spec.settings :as ss]) | |
;; declare your configuration | |
(def settings-config | |
{:debug {:spec spec/boolean? | |
:default false} | |
:num-processes {:spec spec/integer? | |
:default 4}}) | |
;; specify your config | |
(s/def ::settings (ss/settings-spec ::settings settings-config)) | |
;; validate your settings | |
(ss/validate-settings! ::settings (all-settings "sampleapp")) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment