Liking cljdoc? Tell your friends :D

license

ninja.anywhere/unifier

A Clojure(Script) library for unified responses. The next generation of clj-unifier library.

codecov lint test build

anywhere-ninja-unifier

Rationale

Lots of engineers, projects and decisions. You may have encountered or used the monads like as Either, Maybe or something like this.

Maybe you used something similar:

  • Used nil’s

;; result of your business logic
(defn f [...]
  (when ...))

;; somewhere in your code
(if-let [res (f ...)]
  ;; (do something with data)
  ;; (do something with error)
  )
  • Used tuples of 2 elements:

;; result of your business logic
(defn f [...]
  [:error :success])

;; somewhere in your code
(let [[error data] (f ...)]
  (if error
    ;; (do something with error)
    ;; (do something with data)
    ))
  • Used maps with some structure:

;; result of your business logic
(defn f [...]
  {:error true
   :data   ...})

(let [{:keys [error data]} (f ...)]
  (if error
    ;; (do something with error)
    ;; (do something with data)
   ))

Probably did some solutions lose the identity of the data and set some restrictions? Have you ever had cases when you need to enrich the data, but without making changes to the data structure?

This library unify data flow, error handling, and take the mental load off developers by allowing them to add metadata without changing the data itself and without thinking about the structure of responses. This works well when working with multiple projects and multiple developers.

If you have not encountered such problems, you are lucky :)

Quick Start Guide

Add the following dependency in your project:

;; project.clj or build.boot
[ninja.anywhere/unifier "1.1.0"]

;; deps.edn
ninja.anywhere/unifier {:mvn/version "1.1.0"}

Examples

(ns your.app
  (:require
    [ninja.unifier.response :as r])
  (:import
    (java.util
      Date)))

;;;;
;; Simple example
;;;;

(def your-data {:your :data})


;; Unified error response

(def err
  (r/as-error your-data))


(identity err) ;; => {:your :data}
(r/response? err) ;; => true
(r/error? err) ;; => true
(r/type err) ;; => :error
(r/meta err) ;; => nil
(r/as-map err) ;; => {:type :error, :data {:your :data}, :meta nil}
(r/as-http err) ;; => {:headers {}, :status 500, :body {:your :data}}
(r/as-http err {:headers {"content-type" "application/edn"}}) ;; => {:headers {"content-type" "application/edn"}, :status 500, :body {:your :data}}


;; Unified success response

(def ok
  (r/as-success your-data))


(identity ok) ;; => {:your :data}
(r/response? ok) ;; => true
(r/error? ok) ;; => false
(r/type ok) ;; => :success
(r/meta ok) ;; => nil
(r/as-map ok) ;; => {:type :success, :data {:your :data}, :meta nil}
(r/as-http ok) ;; => {:headers {}, :status 200, :body {:your :data}}
(r/as-http ok {:headers {"content-type" "application/edn"}}) ;; => {:headers {"content-type" "application/edn"}, :status 200, :body {:your :data}}



;;;;
;; Response with metadata
;;;;

(def your-data {:your :data})
(def your-meta {:created-at (Date.)})


;; Unified error response

(def err
  (r/as-error your-data your-meta))


(identity err) ;; => {:your :data}
(r/response? err) ;; => true
(r/error? err) ;; => true
(r/type err) ;; => :error
(r/meta err) ;; => {:created-at #inst"2020-09-22T17:03:23.231-00:00"}
(r/as-map err) ;; => {:type :error, :data {:your :data}, :meta {:created-at #inst"2020-10-20T21:46:09.705-00:00"}}
(r/as-http err) ;; => {:headers {}, :status 500, :body {:your :data}}
(r/as-http err {:headers {"content-type" "application/edn"}}) ;; => {:headers {"content-type" "application/edn"}, :status 500, :body {:your :data}}


;; Unified success response

(def ok
  (r/as-success your-data your-meta))


(identity ok) ;; => {:your :data}
(r/response? ok) ;; => true
(r/error? ok) ;; => false
(r/type ok) ;; => :success
(r/meta ok) ;; => {:created-at #inst"2020-09-22T17:03:23.231-00:00"}
(r/as-map ok) ;; => {:type :success, :data {:your :data}, :meta {:created-at #inst"2020-10-20T21:46:09.705-00:00"}}
(r/as-http ok) ;; => {:headers {}, :status 200, :body {:your :data}}
(r/as-http ok {:headers {"content-type" "application/edn"}}) ;; => {:headers {"content-type" "application/edn"}, :status 200, :body {:your :data}}



;;;;
;; Unified custom response
;;;;

(def your-data {:your :data})
(def your-meta {:created-at (Date.)})


;; Unified custom error response

(def err
  (r/as-response
    your-data
    {:type :custom/error, :error? true, :meta your-meta}))


(identity err) ;; => {:your :data}
(r/response? err) ;; => true
(r/error? err) ;; => true
(r/type err) ;; => :custom/error
(r/meta err) ;; => {:created-at #inst"2020-09-22T17:03:23.231-00:00"}
(r/as-map err) ;; => {:type :custom/error, :data {:your :data}, :meta {:created-at #inst"2020-10-20T21:46:09.705-00:00"}}
(r/as-http err) ;; => {:headers {}, :status 500, :body {:your :data}}
(r/as-http err {:headers {"content-type" "application/edn"}}) ;; => {:headers {"content-type" "application/edn"}, :status 500, :body {:your :data}}


;; Unified custom success response

(def ok
  (r/as-response
    your-data
    {:type :custom/ok, :error? false, :meta your-meta}))


(identity ok) ;; => {:your :data}
(r/response? ok) ;; => true
(r/error? ok) ;; => false
(r/type ok) ;; => :custom/ok
(r/meta ok) ;; => {:created-at #inst"2020-09-22T17:03:23.231-00:00"}
(r/as-map ok) ;; => {:type :custom/ok, :data {:your :data}, :meta {:created-at #inst"2020-09-22T17:03:23.231-00:00"}}
(r/as-http ok) ;; => {:headers {}, :status 200, :body {:your :data}}
(r/as-http ok {:headers {"content-type" "application/edn"}}) ;; => {:headers {"content-type" "application/edn"}, :status 200, :body {:your :data}}



;;;;
;; The available predefined unified responses
;;;;

;; Unified error responses

(r/as-warning ...)
(r/as-error ...)
(r/as-exception ...)
(r/as-unavailable ...)
(r/as-interrupted ...)
(r/as-incorrect ...)
(r/as-unauthorized ...)
(r/as-forbidden ...)
(r/as-not-found ...)
(r/as-unsupported ...)
(r/as-conflict ...)
(r/as-busy ...)
(r/as-unknown ...)


;; Unified success responses

(r/as-success ...)
(r/as-created ...)
(r/as-deleted ...)
(r/as-accepted ...)

License

Copyright © 2019-2020 anywhere.ninja. All rights reserved.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close