{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Test.Hindsight.Store.Common where

import Data.Aeson (FromJSON, ToJSON)
import Data.Proxy (Proxy (..))
import Data.Text (Text, pack)
import GHC.Generics (Generic)
import Hindsight.Events
import Test.Hindsight.Examples
import Test.QuickCheck (Arbitrary (..))
import Test.QuickCheck.Instances.Text ()

-- | Tombstone event used to signal end of test data
type Tombstone = "tombstone"

-- | Simple payload for tombstone event
data TombstonePayload = TombstonePayload
    {TombstonePayload -> Text
marker :: Text}
    deriving stock (Int -> TombstonePayload -> ShowS
[TombstonePayload] -> ShowS
TombstonePayload -> String
(Int -> TombstonePayload -> ShowS)
-> (TombstonePayload -> String)
-> ([TombstonePayload] -> ShowS)
-> Show TombstonePayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TombstonePayload -> ShowS
showsPrec :: Int -> TombstonePayload -> ShowS
$cshow :: TombstonePayload -> String
show :: TombstonePayload -> String
$cshowList :: [TombstonePayload] -> ShowS
showList :: [TombstonePayload] -> ShowS
Show, TombstonePayload -> TombstonePayload -> Bool
(TombstonePayload -> TombstonePayload -> Bool)
-> (TombstonePayload -> TombstonePayload -> Bool)
-> Eq TombstonePayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TombstonePayload -> TombstonePayload -> Bool
== :: TombstonePayload -> TombstonePayload -> Bool
$c/= :: TombstonePayload -> TombstonePayload -> Bool
/= :: TombstonePayload -> TombstonePayload -> Bool
Eq, (forall x. TombstonePayload -> Rep TombstonePayload x)
-> (forall x. Rep TombstonePayload x -> TombstonePayload)
-> Generic TombstonePayload
forall x. Rep TombstonePayload x -> TombstonePayload
forall x. TombstonePayload -> Rep TombstonePayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TombstonePayload -> Rep TombstonePayload x
from :: forall x. TombstonePayload -> Rep TombstonePayload x
$cto :: forall x. Rep TombstonePayload x -> TombstonePayload
to :: forall x. Rep TombstonePayload x -> TombstonePayload
Generic)
    deriving anyclass (Maybe TombstonePayload
Value -> Parser [TombstonePayload]
Value -> Parser TombstonePayload
(Value -> Parser TombstonePayload)
-> (Value -> Parser [TombstonePayload])
-> Maybe TombstonePayload
-> FromJSON TombstonePayload
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser TombstonePayload
parseJSON :: Value -> Parser TombstonePayload
$cparseJSONList :: Value -> Parser [TombstonePayload]
parseJSONList :: Value -> Parser [TombstonePayload]
$comittedField :: Maybe TombstonePayload
omittedField :: Maybe TombstonePayload
FromJSON, [TombstonePayload] -> Value
[TombstonePayload] -> Encoding
TombstonePayload -> Bool
TombstonePayload -> Value
TombstonePayload -> Encoding
(TombstonePayload -> Value)
-> (TombstonePayload -> Encoding)
-> ([TombstonePayload] -> Value)
-> ([TombstonePayload] -> Encoding)
-> (TombstonePayload -> Bool)
-> ToJSON TombstonePayload
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: TombstonePayload -> Value
toJSON :: TombstonePayload -> Value
$ctoEncoding :: TombstonePayload -> Encoding
toEncoding :: TombstonePayload -> Encoding
$ctoJSONList :: [TombstonePayload] -> Value
toJSONList :: [TombstonePayload] -> Value
$ctoEncodingList :: [TombstonePayload] -> Encoding
toEncodingList :: [TombstonePayload] -> Encoding
$comitField :: TombstonePayload -> Bool
omitField :: TombstonePayload -> Bool
ToJSON)

instance Arbitrary TombstonePayload where
    arbitrary :: Gen TombstonePayload
arbitrary = Text -> TombstonePayload
TombstonePayload (Text -> TombstonePayload) -> Gen Text -> Gen TombstonePayload
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Text
forall a. Arbitrary a => Gen a
arbitrary

-- | Event definition for tombstone event (single version)
type instance MaxVersion Tombstone = 0

type instance Versions Tombstone = '[TombstonePayload]

instance Event Tombstone

-- | No upgrade needed for single version (uses default identity)
instance MigrateVersion 0 Tombstone

-- | Helper to create a test user event
makeUserEvent :: Int -> SomeLatestEvent
makeUserEvent :: Int -> SomeLatestEvent
makeUserEvent Int
userId =
    Proxy UserCreated
-> CurrentPayloadType UserCreated -> SomeLatestEvent
forall (event :: Symbol).
Event event =>
Proxy event -> CurrentPayloadType event -> SomeLatestEvent
SomeLatestEvent (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @UserCreated) (CurrentPayloadType UserCreated -> SomeLatestEvent)
-> CurrentPayloadType UserCreated -> SomeLatestEvent
forall a b. (a -> b) -> a -> b
$
        UserInformation2
            { userId :: Int
userId = Int
userId
            , userName :: Text
userName = Text
"user" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Int -> String
forall a. Show a => a -> String
show Int
userId)
            , userEmail :: Maybe Text
userEmail = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"user" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Int -> String
forall a. Show a => a -> String
show Int
userId) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"@test.com"
            , likeability :: Int
likeability = Int
10
            }

-- | Helper to create a tombstone event
makeTombstone :: SomeLatestEvent
makeTombstone :: SomeLatestEvent
makeTombstone =
    Proxy Tombstone -> CurrentPayloadType Tombstone -> SomeLatestEvent
forall (event :: Symbol).
Event event =>
Proxy event -> CurrentPayloadType event -> SomeLatestEvent
SomeLatestEvent
        (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @Tombstone)
        TombstonePayload
            { marker :: Text
marker = Text
"end_of_test"
            }

-- | Counter increment event for testing subscription stop behavior
type CounterInc = "counter_inc"

data CounterIncPayload = CounterIncPayload
    deriving stock (Int -> CounterIncPayload -> ShowS
[CounterIncPayload] -> ShowS
CounterIncPayload -> String
(Int -> CounterIncPayload -> ShowS)
-> (CounterIncPayload -> String)
-> ([CounterIncPayload] -> ShowS)
-> Show CounterIncPayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CounterIncPayload -> ShowS
showsPrec :: Int -> CounterIncPayload -> ShowS
$cshow :: CounterIncPayload -> String
show :: CounterIncPayload -> String
$cshowList :: [CounterIncPayload] -> ShowS
showList :: [CounterIncPayload] -> ShowS
Show, CounterIncPayload -> CounterIncPayload -> Bool
(CounterIncPayload -> CounterIncPayload -> Bool)
-> (CounterIncPayload -> CounterIncPayload -> Bool)
-> Eq CounterIncPayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CounterIncPayload -> CounterIncPayload -> Bool
== :: CounterIncPayload -> CounterIncPayload -> Bool
$c/= :: CounterIncPayload -> CounterIncPayload -> Bool
/= :: CounterIncPayload -> CounterIncPayload -> Bool
Eq, (forall x. CounterIncPayload -> Rep CounterIncPayload x)
-> (forall x. Rep CounterIncPayload x -> CounterIncPayload)
-> Generic CounterIncPayload
forall x. Rep CounterIncPayload x -> CounterIncPayload
forall x. CounterIncPayload -> Rep CounterIncPayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CounterIncPayload -> Rep CounterIncPayload x
from :: forall x. CounterIncPayload -> Rep CounterIncPayload x
$cto :: forall x. Rep CounterIncPayload x -> CounterIncPayload
to :: forall x. Rep CounterIncPayload x -> CounterIncPayload
Generic)
    deriving anyclass (Maybe CounterIncPayload
Value -> Parser [CounterIncPayload]
Value -> Parser CounterIncPayload
(Value -> Parser CounterIncPayload)
-> (Value -> Parser [CounterIncPayload])
-> Maybe CounterIncPayload
-> FromJSON CounterIncPayload
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser CounterIncPayload
parseJSON :: Value -> Parser CounterIncPayload
$cparseJSONList :: Value -> Parser [CounterIncPayload]
parseJSONList :: Value -> Parser [CounterIncPayload]
$comittedField :: Maybe CounterIncPayload
omittedField :: Maybe CounterIncPayload
FromJSON, [CounterIncPayload] -> Value
[CounterIncPayload] -> Encoding
CounterIncPayload -> Bool
CounterIncPayload -> Value
CounterIncPayload -> Encoding
(CounterIncPayload -> Value)
-> (CounterIncPayload -> Encoding)
-> ([CounterIncPayload] -> Value)
-> ([CounterIncPayload] -> Encoding)
-> (CounterIncPayload -> Bool)
-> ToJSON CounterIncPayload
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: CounterIncPayload -> Value
toJSON :: CounterIncPayload -> Value
$ctoEncoding :: CounterIncPayload -> Encoding
toEncoding :: CounterIncPayload -> Encoding
$ctoJSONList :: [CounterIncPayload] -> Value
toJSONList :: [CounterIncPayload] -> Value
$ctoEncodingList :: [CounterIncPayload] -> Encoding
toEncodingList :: [CounterIncPayload] -> Encoding
$comitField :: CounterIncPayload -> Bool
omitField :: CounterIncPayload -> Bool
ToJSON)

instance Arbitrary CounterIncPayload where
    arbitrary :: Gen CounterIncPayload
arbitrary = CounterIncPayload -> Gen CounterIncPayload
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CounterIncPayload
CounterIncPayload

type instance MaxVersion CounterInc = 0
type instance Versions CounterInc = '[CounterIncPayload]
instance Event CounterInc
instance MigrateVersion 0 CounterInc

-- | Counter stop event for testing subscription stop behavior
type CounterStop = "counter_stop"

data CounterStopPayload = CounterStopPayload
    deriving stock (Int -> CounterStopPayload -> ShowS
[CounterStopPayload] -> ShowS
CounterStopPayload -> String
(Int -> CounterStopPayload -> ShowS)
-> (CounterStopPayload -> String)
-> ([CounterStopPayload] -> ShowS)
-> Show CounterStopPayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CounterStopPayload -> ShowS
showsPrec :: Int -> CounterStopPayload -> ShowS
$cshow :: CounterStopPayload -> String
show :: CounterStopPayload -> String
$cshowList :: [CounterStopPayload] -> ShowS
showList :: [CounterStopPayload] -> ShowS
Show, CounterStopPayload -> CounterStopPayload -> Bool
(CounterStopPayload -> CounterStopPayload -> Bool)
-> (CounterStopPayload -> CounterStopPayload -> Bool)
-> Eq CounterStopPayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CounterStopPayload -> CounterStopPayload -> Bool
== :: CounterStopPayload -> CounterStopPayload -> Bool
$c/= :: CounterStopPayload -> CounterStopPayload -> Bool
/= :: CounterStopPayload -> CounterStopPayload -> Bool
Eq, (forall x. CounterStopPayload -> Rep CounterStopPayload x)
-> (forall x. Rep CounterStopPayload x -> CounterStopPayload)
-> Generic CounterStopPayload
forall x. Rep CounterStopPayload x -> CounterStopPayload
forall x. CounterStopPayload -> Rep CounterStopPayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CounterStopPayload -> Rep CounterStopPayload x
from :: forall x. CounterStopPayload -> Rep CounterStopPayload x
$cto :: forall x. Rep CounterStopPayload x -> CounterStopPayload
to :: forall x. Rep CounterStopPayload x -> CounterStopPayload
Generic)
    deriving anyclass (Maybe CounterStopPayload
Value -> Parser [CounterStopPayload]
Value -> Parser CounterStopPayload
(Value -> Parser CounterStopPayload)
-> (Value -> Parser [CounterStopPayload])
-> Maybe CounterStopPayload
-> FromJSON CounterStopPayload
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser CounterStopPayload
parseJSON :: Value -> Parser CounterStopPayload
$cparseJSONList :: Value -> Parser [CounterStopPayload]
parseJSONList :: Value -> Parser [CounterStopPayload]
$comittedField :: Maybe CounterStopPayload
omittedField :: Maybe CounterStopPayload
FromJSON, [CounterStopPayload] -> Value
[CounterStopPayload] -> Encoding
CounterStopPayload -> Bool
CounterStopPayload -> Value
CounterStopPayload -> Encoding
(CounterStopPayload -> Value)
-> (CounterStopPayload -> Encoding)
-> ([CounterStopPayload] -> Value)
-> ([CounterStopPayload] -> Encoding)
-> (CounterStopPayload -> Bool)
-> ToJSON CounterStopPayload
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: CounterStopPayload -> Value
toJSON :: CounterStopPayload -> Value
$ctoEncoding :: CounterStopPayload -> Encoding
toEncoding :: CounterStopPayload -> Encoding
$ctoJSONList :: [CounterStopPayload] -> Value
toJSONList :: [CounterStopPayload] -> Value
$ctoEncodingList :: [CounterStopPayload] -> Encoding
toEncodingList :: [CounterStopPayload] -> Encoding
$comitField :: CounterStopPayload -> Bool
omitField :: CounterStopPayload -> Bool
ToJSON)

instance Arbitrary CounterStopPayload where
    arbitrary :: Gen CounterStopPayload
arbitrary = CounterStopPayload -> Gen CounterStopPayload
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CounterStopPayload
CounterStopPayload

type instance MaxVersion CounterStop = 0
type instance Versions CounterStop = '[CounterStopPayload]
instance Event CounterStop
instance MigrateVersion 0 CounterStop

-- | Helper to create a counter increment event
makeCounterInc :: SomeLatestEvent
makeCounterInc :: SomeLatestEvent
makeCounterInc =
    Proxy CounterInc
-> CurrentPayloadType CounterInc -> SomeLatestEvent
forall (event :: Symbol).
Event event =>
Proxy event -> CurrentPayloadType event -> SomeLatestEvent
SomeLatestEvent
        (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @CounterInc)
        CurrentPayloadType CounterInc
CounterIncPayload
CounterIncPayload

-- | Helper to create a counter stop event
makeCounterStop :: SomeLatestEvent
makeCounterStop :: SomeLatestEvent
makeCounterStop =
    Proxy CounterStop
-> CurrentPayloadType CounterStop -> SomeLatestEvent
forall (event :: Symbol).
Event event =>
Proxy event -> CurrentPayloadType event -> SomeLatestEvent
SomeLatestEvent
        (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @CounterStop)
        CurrentPayloadType CounterStop
CounterStopPayload
CounterStopPayload

-- | Counter fail event for testing exception handling
type CounterFail = "counter_fail"

data CounterFailPayload = CounterFailPayload
    deriving stock (Int -> CounterFailPayload -> ShowS
[CounterFailPayload] -> ShowS
CounterFailPayload -> String
(Int -> CounterFailPayload -> ShowS)
-> (CounterFailPayload -> String)
-> ([CounterFailPayload] -> ShowS)
-> Show CounterFailPayload
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CounterFailPayload -> ShowS
showsPrec :: Int -> CounterFailPayload -> ShowS
$cshow :: CounterFailPayload -> String
show :: CounterFailPayload -> String
$cshowList :: [CounterFailPayload] -> ShowS
showList :: [CounterFailPayload] -> ShowS
Show, CounterFailPayload -> CounterFailPayload -> Bool
(CounterFailPayload -> CounterFailPayload -> Bool)
-> (CounterFailPayload -> CounterFailPayload -> Bool)
-> Eq CounterFailPayload
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CounterFailPayload -> CounterFailPayload -> Bool
== :: CounterFailPayload -> CounterFailPayload -> Bool
$c/= :: CounterFailPayload -> CounterFailPayload -> Bool
/= :: CounterFailPayload -> CounterFailPayload -> Bool
Eq, (forall x. CounterFailPayload -> Rep CounterFailPayload x)
-> (forall x. Rep CounterFailPayload x -> CounterFailPayload)
-> Generic CounterFailPayload
forall x. Rep CounterFailPayload x -> CounterFailPayload
forall x. CounterFailPayload -> Rep CounterFailPayload x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CounterFailPayload -> Rep CounterFailPayload x
from :: forall x. CounterFailPayload -> Rep CounterFailPayload x
$cto :: forall x. Rep CounterFailPayload x -> CounterFailPayload
to :: forall x. Rep CounterFailPayload x -> CounterFailPayload
Generic)
    deriving anyclass (Maybe CounterFailPayload
Value -> Parser [CounterFailPayload]
Value -> Parser CounterFailPayload
(Value -> Parser CounterFailPayload)
-> (Value -> Parser [CounterFailPayload])
-> Maybe CounterFailPayload
-> FromJSON CounterFailPayload
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser CounterFailPayload
parseJSON :: Value -> Parser CounterFailPayload
$cparseJSONList :: Value -> Parser [CounterFailPayload]
parseJSONList :: Value -> Parser [CounterFailPayload]
$comittedField :: Maybe CounterFailPayload
omittedField :: Maybe CounterFailPayload
FromJSON, [CounterFailPayload] -> Value
[CounterFailPayload] -> Encoding
CounterFailPayload -> Bool
CounterFailPayload -> Value
CounterFailPayload -> Encoding
(CounterFailPayload -> Value)
-> (CounterFailPayload -> Encoding)
-> ([CounterFailPayload] -> Value)
-> ([CounterFailPayload] -> Encoding)
-> (CounterFailPayload -> Bool)
-> ToJSON CounterFailPayload
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: CounterFailPayload -> Value
toJSON :: CounterFailPayload -> Value
$ctoEncoding :: CounterFailPayload -> Encoding
toEncoding :: CounterFailPayload -> Encoding
$ctoJSONList :: [CounterFailPayload] -> Value
toJSONList :: [CounterFailPayload] -> Value
$ctoEncodingList :: [CounterFailPayload] -> Encoding
toEncodingList :: [CounterFailPayload] -> Encoding
$comitField :: CounterFailPayload -> Bool
omitField :: CounterFailPayload -> Bool
ToJSON)

instance Arbitrary CounterFailPayload where
    arbitrary :: Gen CounterFailPayload
arbitrary = CounterFailPayload -> Gen CounterFailPayload
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CounterFailPayload
CounterFailPayload

type instance MaxVersion CounterFail = 0
type instance Versions CounterFail = '[CounterFailPayload]
instance Event CounterFail
instance MigrateVersion 0 CounterFail

-- | Helper to create a counter fail event
makeCounterFail :: SomeLatestEvent
makeCounterFail :: SomeLatestEvent
makeCounterFail =
    Proxy CounterFail
-> CurrentPayloadType CounterFail -> SomeLatestEvent
forall (event :: Symbol).
Event event =>
Proxy event -> CurrentPayloadType event -> SomeLatestEvent
SomeLatestEvent
        (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @CounterFail)
        CurrentPayloadType CounterFail
CounterFailPayload
CounterFailPayload