module Database.CouchDB.Conduit.Internal.Doc (
couchRev,
couchDelete,
couchGetRaw,
couchGetWith,
couchPutWith,
couchPutWith'
) where
import Prelude hiding (catch)
import Control.Exception.Lifted (catch)
import Control.Monad.Trans.Class (lift)
import Data.Maybe (fromJust)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text.Encoding as TE
import qualified Data.Aeson as A
import Data.Conduit (ResourceT, resourceThrow, ($$))
import qualified Data.Conduit.Attoparsec as CA
import qualified Network.HTTP.Conduit as H
import Network.HTTP.Types as HT
import Database.CouchDB.Conduit
import Database.CouchDB.Conduit.LowLevel (couch, protect')
import Database.CouchDB.Conduit.Internal.Parser
couchRev :: MonadCouch m =>
Path
-> ResourceT m Revision
couchRev p = do
(H.Response _ hs _) <- couch HT.methodHead p [] []
(H.RequestBodyBS B.empty)
protect'
return $ peekRev hs
where
peekRev = B.tail . B.init . fromJust . lookup "Etag"
couchDelete :: MonadCouch m =>
Path
-> Revision
-> ResourceT m ()
couchDelete p r = couch HT.methodDelete p
[] [("rev", Just r)]
(H.RequestBodyBS B.empty)
protect' >> return ()
couchGetRaw :: MonadCouch m =>
Path
-> HT.Query
-> ResourceT m A.Value
couchGetRaw p q = do
H.Response _ _ bsrc <- couch HT.methodGet p [] q
(H.RequestBodyBS B.empty) protect'
bsrc $$ CA.sinkParser A.json
couchGetWith :: MonadCouch m =>
(A.Value -> A.Result a)
-> Path
-> Query
-> ResourceT m (Revision, a)
couchGetWith f p q = do
H.Response _ _ bsrc <- couch HT.methodGet p [] q
(H.RequestBodyBS B.empty) protect'
j <- bsrc $$ CA.sinkParser A.json
A.String r <- lift $ extractField "_rev" j
o <- lift $ jsonToTypeWith f j
return (TE.encodeUtf8 r, o)
couchPutWith :: MonadCouch m =>
(a -> BL.ByteString)
-> Path
-> Revision
-> Query
-> a
-> ResourceT m Revision
couchPutWith f p r q val = do
H.Response _ _ bsrc <- couch HT.methodPut p (ifMatch r) q
(H.RequestBodyLBS $ f val) protect'
j <- bsrc $$ CA.sinkParser A.json
lift $ extractRev j
where
ifMatch "" = []
ifMatch rv = [("If-Match", rv)]
couchPutWith' :: MonadCouch m =>
(a -> BL.ByteString)
-> Path
-> HT.Query
-> a
-> ResourceT m Revision
couchPutWith' f p q val = do
rev <- catch (couchRev p) handler404
couchPutWith f p rev q val
where
handler404 (CouchError (Just 404) _) = return ""
handler404 e = lift $ resourceThrow e