-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Core module for eventful
--   
--   Core module for eventful
@package eventful-core
@version 0.2.0

module Eventful.Serializer

-- | A <a>Serializer</a> describes the injective conversion between types
--   <tt>a</tt> and <tt>b</tt>. In plain English, this means that you can
--   go from <tt>a</tt> to <tt>b</tt>, and you can <a>Maybe</a> go from
--   <tt>b</tt> back to <tt>a</tt>. This is often used to serialize events
--   to an event store, and then deserialize them back.
data Serializer a b
Serializer :: (a -> b) -> (b -> Maybe a) -> (b -> Either String a) -> Serializer a b
[serialize] :: Serializer a b -> a -> b
[deserialize] :: Serializer a b -> b -> Maybe a

-- | Deserialize with additional information on failure
[deserializeEither] :: Serializer a b -> b -> Either String a

-- | Simple constructor to just use <a>deserialize</a> to construct
--   <a>deserializeEither</a>.
simpleSerializer :: (a -> b) -> (b -> Maybe a) -> Serializer a b

-- | Apply an intermediate <a>Serializer</a> to a serializer to go from
--   type <tt>a</tt> to <tt>c</tt> with <tt>b</tt> in the middle. Note that
--   with deserializing, if the conversion from <tt>c</tt> to <tt>b</tt> or
--   from <tt>b</tt> to <tt>a</tt> fails, the whole deserialization fails.
composeSerializers :: Serializer a b -> Serializer b c -> Serializer a c

-- | Simple "serializer" using <a>id</a>. Useful for when an API requires a
--   serializer but you don't need to actually change types.
idSerializer :: Serializer a a

-- | Uses <a>Traversable</a> to wrap a <a>Serializer</a>.
traverseSerializer :: (Traversable t) => Serializer a b -> Serializer (t a) (t b)

-- | A <a>Serializer</a> for aeson <a>Value</a>s.
jsonSerializer :: (ToJSON a, FromJSON a) => Serializer a Value

-- | A <a>Serializer</a> to convert JSON to/from lazy text. Useful for Sql
--   event stores that store JSON values as text.
jsonTextSerializer :: (ToJSON a, FromJSON a) => Serializer a Text

-- | A <a>Serializer</a> for <a>Dynamic</a> values using <a>toDyn</a> and
--   <a>fromDynamic</a>.
dynamicSerializer :: (Typeable a) => Serializer a Dynamic

-- | This is a type class for serializing sum types of events to
--   <a>Dynamic</a> without the associated constructor. This is useful when
--   transforming between two sum types of events. A common pattern is to
--   put all the events in an application in one big event sum type, and
--   then have a smaller sum type for each <tt>Projection</tt>. Then, you
--   can use <a>eventSumTypeSerializer</a> to transform between the two.
--   
--   It is meant to be derived with <a>Generic</a>. For example:
--   
--   <pre>
--   data EventA = EventA deriving (Show)
--   data EventB = EventB deriving (Show)
--   data EventC = EventC deriving (Show)
--   
--   data AllEvents
--     = AllEventsEventA EventA
--     | AllEventsEventB EventB
--     | AllEventsEventC EventC
--     deriving (Show, Generic)
--   
--   instance EventSumType AllEvents
--   
--   data MyEvents
--     = MyEventsEventA EventA
--     | MyEventsEventB EventB
--     deriving (Show, Generic)
--   
--   instance EventSumType MyEvents
--   </pre>
--   
--   Now we can serialize to <a>Dynamic</a> without a constructor tag:
--   
--   <pre>
--   &gt;&gt;&gt; eventToDyn (MyEventsEventA EventA)
--   &lt;&lt;EventA&gt;&gt;
--   </pre>
--   
--   We can also go from a <tt>MyEvents</tt> value to an <tt>AllEvents</tt>
--   value:
--   
--   <pre>
--   &gt;&gt;&gt; eventFromDyn (eventToDyn (MyEventsEventA EventA)) :: Maybe AllEvents
--   Just (AllEventsEventA EventA)
--   </pre>
class EventSumType a

-- | Convert an event to a <a>Dynamic</a> without the constructor tag
eventToDyn :: EventSumType a => a -> Dynamic

-- | Go from a <a>Dynamic</a> to an event with the constructor tag. Note,
--   this function is <tt>O(n)</tt> to the number of constructors.
eventFromDyn :: EventSumType a => Dynamic -> Maybe a

-- | Convert an event to a <a>Dynamic</a> without the constructor tag
eventToDyn :: (EventSumType a, Generic a, EventSumType' (Rep a)) => a -> Dynamic

-- | Go from a <a>Dynamic</a> to an event with the constructor tag. Note,
--   this function is <tt>O(n)</tt> to the number of constructors.
eventFromDyn :: (EventSumType a, Generic a, EventSumType' (Rep a)) => Dynamic -> Maybe a

-- | A <a>Serializer</a> from one <a>EventSumType</a> instance to another.
--   WARNING: If not all events in the source <a>EventSumType</a> are in
--   the <tt>serialized</tt> <a>EventSumType</a>, then this function will
--   be partial!
eventSumTypeSerializer :: (Typeable a, EventSumType a, EventSumType b) => Serializer a b
instance Eventful.Serializer.EventSumType' f => Eventful.Serializer.EventSumType' (GHC.Generics.M1 i t f)
instance (Eventful.Serializer.EventSumType' f, Eventful.Serializer.EventSumType' g) => Eventful.Serializer.EventSumType' (f GHC.Generics.:+: g)
instance Data.Typeable.Internal.Typeable c => Eventful.Serializer.EventSumType' (GHC.Generics.K1 GHC.Generics.R c)

module Eventful.Store.Queries

-- | This type defines how to query an event stream. It defines the stream
--   key and the start/stop points for the query.
data QueryRange key position
QueryRange :: key -> QueryStart position -> QueryLimit position -> QueryRange key position
[queryRangeKey] :: QueryRange key position -> key
[queryRangeStart] :: QueryRange key position -> QueryStart position
[queryRangeLimit] :: QueryRange key position -> QueryLimit position

-- | This type defines where an event store query starts.
data QueryStart position
StartFromBeginning :: QueryStart position
StartQueryAt :: position -> QueryStart position

-- | This type is used to limit the results of a query from an event store.
data QueryLimit position
NoQueryLimit :: QueryLimit position
MaxNumberOfEvents :: Int -> QueryLimit position
StopQueryAt :: position -> QueryLimit position
allEvents :: key -> QueryRange key position
eventsUntil :: key -> position -> QueryRange key position
eventsStartingAt :: key -> position -> QueryRange key position
eventsStartingAtUntil :: key -> position -> position -> QueryRange key position
eventsStartingAtTakeLimit :: key -> position -> Int -> QueryRange key position
instance (GHC.Classes.Eq position, GHC.Classes.Eq key) => GHC.Classes.Eq (Eventful.Store.Queries.QueryRange key position)
instance (GHC.Show.Show position, GHC.Show.Show key) => GHC.Show.Show (Eventful.Store.Queries.QueryRange key position)
instance GHC.Base.Functor Eventful.Store.Queries.QueryLimit
instance GHC.Classes.Eq position => GHC.Classes.Eq (Eventful.Store.Queries.QueryLimit position)
instance GHC.Show.Show position => GHC.Show.Show (Eventful.Store.Queries.QueryLimit position)
instance GHC.Base.Functor Eventful.Store.Queries.QueryStart
instance GHC.Classes.Eq position => GHC.Classes.Eq (Eventful.Store.Queries.QueryStart position)
instance GHC.Show.Show position => GHC.Show.Show (Eventful.Store.Queries.QueryStart position)

module Eventful.TH.SumTypeSerializer

-- | This is a template haskell function that creates a <tt>Serializer</tt>
--   between two sum types. The first sum type must be a subset of the
--   second sum type. This is useful in situations where you define all the
--   events in your system in one type, and you want to create sum types
--   that are subsets for each <tt>Projection</tt>.
--   
--   For example, assume we have the following three event types and two
--   sum types holding these events:
--   
--   <pre>
--   data EventA = EventA
--   data EventB = EventB
--   data EventC = EventC
--   
--   data AllEvents
--     = AllEventsEventA EventA
--     | AllEventsEventB EventB
--     | AllEventsEventC EventC
--   
--   data MyEvents
--     = MyEventsEventA EventA
--     | MyEventsEventB EventB
--   </pre>
--   
--   In this case, <tt>AllEvents</tt> holds all the events in our system,
--   and <tt>MyEvents</tt> holds some subset of <tt>AllEvents</tt>. If we
--   run
--   
--   <pre>
--   mkSumTypeSerializer "myEventsSerializer" ''MyEvents ''AllEvents
--   </pre>
--   
--   we will produce the following code:
--   
--   <pre>
--   -- Serialization function
--   myEventsToAllEvents :: MyEvents -&gt; AllEvents
--   myEventsToAllEvents (MyEventsEventA e) = AllEventsEventA e
--   myEventsToAllEvents (MyEventsEventB e) = AllEventsEventB e
--   
--   -- Deserialization function
--   allEventsToMyEvents :: AllEvents -&gt; Maybe MyEvents
--   allEventsToMyEvents (AllEventsEventA e) = Just (MyEventsEventA e)
--   allEventsToMyEvents (AllEventsEventB e) = Just (MyEventsEventB e)
--   allEventsToMyEvents _ = Nothing
--   
--   -- Serializer
--   myEventsSerializer :: Serializer MyEvents AllEvents
--   myEventsSerializer = simpleSerializer myEventsToAllEvents allEventsToMyEvents
--   </pre>
mkSumTypeSerializer :: String -> Name -> Name -> Q [Dec]


-- | This module contains orphan <a>UUID</a> instances and a few
--   convenience functions around UUIDs. It would be great if this were its
--   own entirely separate package.
module Eventful.UUID

-- | The UUID type. A <a>Random</a> instance is provided which produces
--   version 4 UUIDs as specified in RFC 4122. The <a>Storable</a> and
--   <a>Binary</a> instances are compatible with RFC 4122, storing the
--   fields in network order as 16 bytes.
data UUID :: *
uuidFromText :: Text -> Maybe UUID
uuidToText :: UUID -> Text

-- | The nil UUID, as defined in RFC 4122. It is a UUID of all zeros.
--   <tt><a>null</a> u</tt> iff <tt><tt>u</tt> == <a>nil</a></tt>.
nil :: UUID
uuidNextRandom :: IO UUID

-- | Constructs a valid <a>UUID</a> from an <a>Integer</a> by padding with
--   zeros. Useful for testing.
--   
--   <pre>
--   &gt;&gt;&gt; uuidFromInteger 1
--   00000000-0000-0000-0000-000000000001
--   </pre>
uuidFromInteger :: Integer -> UUID
instance Web.PathPieces.PathPiece Data.UUID.Types.Internal.UUID

module Eventful.Store.Class

-- | An <a>EventStoreReader</a> is a function to query a stream from an
--   event store. It operates in some monad <tt>m</tt> and returns events
--   of type <tt>event</tt> from a stream at <tt>key</tt> ordered by
--   <tt>position</tt>.
newtype EventStoreReader key position m event
EventStoreReader :: (QueryRange key position -> m [event]) -> EventStoreReader key position m event
[getEvents] :: EventStoreReader key position m event -> QueryRange key position -> m [event]

-- | An <a>EventStoreWriter</a> is a function to write some events of type
--   <tt>event</tt> to an event store in some monad <tt>m</tt>.
newtype EventStoreWriter m event
EventStoreWriter :: (ExpectedVersion -> UUID -> [event] -> m (Maybe EventWriteError)) -> EventStoreWriter m event
[storeEvents] :: EventStoreWriter m event -> ExpectedVersion -> UUID -> [event] -> m (Maybe EventWriteError)
type VersionedEventStoreReader m event = EventStoreReader UUID EventVersion m (VersionedStreamEvent event)
type GlobalEventStoreReader m event = EventStoreReader () SequenceNumber m (GlobalStreamEvent event)

-- | An event along with the <tt>key</tt> for the event stream it is from
--   and its <tt>position</tt> in that event stream.
data StreamEvent key position event
StreamEvent :: !key -> !position -> !event -> StreamEvent key position event
[streamEventKey] :: StreamEvent key position event -> !key
[streamEventPosition] :: StreamEvent key position event -> !position
[streamEventEvent] :: StreamEvent key position event -> !event
type VersionedStreamEvent event = StreamEvent UUID EventVersion event
type GlobalStreamEvent event = StreamEvent () SequenceNumber (VersionedStreamEvent event)

-- | ExpectedVersion is used to assert the event stream is at a certain
--   version number. This is used when multiple writers are concurrently
--   writing to the event store. If the expected version is incorrect, then
--   storing fails.
data ExpectedVersion

-- | Used when the writer doesn't care what version the stream is at.
AnyVersion :: ExpectedVersion

-- | The stream shouldn't exist yet.
NoStream :: ExpectedVersion

-- | The stream should already exist.
StreamExists :: ExpectedVersion

-- | Used to assert the stream is at a particular version.
ExactVersion :: EventVersion -> ExpectedVersion
data EventWriteError
EventStreamNotAtExpectedVersion :: EventVersion -> EventWriteError

-- | Changes the monad an <a>EventStoreReader</a> runs in. This is useful
--   to run event stores in another <a>Monad</a> while forgetting the
--   original <a>Monad</a>.
runEventStoreReaderUsing :: (Monad m, Monad mstore) => (forall a. mstore a -> m a) -> EventStoreReader key position mstore event -> EventStoreReader key position m event

-- | Analog of <a>runEventStoreReaderUsing</a> for a
--   <a>EventStoreWriter</a>.
runEventStoreWriterUsing :: (Monad m, Monad mstore) => (forall a. mstore a -> m a) -> EventStoreWriter mstore event -> EventStoreWriter m event

-- | Wraps an <a>EventStoreReader</a> and transparently
--   serializes/deserializes events for you. Note that in this
--   implementation deserialization errors are simply ignored (the event is
--   not returned).
serializedEventStoreReader :: (Monad m) => Serializer event serialized -> EventStoreReader key position m serialized -> EventStoreReader key position m event

-- | Convenience wrapper around <a>serializedEventStoreReader</a> for
--   <a>VersionedEventStoreReader</a>.
serializedVersionedEventStoreReader :: (Monad m) => Serializer event serialized -> VersionedEventStoreReader m serialized -> VersionedEventStoreReader m event

-- | Convenience wrapper around <a>serializedEventStoreReader</a> for
--   <a>GlobalEventStoreReader</a>.
serializedGlobalEventStoreReader :: (Monad m) => Serializer event serialized -> GlobalEventStoreReader m serialized -> GlobalEventStoreReader m event

-- | Like <a>serializedEventStoreReader</a> but for an
--   <a>EventStoreWriter</a>. Note that <a>EventStoreWriter</a> is an
--   instance of <a>Contravariant</a>, so you can just use <tt>contramap
--   serialize</tt> instead of this function.
serializedEventStoreWriter :: (Monad m) => Serializer event serialized -> EventStoreWriter m serialized -> EventStoreWriter m event

-- | Event versions are a strictly increasing series of integers for each
--   projection. They allow us to order the events when they are replayed,
--   and they also help as a concurrency check in a multi-threaded
--   environment so services modifying the projection can be sure the
--   projection didn't change during their execution.
newtype EventVersion
EventVersion :: Int -> EventVersion
[unEventVersion] :: EventVersion -> Int

-- | The sequence number gives us a global ordering of events in a
--   particular event store. Using sequence numbers is not strictly
--   necessary for an event sourcing and CQRS system, but it makes it way
--   easier to replay events consistently without having to use distributed
--   transactions in an event bus. In SQL-based event stores, they are also
--   very cheap to create.
newtype SequenceNumber
SequenceNumber :: Int -> SequenceNumber
[unSequenceNumber] :: SequenceNumber -> Int

-- | Helper to create <tt>storeEventsRaw</tt> given a function to get the
--   latest stream version and a function to write to the event store.
--   **NOTE**: This only works if the monad <tt>m</tt> is transactional.
transactionalExpectedWriteHelper :: (Monad m) => (UUID -> m EventVersion) -> (UUID -> [event] -> m ()) -> ExpectedVersion -> UUID -> [event] -> m (Maybe EventWriteError)
instance Web.Internal.HttpApiData.FromHttpApiData Eventful.Store.Class.SequenceNumber
instance Web.Internal.HttpApiData.ToHttpApiData Eventful.Store.Class.SequenceNumber
instance Web.PathPieces.PathPiece Eventful.Store.Class.SequenceNumber
instance Data.Aeson.Types.ToJSON.ToJSON Eventful.Store.Class.SequenceNumber
instance Data.Aeson.Types.FromJSON.FromJSON Eventful.Store.Class.SequenceNumber
instance GHC.Num.Num Eventful.Store.Class.SequenceNumber
instance GHC.Enum.Enum Eventful.Store.Class.SequenceNumber
instance GHC.Classes.Eq Eventful.Store.Class.SequenceNumber
instance GHC.Classes.Ord Eventful.Store.Class.SequenceNumber
instance GHC.Read.Read Eventful.Store.Class.SequenceNumber
instance GHC.Show.Show Eventful.Store.Class.SequenceNumber
instance GHC.Classes.Eq Eventful.Store.Class.ExpectedVersion
instance GHC.Show.Show Eventful.Store.Class.ExpectedVersion
instance GHC.Classes.Eq Eventful.Store.Class.EventWriteError
instance GHC.Show.Show Eventful.Store.Class.EventWriteError
instance Data.Aeson.Types.ToJSON.ToJSON Eventful.Store.Class.EventVersion
instance Data.Aeson.Types.FromJSON.FromJSON Eventful.Store.Class.EventVersion
instance GHC.Num.Num Eventful.Store.Class.EventVersion
instance GHC.Enum.Enum Eventful.Store.Class.EventVersion
instance GHC.Classes.Eq Eventful.Store.Class.EventVersion
instance GHC.Classes.Ord Eventful.Store.Class.EventVersion
instance GHC.Read.Read Eventful.Store.Class.EventVersion
instance GHC.Show.Show Eventful.Store.Class.EventVersion
instance Data.Traversable.Traversable (Eventful.Store.Class.StreamEvent key position)
instance Data.Foldable.Foldable (Eventful.Store.Class.StreamEvent key position)
instance GHC.Base.Functor (Eventful.Store.Class.StreamEvent key position)
instance (GHC.Classes.Eq event, GHC.Classes.Eq position, GHC.Classes.Eq key) => GHC.Classes.Eq (Eventful.Store.Class.StreamEvent key position event)
instance (GHC.Show.Show event, GHC.Show.Show position, GHC.Show.Show key) => GHC.Show.Show (Eventful.Store.Class.StreamEvent key position event)
instance Data.Functor.Contravariant.Contravariant (Eventful.Store.Class.EventStoreWriter m)
instance GHC.Base.Functor m => GHC.Base.Functor (Eventful.Store.Class.EventStoreReader key position m)

module Eventful.ReadModel.Class
data ReadModel model serialized m
ReadModel :: model -> (model -> m SequenceNumber) -> (model -> [GlobalStreamEvent serialized] -> m ()) -> ReadModel model serialized m
[readModelModel] :: ReadModel model serialized m -> model
[readModelLatestAppliedSequence] :: ReadModel model serialized m -> model -> m SequenceNumber
[readModelHandleEvents] :: ReadModel model serialized m -> model -> [GlobalStreamEvent serialized] -> m ()
runPollingReadModel :: (MonadIO m, Monad mstore) => ReadModel model serialized m -> GlobalEventStoreReader mstore serialized -> (forall a. mstore a -> m a) -> PollingPeriodSeconds -> m ()

module Eventful.Projection

-- | A <a>Projection</a> is a piece of <tt>state</tt> that is constructed
--   only from <tt>event</tt>s. A Projection is how you reconstruct event
--   sourced state from the ordered stream of events that constitute that
--   state. The "seed" of a Projection is the initial state before any
--   events are applied. The event handler for a projection is the function
--   that actually modifies state based on the given event.
data Projection state event
Projection :: state -> (state -> event -> state) -> Projection state event

-- | Initial state of a projection
[projectionSeed] :: Projection state event -> state

-- | The function that applies and event to the current state, producing a
--   new state.
[projectionEventHandler] :: Projection state event -> state -> event -> state

-- | Computes the latest state of a <a>Projection</a> from some events.
latestProjection :: (Foldable t) => Projection state event -> t event -> state

-- | Given a list of events, produce all the Projections that were ever
--   produced. Just a <a>scanl</a> using <a>projectionEventHandler</a>.
--   This function is useful for testing <a>Projection</a>s; you can easily
--   assert that all the states of a Projection are valid given a list of
--   events.
allProjections :: Projection state event -> [event] -> [state]

-- | A <a>StreamProjection</a> is a <a>Projection</a> that has been
--   constructed from events from a particular event stream. This is useful
--   when we want to cache the resulting state and also keep track of what
--   part of the stream the state is caught up to.
data StreamProjection key position state event
StreamProjection :: !key -> !position -> !(Projection state event) -> !state -> StreamProjection key position state event
[streamProjectionKey] :: StreamProjection key position state event -> !key
[streamProjectionPosition] :: StreamProjection key position state event -> !position
[streamProjectionProjection] :: StreamProjection key position state event -> !(Projection state event)
[streamProjectionState] :: StreamProjection key position state event -> !state
type VersionedStreamProjection = StreamProjection UUID EventVersion
type GlobalStreamProjection state event = StreamProjection () SequenceNumber state (VersionedStreamEvent event)

-- | Initialize a <a>StreamProjection</a> with a <a>Projection</a>, key,
--   and order key.
streamProjection :: key -> position -> Projection state event -> StreamProjection key position state event

-- | Initialize a <a>VersionedStreamProjection</a>.
versionedStreamProjection :: UUID -> Projection state event -> VersionedStreamProjection state event

-- | Initialize a <a>GlobalStreamProjection</a>.
globalStreamProjection :: Projection state (VersionedStreamEvent event) -> GlobalStreamProjection state event

-- | Gets the latest projection from a store by querying events from the
--   latest order key and then applying the events using the Projection's
--   event handler.
getLatestStreamProjection :: (Monad m, Num position) => EventStoreReader key position m (StreamEvent key position event) -> StreamProjection key position state event -> m (StreamProjection key position state event)

-- | Use a <a>Serializer</a> to wrap a <a>Projection</a> with event type
--   <tt>event</tt> so it uses the <tt>serialized</tt> type.
serializedProjection :: Projection state event -> Serializer event serialized -> Projection state serialized

-- | Transform a <a>Projection</a> when you only have a partial
--   relationship between the source event type and the target event type.
projectionMapMaybe :: (eventB -> Maybe eventA) -> Projection state eventA -> Projection state eventB
instance Data.Functor.Contravariant.Contravariant (Eventful.Projection.Projection state)

module Eventful.TH.Projection

-- | Creates a <a>Projection</a> for a given type and a list of events. The
--   user of this function also needs to provide event handlers for each
--   event. For example:
--   
--   <pre>
--   data EventA = EventA
--   data EventB = EventB
--   
--   data MyState = MyState Int
--   
--   myStateDefault :: MyState
--   myStateDefault = MyState 0
--   
--   mkProjection ''MyState 'myStateDefault [''EventA, ''EventB]
--   
--   handleEventA :: MyState -&gt; EventA -&gt; MyState
--   handleEventA (MyState x) EventA = MyState (x + 1)
--   
--   handleEventB :: MyState -&gt; EventB -&gt; MyState
--   handleEventB (MyState x) EventB = MyState (x - 1)
--   </pre>
--   
--   This will produce the following:
--   
--   <pre>
--   data MyStateEvent = MyStateEventA !EventA | MyStateEventB !EventB
--   
--   handleMyStateEvent :: MyState -&gt; MyStateEvent -&gt; MyState
--   handleMyStateEvent state (MyStateEventA event) = handleEventA state event
--   handleMyStateEvent state (MyStateEventB event) = handleEventB state event
--   
--   type MyStateProjection = Projection MyState MyStateEvent
--   
--   myStateProjection :: MyStateProjection
--   myStateProjection = Projection myStateDefault handleMyStateEvent
--   </pre>
mkProjection :: Name -> Name -> [Name] -> Q [Dec]

module Eventful.TH

module Eventful.ProjectionCache.Types

-- | A <a>ProjectionCache</a> caches snapshots of <a>Projection</a>s in
--   event streams. This is useful if your event streams are very large.
--   This cache operates on some <a>Monad</a> <tt>m</tt> and stores the
--   <a>Projection</a> state of type <tt>serialized</tt>.
--   
--   At its core, this is essentially just a key-value store with knowledge
--   of the stream <a>UUID</a> and <a>EventVersion</a>. It is recommended
--   to use the other helper functions in this module to interpret the
--   stored values using a <a>Projection</a>.
--   
--   The <tt>key</tt> and <tt>position</tt> type parameters are polymorphic
--   so we can abstract over a cache for individual event streams, and a
--   cache for globally ordered streams.
data ProjectionCache key position serialized m
ProjectionCache :: (key -> position -> serialized -> m ()) -> (key -> m (Maybe (position, serialized))) -> ProjectionCache key position serialized m

-- | Stores the state for a projection at a given <tt>key</tt> and
--   <tt>position</tt>. This is pretty unsafe, because there is no
--   guarantee what is stored is actually derived from the events in the
--   stream. Consider using <a>updateProjectionCache</a>.
[storeProjectionSnapshot] :: ProjectionCache key position serialized m -> key -> position -> serialized -> m ()

-- | Loads the latest projection state from the cache.
[loadProjectionSnapshot] :: ProjectionCache key position serialized m -> key -> m (Maybe (position, serialized))

-- | Type synonym for a <a>ProjectionCache</a> used on individual event
--   streams.
type VersionedProjectionCache serialized m = ProjectionCache UUID EventVersion serialized m

-- | Type synonym for a <a>ProjectionCache</a> that is used in conjunction
--   with a <tt>GlobalStreamEventStore</tt>.
type GlobalStreamProjectionCache key serialized m = ProjectionCache key SequenceNumber serialized m

-- | Changes the monad a <a>ProjectionCache</a> runs in. This is useful to
--   run the cache in another <a>Monad</a> while forgetting the original
--   <a>Monad</a>.
runProjectionCacheUsing :: (Monad m, Monad mstore) => (forall a. mstore a -> m a) -> ProjectionCache key position serialized mstore -> ProjectionCache key position serialized m

-- | Wraps a <a>ProjectionCache</a> and transparently
--   serializes/deserializes events for you. Note that in this
--   implementation deserialization errors when using <a>getEvents</a> are
--   simply ignored (the event is not returned).
serializedProjectionCache :: (Monad m) => Serializer state serialized -> ProjectionCache key position serialized m -> ProjectionCache key position state m

-- | Like <tt>getLatestVersionedProjection</tt>, but uses a
--   <a>ProjectionCache</a> if it contains more recent state.
getLatestVersionedProjectionWithCache :: (Monad m) => VersionedEventStoreReader m event -> VersionedProjectionCache state m -> VersionedStreamProjection state event -> m (VersionedStreamProjection state event)

-- | Like <tt>getLatestGlobalProjection</tt>, but uses a
--   <a>ProjectionCache</a> if it contains more recent state.
getLatestGlobalProjectionWithCache :: (Monad m) => GlobalEventStoreReader m event -> GlobalStreamProjectionCache key state m -> GlobalStreamProjection state event -> key -> m (GlobalStreamProjection state event)

-- | Loads the latest projection state from the cache/store and stores this
--   value back into the projection cache.
updateProjectionCache :: (Monad m) => VersionedEventStoreReader m event -> VersionedProjectionCache state m -> VersionedStreamProjection state event -> m ()

-- | Analog of <a>updateProjectionCache</a> for a
--   <a>GlobalStreamProjectionCache</a>.
updateGlobalProjectionCache :: (Monad m) => GlobalEventStoreReader m event -> GlobalStreamProjectionCache key state m -> GlobalStreamProjection state event -> key -> m ()

module Eventful.EventBus

-- | This function wraps an event store by sending events to event handlers
--   after running <a>storeEvents</a>. This is useful to quickly wire up
--   event handlers in your application (like read models or process
--   managers), and it is also useful for integration testing along with an
--   in-memory event store.
synchronousEventBusWrapper :: (Monad m) => EventStoreWriter m event -> [EventStoreWriter m event -> UUID -> event -> m ()] -> EventStoreWriter m event

-- | Stores events in the store and them publishes them to the event
--   handlers. This is used in the <a>synchronousEventBusWrapper</a>.
storeAndPublishEvents :: (Monad m) => EventStoreWriter m event -> [UUID -> event -> m ()] -> ExpectedVersion -> UUID -> [event] -> m (Maybe EventWriteError)


-- | Defines an Aggregate type-class from DDD parlance.
module Eventful.Aggregate

-- | An <a>Aggregate</a> is a combination of a <a>Projection</a> and a
--   function to validate commands against that <a>Projection</a>. When
--   using an aggregate in some service, it is common to simply load the
--   latest projection state from the event store and handle the command.
--   If the command is valid then the new events are applied to the
--   projection in the event store.
data Aggregate state event command
Aggregate :: (state -> command -> [event]) -> Projection state event -> Aggregate state event command
[aggregateCommandHandler] :: Aggregate state event command -> state -> command -> [event]
[aggregateProjection] :: Aggregate state event command -> Projection state event

-- | Given a list commands, produce all of the states the aggregate's
--   projection sees. This is useful for unit testing aggregates.
allAggregateStates :: Aggregate state event command -> [command] -> [state]

-- | Loads the latest version of a <a>Projection</a> from the event store
--   and tries to apply the <a>Aggregate</a> command to it. If the command
--   succeeds, then this saves the events back to the store as well.
commandStoredAggregate :: (Monad m) => EventStoreWriter m event -> VersionedEventStoreReader m event -> Aggregate state event command -> UUID -> command -> m [event]

-- | Use a pair of <a>Serializer</a>s to wrap a <a>Aggregate</a> with event
--   type <tt>event</tt> and command type <tt>command</tt> so it uses the
--   <tt>serializedEvent</tt> and <tt>serializedCommand</tt> types.
serializedAggregate :: Aggregate state event command -> Serializer event serializedEvent -> Serializer command serializedCommand -> Aggregate state serializedEvent serializedCommand

module Eventful.ProcessManager

-- | A <a>ProcessManager</a> manages interaction between aggregates. It
--   works by listening to events on an event bus and applying events to
--   its internal <a>Projection</a> (see
--   <a>applyProcessManagerCommandsAndEvents</a>). Then, pending commands
--   and events are plucked off of that Projection and applied to the
--   appropriate Aggregates or Projections in other streams.
data ProcessManager state event command
ProcessManager :: Projection state (VersionedStreamEvent event) -> (state -> [ProcessManagerCommand event command]) -> (state -> [StreamEvent UUID () event]) -> ProcessManager state event command
[processManagerProjection] :: ProcessManager state event command -> Projection state (VersionedStreamEvent event)
[processManagerPendingCommands] :: ProcessManager state event command -> state -> [ProcessManagerCommand event command]
[processManagerPendingEvents] :: ProcessManager state event command -> state -> [StreamEvent UUID () event]

-- | This is a <tt>command</tt> along with the UUID of the target
--   <a>Aggregate</a>, and well as the <a>Aggregate</a> instance. Note that
--   this uses an existential type to hide the <tt>state</tt> type
--   parameter on the Aggregate.
data ProcessManagerCommand event command
ProcessManagerCommand :: UUID -> Aggregate state event command -> command -> ProcessManagerCommand event command
[processManagerCommandAggregateId] :: ProcessManagerCommand event command -> UUID
[processManagerCommandAggregate] :: ProcessManagerCommand event command -> Aggregate state event command
[processManagerCommandCommand] :: ProcessManagerCommand event command -> command

-- | Plucks the pending commands and events off of the process manager's
--   state and applies them to the appropriate locations in the event
--   store.
applyProcessManagerCommandsAndEvents :: (Monad m) => ProcessManager state event command -> EventStoreWriter m event -> VersionedEventStoreReader m event -> state -> m ()
instance (GHC.Show.Show command, GHC.Show.Show event) => GHC.Show.Show (Eventful.ProcessManager.ProcessManagerCommand event command)

module Eventful
