66--
77{-# LANGUAGE LambdaCase #-}
88{-# LANGUAGE NamedFieldPuns #-}
9+ {-# OPTIONS_GHC -fno-warn-orphans #-}
910module PostgREST.ApiRequest.Payload
1011 ( getPayload
1112 ) where
@@ -18,13 +19,16 @@ import qualified Data.ByteString.Lazy as LBS
1819import qualified Data.Csv as CSV
1920import qualified Data.HashMap.Strict as HM
2021import qualified Data.Map.Strict as M
22+ import qualified Data.Scientific as Sci
2123import qualified Data.Set as S
2224import qualified Data.Text.Encoding as T
2325import qualified Data.Vector as V
2426
2527import Control.Arrow ((***) )
28+ import Control.Monad (fail )
29+ import Data.Aeson ((.:) )
2630import Data.Aeson.Types (emptyArray , emptyObject )
27- import Data.Either.Combinators (mapBoth )
31+ import Data.Either.Combinators (mapBoth , mapLeft )
2832import Network.HTTP.Types.URI (parseSimpleQuery )
2933
3034import PostgREST.ApiRequest.QueryParams (QueryParams (.. ))
@@ -44,6 +48,7 @@ getPayload reqBody contentMediaType QueryParams{qsColumns} action = do
4448 (Just ProcessedJSON {payKeys}, _) -> payKeys
4549 (Just ProcessedUrlEncoded {payKeys}, _) -> payKeys
4650 (Just RawJSON {}, Just cls) -> cls
51+ (Just PgrstPatchPay {}, Just cls) -> cls
4752 _ -> S. empty
4853 return (checkedPayload, cols)
4954 where
@@ -69,8 +74,12 @@ getPayload reqBody contentMediaType QueryParams{qsColumns} action = do
6974 (MTTextPlain , True ) -> Right $ RawPay reqBody
7075 (MTTextXML , True ) -> Right $ RawPay reqBody
7176 (MTOctetStream , True ) -> Right $ RawPay reqBody
77+ (MTVndPgrstPatch , False ) -> PgrstPatchPay <$> parsePgrstPatch reqBody
7278 (ct, _) -> Left $ " Content-Type not acceptable: " <> MediaType. toMime ct
7379
80+ parsePgrstPatch :: LBS. ByteString -> Either ByteString [PgrstPatchOp ]
81+ parsePgrstPatch = mapLeft BS. pack . JSON. eitherDecode
82+
7483 shouldParsePayload = case action of
7584 ActDb (ActRelationMut _ MutationDelete ) -> False
7685 ActDb (ActRelationMut _ _) -> True
@@ -88,6 +97,7 @@ getPayload reqBody contentMediaType QueryParams{qsColumns} action = do
8897 _ -> False
8998 params = (T. decodeUtf8 *** T. decodeUtf8) <$> parseSimpleQuery (LBS. toStrict reqBody)
9099
100+
91101type CsvData = V. Vector (M. Map Text LBS. ByteString )
92102
93103{-|
@@ -136,3 +146,32 @@ payloadAttributes raw json =
136146 _ -> Just emptyPJArray
137147 where
138148 emptyPJArray = ProcessedJSON (JSON. encode emptyArray) S. empty
149+
150+
151+ instance JSON. FromJSON PgrstPatchOp where
152+ parseJSON (JSON. Object o) = do
153+ op <- parseString o " op"
154+ path <- parseString o " path"
155+ -- TODO: We need to decide what JSON "value"s are allowed in our
156+ -- our Pgrst Patch implementation.
157+ -- For now, we only have incr operator, so it's number only
158+ case op of
159+ " incr" -> Incr path <$> parseNumber o " value"
160+ _ -> fail $ " Unknown Pgrst Patch operation " ++ show op
161+ where
162+ parseString obj key = do
163+ val <- obj .: key
164+ case val of
165+ JSON. String txt -> pure txt
166+ _ -> fail $ " Expected JSON string for " ++ show key
167+
168+ parseNumber obj key = do
169+ val <- obj .: key
170+ case val of
171+ JSON. Number num -> pure $ sciToInt num
172+ _ -> fail $ " Expected JSON number for " ++ show key
173+ where
174+ sciToInt :: Sci. Scientific -> Int
175+ sciToInt = fromMaybe 0 . Sci. toBoundedInteger
176+
177+ parseJSON _ = mzero
0 commit comments