{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleContexts, AllowAmbiguousTypes, UndecidableInstances, FlexibleInstances, DataKinds, PolyKinds, TypeApplications, ScopedTypeVariables, ConstraintKinds, TypeOperators, GADTs, GeneralizedNewtypeDeriving #-}
module IHP.ModelSupport.Types
(
ModelContext (..)
, RowLevelSecurityContext (..)
, TransactionRunner (..)
, GetModelById
, GetTableName
, GetModelByTableName
, PrimaryKey
, GetModelName
, Include
, Include'
, NormalizeModel
, Id'(..)
, Id
, MetaBag (..)
, Violation (..)
, FieldName
, FieldWithDefault (..)
, FieldWithUpdate (..)
, LabeledData (..)
, RecordNotFoundException (..)
, EnhancedSqlError (..)
, enhancedSqlErrorMessage
, HasqlSessionError (..)
, CanCreate (..)
, CanUpdate (..)
, ParsePrimaryKey (..)
) where
import Prelude
import Data.ByteString (ByteString)
import Data.Text (Text)
import qualified Data.Text.Encoding
import Data.Hashable (Hashable)
import Control.DeepSeq (NFData)
import Control.Exception (Exception)
import Database.PostgreSQL.Simple.Types (Query)
import qualified Database.PostgreSQL.Simple as PG
import qualified Hasql.Pool as Hasql
import qualified Hasql.Session as HasqlSession
import qualified Hasql.Errors as HasqlErrors
import GHC.TypeLits
import GHC.Types
import Data.Data
import Data.Dynamic
import IHP.Log.Types (Logger)
newtype TransactionRunner = TransactionRunner
{ TransactionRunner -> forall a. Session a -> IO a
runInTransaction :: forall a. HasqlSession.Session a -> IO a }
data HasqlSessionError = HasqlSessionError HasqlErrors.SessionError
deriving (Int -> HasqlSessionError -> ShowS
[HasqlSessionError] -> ShowS
HasqlSessionError -> String
(Int -> HasqlSessionError -> ShowS)
-> (HasqlSessionError -> String)
-> ([HasqlSessionError] -> ShowS)
-> Show HasqlSessionError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HasqlSessionError -> ShowS
showsPrec :: Int -> HasqlSessionError -> ShowS
$cshow :: HasqlSessionError -> String
show :: HasqlSessionError -> String
$cshowList :: [HasqlSessionError] -> ShowS
showList :: [HasqlSessionError] -> ShowS
Show)
instance Exception HasqlSessionError
data ModelContext = ModelContext
{ ModelContext -> Pool
hasqlPool :: Hasql.Pool
, ModelContext -> Maybe TransactionRunner
transactionRunner :: Maybe TransactionRunner
, ModelContext -> Logger
logger :: Logger
, ModelContext -> Maybe (Text -> IO ())
trackTableReadCallback :: Maybe (Text -> IO ())
, ModelContext -> Maybe RowLevelSecurityContext
rowLevelSecurity :: Maybe RowLevelSecurityContext
}
data RowLevelSecurityContext = RowLevelSecurityContext
{ RowLevelSecurityContext -> Text
rlsAuthenticatedRole :: Text
, RowLevelSecurityContext -> Text
rlsUserId :: Text
}
type family GetModelById id :: Type where
GetModelById (Maybe (Id' tableName)) = Maybe (GetModelByTableName tableName)
GetModelById (Id' tableName) = GetModelByTableName tableName
type family GetTableName model :: Symbol
type family GetModelByTableName (tableName :: Symbol) :: Type
type family PrimaryKey (tableName :: Symbol)
type family GetModelName model :: Symbol
type family Include (name :: GHC.Types.Symbol) model
type family Include' (name :: [GHC.Types.Symbol]) model where
Include' '[] model = model
Include' (x:xs) model = Include' xs (Include x model)
type NormalizeModel model = GetModelByTableName (GetTableName model)
newtype Id' table = Id (PrimaryKey table)
deriving instance (Eq (PrimaryKey table)) => Eq (Id' table)
deriving instance (Ord (PrimaryKey table)) => Ord (Id' table)
deriving instance (Hashable (PrimaryKey table)) => Hashable (Id' table)
deriving instance (KnownSymbol table, Data (PrimaryKey table)) => Data (Id' table)
deriving instance (KnownSymbol table, NFData (PrimaryKey table)) => NFData (Id' table)
type Id model = Id' (GetTableName model)
type FieldName = ByteString
data Violation
= TextViolation { Violation -> Text
message :: !Text }
| HtmlViolation { message :: !Text }
deriving (Violation -> Violation -> Bool
(Violation -> Violation -> Bool)
-> (Violation -> Violation -> Bool) -> Eq Violation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Violation -> Violation -> Bool
== :: Violation -> Violation -> Bool
$c/= :: Violation -> Violation -> Bool
/= :: Violation -> Violation -> Bool
Eq, Int -> Violation -> ShowS
[Violation] -> ShowS
Violation -> String
(Int -> Violation -> ShowS)
-> (Violation -> String)
-> ([Violation] -> ShowS)
-> Show Violation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Violation -> ShowS
showsPrec :: Int -> Violation -> ShowS
$cshow :: Violation -> String
show :: Violation -> String
$cshowList :: [Violation] -> ShowS
showList :: [Violation] -> ShowS
Show)
data MetaBag = MetaBag
{ MetaBag -> [(Text, Violation)]
annotations :: ![(Text, Violation)]
, MetaBag -> [Text]
touchedFields :: ![Text]
, MetaBag -> Maybe Dynamic
originalDatabaseRecord :: Maybe Dynamic
} deriving (Int -> MetaBag -> ShowS
[MetaBag] -> ShowS
MetaBag -> String
(Int -> MetaBag -> ShowS)
-> (MetaBag -> String) -> ([MetaBag] -> ShowS) -> Show MetaBag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MetaBag -> ShowS
showsPrec :: Int -> MetaBag -> ShowS
$cshow :: MetaBag -> String
show :: MetaBag -> String
$cshowList :: [MetaBag] -> ShowS
showList :: [MetaBag] -> ShowS
Show)
instance Eq MetaBag where
MetaBag { [(Text, Violation)]
annotations :: MetaBag -> [(Text, Violation)]
annotations :: [(Text, Violation)]
annotations, [Text]
touchedFields :: MetaBag -> [Text]
touchedFields :: [Text]
touchedFields } == :: MetaBag -> MetaBag -> Bool
== MetaBag { annotations :: MetaBag -> [(Text, Violation)]
annotations = [(Text, Violation)]
annotations', touchedFields :: MetaBag -> [Text]
touchedFields = [Text]
touchedFields' } = [(Text, Violation)]
annotations [(Text, Violation)] -> [(Text, Violation)] -> Bool
forall a. Eq a => a -> a -> Bool
== [(Text, Violation)]
annotations' Bool -> Bool -> Bool
&& [Text]
touchedFields [Text] -> [Text] -> Bool
forall a. Eq a => a -> a -> Bool
== [Text]
touchedFields'
data FieldWithDefault valueType = Default | NonDefault valueType deriving (FieldWithDefault valueType -> FieldWithDefault valueType -> Bool
(FieldWithDefault valueType -> FieldWithDefault valueType -> Bool)
-> (FieldWithDefault valueType
-> FieldWithDefault valueType -> Bool)
-> Eq (FieldWithDefault valueType)
forall valueType.
Eq valueType =>
FieldWithDefault valueType -> FieldWithDefault valueType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall valueType.
Eq valueType =>
FieldWithDefault valueType -> FieldWithDefault valueType -> Bool
== :: FieldWithDefault valueType -> FieldWithDefault valueType -> Bool
$c/= :: forall valueType.
Eq valueType =>
FieldWithDefault valueType -> FieldWithDefault valueType -> Bool
/= :: FieldWithDefault valueType -> FieldWithDefault valueType -> Bool
Eq, Int -> FieldWithDefault valueType -> ShowS
[FieldWithDefault valueType] -> ShowS
FieldWithDefault valueType -> String
(Int -> FieldWithDefault valueType -> ShowS)
-> (FieldWithDefault valueType -> String)
-> ([FieldWithDefault valueType] -> ShowS)
-> Show (FieldWithDefault valueType)
forall valueType.
Show valueType =>
Int -> FieldWithDefault valueType -> ShowS
forall valueType.
Show valueType =>
[FieldWithDefault valueType] -> ShowS
forall valueType.
Show valueType =>
FieldWithDefault valueType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall valueType.
Show valueType =>
Int -> FieldWithDefault valueType -> ShowS
showsPrec :: Int -> FieldWithDefault valueType -> ShowS
$cshow :: forall valueType.
Show valueType =>
FieldWithDefault valueType -> String
show :: FieldWithDefault valueType -> String
$cshowList :: forall valueType.
Show valueType =>
[FieldWithDefault valueType] -> ShowS
showList :: [FieldWithDefault valueType] -> ShowS
Show)
data FieldWithUpdate name value
= NoUpdate (Proxy name)
| Update value
deriving (FieldWithUpdate name value -> FieldWithUpdate name value -> Bool
(FieldWithUpdate name value -> FieldWithUpdate name value -> Bool)
-> (FieldWithUpdate name value
-> FieldWithUpdate name value -> Bool)
-> Eq (FieldWithUpdate name value)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k (name :: k) value.
Eq value =>
FieldWithUpdate name value -> FieldWithUpdate name value -> Bool
$c== :: forall k (name :: k) value.
Eq value =>
FieldWithUpdate name value -> FieldWithUpdate name value -> Bool
== :: FieldWithUpdate name value -> FieldWithUpdate name value -> Bool
$c/= :: forall k (name :: k) value.
Eq value =>
FieldWithUpdate name value -> FieldWithUpdate name value -> Bool
/= :: FieldWithUpdate name value -> FieldWithUpdate name value -> Bool
Eq, Int -> FieldWithUpdate name value -> ShowS
[FieldWithUpdate name value] -> ShowS
FieldWithUpdate name value -> String
(Int -> FieldWithUpdate name value -> ShowS)
-> (FieldWithUpdate name value -> String)
-> ([FieldWithUpdate name value] -> ShowS)
-> Show (FieldWithUpdate name value)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall k (name :: k) value.
Show value =>
Int -> FieldWithUpdate name value -> ShowS
forall k (name :: k) value.
Show value =>
[FieldWithUpdate name value] -> ShowS
forall k (name :: k) value.
Show value =>
FieldWithUpdate name value -> String
$cshowsPrec :: forall k (name :: k) value.
Show value =>
Int -> FieldWithUpdate name value -> ShowS
showsPrec :: Int -> FieldWithUpdate name value -> ShowS
$cshow :: forall k (name :: k) value.
Show value =>
FieldWithUpdate name value -> String
show :: FieldWithUpdate name value -> String
$cshowList :: forall k (name :: k) value.
Show value =>
[FieldWithUpdate name value] -> ShowS
showList :: [FieldWithUpdate name value] -> ShowS
Show)
data LabeledData a b = LabeledData { forall a b. LabeledData a b -> a
labelValue :: a, forall a b. LabeledData a b -> b
contentValue :: b }
deriving (Int -> LabeledData a b -> ShowS
[LabeledData a b] -> ShowS
LabeledData a b -> String
(Int -> LabeledData a b -> ShowS)
-> (LabeledData a b -> String)
-> ([LabeledData a b] -> ShowS)
-> Show (LabeledData a b)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall a b. (Show a, Show b) => Int -> LabeledData a b -> ShowS
forall a b. (Show a, Show b) => [LabeledData a b] -> ShowS
forall a b. (Show a, Show b) => LabeledData a b -> String
$cshowsPrec :: forall a b. (Show a, Show b) => Int -> LabeledData a b -> ShowS
showsPrec :: Int -> LabeledData a b -> ShowS
$cshow :: forall a b. (Show a, Show b) => LabeledData a b -> String
show :: LabeledData a b -> String
$cshowList :: forall a b. (Show a, Show b) => [LabeledData a b] -> ShowS
showList :: [LabeledData a b] -> ShowS
Show)
data RecordNotFoundException
= RecordNotFoundException { RecordNotFoundException -> Text
queryAndParams :: Text }
deriving (Int -> RecordNotFoundException -> ShowS
[RecordNotFoundException] -> ShowS
RecordNotFoundException -> String
(Int -> RecordNotFoundException -> ShowS)
-> (RecordNotFoundException -> String)
-> ([RecordNotFoundException] -> ShowS)
-> Show RecordNotFoundException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RecordNotFoundException -> ShowS
showsPrec :: Int -> RecordNotFoundException -> ShowS
$cshow :: RecordNotFoundException -> String
show :: RecordNotFoundException -> String
$cshowList :: [RecordNotFoundException] -> ShowS
showList :: [RecordNotFoundException] -> ShowS
Show)
instance Exception RecordNotFoundException
data EnhancedSqlError
= EnhancedSqlError
{ EnhancedSqlError -> Query
sqlErrorQuery :: Query
, EnhancedSqlError -> Text
sqlErrorQueryParams :: Text
, EnhancedSqlError -> SqlError
sqlError :: PG.SqlError
} deriving (Int -> EnhancedSqlError -> ShowS
[EnhancedSqlError] -> ShowS
EnhancedSqlError -> String
(Int -> EnhancedSqlError -> ShowS)
-> (EnhancedSqlError -> String)
-> ([EnhancedSqlError] -> ShowS)
-> Show EnhancedSqlError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EnhancedSqlError -> ShowS
showsPrec :: Int -> EnhancedSqlError -> ShowS
$cshow :: EnhancedSqlError -> String
show :: EnhancedSqlError -> String
$cshowList :: [EnhancedSqlError] -> ShowS
showList :: [EnhancedSqlError] -> ShowS
Show)
instance Exception EnhancedSqlError
enhancedSqlErrorMessage :: EnhancedSqlError -> Text
enhancedSqlErrorMessage :: EnhancedSqlError -> Text
enhancedSqlErrorMessage EnhancedSqlError
e = ByteString -> Text
Data.Text.Encoding.decodeUtf8 EnhancedSqlError
e.sqlError.sqlErrorMsg
{-# INLINE enhancedSqlErrorMessage #-}
class CanCreate a where
create :: (?modelContext :: ModelContext) => a -> IO a
createMany :: (?modelContext :: ModelContext) => [a] -> IO [a]
createRecordDiscardResult :: (?modelContext :: ModelContext) => a -> IO ()
createRecordDiscardResult a
record = do
_ <- a -> IO a
forall a. (CanCreate a, ?modelContext::ModelContext) => a -> IO a
create a
record
pure ()
class CanUpdate a where
updateRecord :: (?modelContext :: ModelContext) => a -> IO a
updateRecordDiscardResult :: (?modelContext :: ModelContext) => a -> IO ()
updateRecordDiscardResult a
record = do
_ <- a -> IO a
forall a. (CanUpdate a, ?modelContext::ModelContext) => a -> IO a
updateRecord a
record
pure ()
class ParsePrimaryKey primaryKey where
parsePrimaryKey :: Text -> Maybe primaryKey