Utilities

All functions are located in the com.biffweb namespace.

(pprint & args)
Alias of clojure.pprint/pprint

start-system

View source
(start-system init)
Deprecated. See Biff v0.7.3 release notes.

Starts a system from an initial system map.

Stores the system in the com.biffweb/system atom. Returns the contents of the
atom. See https://biffweb.com/docs/reference/system-composition
(refresh)
Deprecated. See Biff v0.7.3 release notes.

Stops the system, refreshes source files, and restarts the system.

The system is stopped by calling all the functions in (:biff/stop
@com.biffweb/system). (:biff/after-refresh @system) is a fully-qualified
symbol which will be resolved and called after refreshing. See
https://biffweb.com/docs/reference/system-composition

use-config

View source
(use-config {:keys [biff/config], :or {config "config.edn"}, :as ctx})
Deprecated. Prefer use-aero-config.

Reads config from an edn file and merges into ctx.

The config file's contents should be a map from environments to config keys
and values, for example:

{:prod {:host "example.com"
        :port 8080}
 :dev {:merge [:prod]
       :host "localhost"}}

The current environment should be stored in the BIFF_ENV environment variable.
The default value is `prod`. To inherit config from other environments, set
:merge to a sequence of environment keys.

use-aero-config

View source
(use-aero-config {:keys [biff.config/skip-validation], :as ctx})
Reads config from various places and merges it into ctx.

 Loads a config.edn file from resources and parses it with Aero. (See
 https://github.com/juxt/aero). Two additional reader tags are supported:
 #biff/env and #biff/secret.

 #biff/env is like #env, but environment variables can also be specified in an
 optional config.env file (read from the filesystem, not from resources) and
 in the system properties (variable names should be prefixed with biff.env,
 e.g biff.env.BIFF_PROFILE). If values are defined in multiple places,
 precedence is as follows:

   1. System properties
   2. Actual environment variables
   3. config.env

 The :profile value for Aero is also taken from these sources, in the
 BIFF_PROFILE key (e.g. `BIFF_PROFILE=prod` -- the value is converted to a
 keyword). It can also be passed in with `ctx` via the :biff.config/profile
 key, but this is only intended as a convenience for inspecting your config
 from the REPL.

 #biff/secret is like #biff/env, but wraps values in a function so that they
 aren't visible if you serialize the system map. The :biff/secret key on the
 system map will be set to a function that can be used to retrieve secret
 values, for example:

   (let [{:keys [biff/secret]} ctx
         jwt-secret (secret :biff/jwt-secret)]
     ...)

 After config is merged into ctx, any keys in ctx with the
 biff.system-properties namespace will be added to the system properties. For
 example:

   :biff.system-properties/user.timezone "UTC"
   ;; Equivalent to:
   (System/setProperty "user.timezone" "UTC")

 Finally, if :biff.middleware/cookie-secret or :biff/jwt-secret aren't set, an
 error will be printed and the process will exit. This can be disabled by
 setting `:biff.config/skip-validation true`.
(sh & args)
Runs a shell command.

Returns the output if successful; otherwise, throws an exception.

assoc-some

View source
(assoc-some m & kvs)
Like assoc, but skips kv pairs where the value is nil.
(pred-> x pred f)
Convenience fn for (cond-> x (pred x) f)
(join sep xs)
Returns a sequence where the elements of coll are separated by sep.

safe-merge

View source
(safe-merge & ms)
Like merge, but throws an exception if any maps share keys.

normalize-email

View source
(normalize-email email)
Normalizes an email address to make future lookups easier.

Trims leading and trailing whitespace and converts to lower case. Returns nil
if the email is empty after trimming.

use-when

View source
(use-when f & components)
Passes the system map to components only if (f system) is true.

See https://biffweb.com/docs/reference/system-composition
(sha256 string)
Returns the SHA256 hash of string.

base64-encode

View source
(base64-encode bytes)
Converts a byte array to a base64 string.

base64-decode

View source
(base64-decode string)
Converts a base64 string to a byte array.

anomaly?

View source
(anomaly? x)
Returns true if x is an anomaly.

See https://github.com/cognitect-labs/anomalies
(anom category & [message & [opts]])
Constructs an anomaly.

Example: (anom :incorrect
               "Invalid parameter"
               {:info "x should be an integer"})

See https://github.com/cognitect-labs/anomalies

select-ns-as

View source
(select-ns-as m ns-from ns-to)
Selects and renames keys from m based on the namespace.

Examples:

(select-ns-as {:foo/a 1, :foo.bar/b 2, :baz/c 3} 'foo 'quux)
=> {:quux/a 1, :quux.bar/b 2}

(select-ns-as {:foo/a 1, :foo.bar/b 2, :baz/c 3} 'foo nil)
=> {:a 1, :bar/b 2}

catchall

View source
(catchall & body)
Wraps body in (try ... (catch Exception _ nil))

catchall-verbose

View source
(catchall-verbose & body)
Like catchall, but prints exceptions.
(letd bindings & body)
Like let, but transparently wraps all bindings with delay.

Examples:

(macroexpand-1 '(letd [a 1]
                  a))
=> (let [a (delay 1)]
     @a)

(letd [a (do (println "a evaluated")
             1)
       {:keys [b]} (do (println "b evaluated")
                       {:b 2})
       [_ _ c] (do (println "c evaluated")
                   [1 2 3])]
  (if (even? b)
    a
    c))
=>
(out) b evaluated
(out) a evaluated
1

fix-print

View source
(fix-print & body)
Ensures that print output doesn't get swallowed by e.g. an editor nrepl plugin.

Binds *out*, *err* and *flush-on-newline* to their root values.

(fix-print
  (println "hello"))

eval-files!

View source
(eval-files!
 {:keys [biff/eval-paths biff.eval/on-eval],
  :or {eval-paths ["src"]},
  :as ctx})
Evaluates any modified files and their dependents via clojure.tools.namespace.

 Returns the evaluation result. If set, `on-eval` is a sequence of 2-parameter
 callback functions which will each be called with `ctx` and the evaluation
 result.

add-libs

View source
(add-libs)
Loads new dependencies in deps.edn via tools.deps.alpha.

Ensures that a DynamicClassLoader is available so that this works even when
not evaluated from the repl. See
https://ask.clojure.org/index.php/10761/clj-behaves-different-in-the-repl-as-opposed-to-from-a-file

delete-old-files

View source
(delete-old-files
 {:keys [dir exts age-seconds], :or {age-seconds 30}, :as opts})
Deletes files descended from the given directory that are older than a given threshold.

dir:          A path to a directory.
age-seconds:  Files will only be deleted if it's been at least this number of seconds since they
              were last modified. Defaults to 30 seconds.
exts:         An optional collection of filename extentions. If provided, files will only be
              deleted if they end with one of the extentions.

For example:
(delete-old-files {:dir "target/resources/public"
                   :exts [".html"]})

s3-request

View source
(s3-request
 {:keys [biff/secret],
  :biff.s3/keys [origin access-key bucket key method headers body],
  :as ctx}
 &
 {:as opts})
Makes a request to an S3-compatible service.

- `key` will be coerced to a string.
- `body` can be a string or a file.
- `headers` is a map. When putting an object, it should at least contain the
  keys "content-type" and "x-amz-acl".
- Common values for the "x-amz-acl" header include "public-read" and
  "private".
- Any keys in `opts` will be prepended with the biff.s3 namespace and merged
  into `ctx`.
- Your S3 secret key should be accessible with (secret :biff.s3/secret-key).
- Public files will be available at "<edge URL>/<key>", for example,
  https://example.ny3.cdn.digitaloceanspaces.com/your-key.

EXAMPLES
========

# secrets.env
S3_SECRET_KEY="your-secret-key"

;; config.edn
{:prod {:biff.s3/origin "https://nyc3.digitaloceanspaces.com"
        :biff.s3/access-key "your-access-key"
        :biff.s3/secret-key "S3_SECRET_KEY"
        :biff.s3/bucket "default-bucket"
        ...

;; Put an object:
(s3-request ctx {:method "PUT"
                 :key "some-key"
                 :body "some-body"
                 :headers {"x-amz-acl" "private"
                           "content-type" "text/plain"}})

;; Get an object:
(:body (s3-request ctx {:method "GET"
                        :key "some-key"}))
Have a question? Join the #biff channel on Clojurians Slack, or ask on GitHub.

Sign up for Biff: The Newsletter
Announcements, blog posts, et cetera et cetera.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.