-
Notifications
You must be signed in to change notification settings - Fork 21
/
env.clj
44 lines (37 loc) · 1.4 KB
/
env.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
(ns duct.core.env
"Functions for pulling values from environment variables."
(:require [clojure.string :as str]))
(defmulti coerce
"Coerce a value to the type referenced by a symbol. By default supports
`Int` and `Str`."
(fn [x type] type))
(defmethod coerce 'Int [x _]
(Long/parseLong x))
(defmethod coerce 'Str [x _]
(str x))
(defmethod coerce 'Bool [x _]
(case (some-> x str/lower-case)
("true" "t" "yes" "y") true
("false" "f" "no" "n" "" nil) false
(throw (ex-info (str "Could not coerce '" (pr-str x) "' into a boolean."
"Must be one of: \"true\", \"t\", \"false\", \"f\","
"\"yes\", \"y\", \"no\", \"n\", \"\" or nil.")
{:value x, :coercion 'Bool}))))
(defn env
"Resolve an environment variable by name. Optionally accepts a type for
coercion, and a keyword option, `:or`, that provides a default value if the
environment variable is missing.
The arguments may optionally be wrapped in a vector. This is to support
their use in [[duct.core/read-config]]. For example:
{:port #duct/env [\"PORT\" Int :or 3000]}"
([name]
(if (vector? name)
(apply env name)
(System/getenv name)))
([name type & options]
(if (keyword? type)
(apply env name 'Str type options)
(let [{default :or} options]
(-> (System/getenv name)
(some-> (coerce type))
(or default))))))