 (defn promise?
   "Returns true if `p` is a primise instance."
   [p]
-  (satisfies? proto/IPromise p))
+  (satisfies? p/IPromise p))
 
 (defn resolved?
   "Returns true if promise `p` is already fulfilled."
   [p]
-  (proto/-resolved? p))
+  (p/-resolved? p))
 
 (defn fulfilled?
   "Convenience alias for the `resolved?` predicate."
   [p]
-  (proto/-resolved? p))
+  (p/-resolved? p))
 
 (defn rejected?
   "Returns true if promise `p` is already rejected."
   [p]
-  (proto/-rejected? p))
+  (p/-rejected? p))
 
 (defn pending?
   "Returns true if promise `p` is stil pending."
   [p]
-  (proto/-pending? p))
+  (not (p/-done? p)))
 
 (defn done?
   "Returns true if promise `p` is already done."
   [p]
-  (not (proto/-pending? p)))
+  (p/-done? p))
 
 ;; Chain operations
 
 (defn then
   "A chain helper for promises."
   [p callback]
-  (proto/-then p callback))
-
-(defn finally
-  "A chain helper that associate handler to the promise
-  that will be called regardless if it is resolved or
-  rejected."
-  [p callback]
-  (proto/-finally p callback))
+  (p/-then p callback))
+
+(defn chain
+  "A variadic chain operation."
+  [p & funcs]
+  (reduce #(then %1 %2) p funcs))
 
 (defn catch
   "Catch all promise chain helper."
   ([p callback]
-   (proto/-catch p callback))
+   (p/-catch p callback))
   ([p type callback]
-   (proto/-catch p type callback)))
-
-(defn error
-  "Catch operational errors promise chain helper."
-  [p callback]
-  (.error p callback))
+   (p/-catch p type callback)))
 
 ;; Helpers
 

                  type)]
       (.catch it type cb))))

  (-finally [it cb]
    (.finally it cb))

  proto/IState
  (-resolved? [it]
    (.isFulfilled it))
  (-rejected? [it]
    (.isRejected it))
  (-pending? [it]
    (.isPending it))
  (-value [it]
    (.value it))
  (-reason [it]
    (.reason it)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Public Api

(ns promesa.core
  (:refer-clojure :exclude [delay spread some])
  (:require [cats.core :as m]
            [cats.context :as mc]
            [cats.protocols :as mp]
            [promesa.protocols :as p]
            [org.bluebird]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Implementation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(declare promise-context)

(extend-type js/Promise
  mp/Context
  (-get-context [_] promise-context)

  mp/Extract
  (-extract [it]
    (if (.isRejected it)
      (.cause it)
      (.value it)))

  p/IPromise
  (-then [it cb]
    (.then it cb))

