{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}

module Eventium.Store.Sql.JSONString
  ( JSONString,
    jsonStringSerializer,
  )
where

import Data.Aeson
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy.Encoding as TLE
import Database.Persist
import Database.Persist.Sql
import Eventium.Serializer

-- | A more specific type than just ByteString for JSON data.
newtype JSONString = JSONString {JSONString -> Text
unJSONString :: Text}
  deriving (JSONString -> JSONString -> Bool
(JSONString -> JSONString -> Bool)
-> (JSONString -> JSONString -> Bool) -> Eq JSONString
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: JSONString -> JSONString -> Bool
== :: JSONString -> JSONString -> Bool
$c/= :: JSONString -> JSONString -> Bool
/= :: JSONString -> JSONString -> Bool
Eq, PersistValue -> Either Text JSONString
JSONString -> PersistValue
(JSONString -> PersistValue)
-> (PersistValue -> Either Text JSONString)
-> PersistField JSONString
forall a.
(a -> PersistValue)
-> (PersistValue -> Either Text a) -> PersistField a
$ctoPersistValue :: JSONString -> PersistValue
toPersistValue :: JSONString -> PersistValue
$cfromPersistValue :: PersistValue -> Either Text JSONString
fromPersistValue :: PersistValue -> Either Text JSONString
PersistField)

instance PersistFieldSql JSONString where
  sqlType :: Proxy JSONString -> SqlType
sqlType Proxy JSONString
_ = Text -> SqlType
SqlOther Text
"jsonb"

instance Show JSONString where
  show :: JSONString -> String
show = Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (JSONString -> Text) -> JSONString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JSONString -> Text
unJSONString

jsonStringSerializer :: (ToJSON a, FromJSON a) => Serializer a JSONString
jsonStringSerializer :: forall a. (ToJSON a, FromJSON a) => Serializer a JSONString
jsonStringSerializer =
  (a -> JSONString)
-> (JSONString -> Maybe a)
-> (JSONString -> Either String a)
-> Serializer a JSONString
forall a b.
(a -> b)
-> (b -> Maybe a) -> (b -> Either String a) -> Serializer a b
Serializer
    a -> JSONString
forall a. ToJSON a => a -> JSONString
encodeJSON
    JSONString -> Maybe a
forall a. FromJSON a => JSONString -> Maybe a
decodeJSON
    JSONString -> Either String a
forall a. FromJSON a => JSONString -> Either String a
decodeJSONEither

encodeJSON :: (ToJSON a) => a -> JSONString
encodeJSON :: forall a. ToJSON a => a -> JSONString
encodeJSON = Text -> JSONString
JSONString (Text -> JSONString) -> (a -> Text) -> a -> JSONString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
TLE.decodeUtf8 (ByteString -> Text) -> (a -> ByteString) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ByteString
forall a. ToJSON a => a -> ByteString
encode

decodeJSON :: (FromJSON a) => JSONString -> Maybe a
decodeJSON :: forall a. FromJSON a => JSONString -> Maybe a
decodeJSON = ByteString -> Maybe a
forall a. FromJSON a => ByteString -> Maybe a
decode (ByteString -> Maybe a)
-> (JSONString -> ByteString) -> JSONString -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TLE.encodeUtf8 (Text -> ByteString)
-> (JSONString -> Text) -> JSONString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JSONString -> Text
unJSONString

decodeJSONEither :: (FromJSON a) => JSONString -> Either String a
decodeJSONEither :: forall a. FromJSON a => JSONString -> Either String a
decodeJSONEither = ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
eitherDecode (ByteString -> Either String a)
-> (JSONString -> ByteString) -> JSONString -> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TLE.encodeUtf8 (Text -> ByteString)
-> (JSONString -> Text) -> JSONString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JSONString -> Text
unJSONString