{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}

module Data.Mergeless.Persistent
  ( -- * Client side
    clientMakeSyncRequestQuery,
    clientMergeSyncResponseQuery,

    -- ** Raw processors
    clientSyncProcessor,

    -- * Server side
    serverProcessSyncQuery,
    serverProcessSyncWithCustomIdQuery,

    -- ** Sync processors
    serverSyncProcessor,
    serverSyncProcessorWithCustomId,

    -- * Utils

    -- ** Client side
    setupUnsyncedClientQuery,
    setupClientQuery,
    clientGetStoreQuery,

    -- ** Server side side
    serverGetStoreQuery,
    setupServerQuery,
  )
where

import Control.Monad
import Control.Monad.IO.Class
import qualified Data.Map as M
import Data.Maybe
import Data.Mergeless
import qualified Data.Set as S
import Database.Persist
import Database.Persist.Sql
import Lens.Micro

-- | Make a sync request on the client side
clientMakeSyncRequestQuery ::
  ( Ord sid,
    PersistEntity clientRecord,
    PersistField sid,
    PersistEntityBackend clientRecord ~ SqlBackend,
    MonadIO m
  ) =>
  -- | How to read a record
  (clientRecord -> a) ->
  -- | The server id field
  EntityField clientRecord (Maybe sid) ->
  -- | The deleted field
  EntityField clientRecord Bool ->
  SqlPersistT m (SyncRequest (Key clientRecord) sid a)
clientMakeSyncRequestQuery :: (clientRecord -> a)
-> EntityField clientRecord (Maybe sid)
-> EntityField clientRecord Bool
-> SqlPersistT m (SyncRequest (Key clientRecord) sid a)
clientMakeSyncRequestQuery clientRecord -> a
func EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord Bool
deletedField = do
  Map (Key clientRecord) a
syncRequestAdded <-
    [(Key clientRecord, a)] -> Map (Key clientRecord) a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Key clientRecord, a)] -> Map (Key clientRecord) a)
-> ([Entity clientRecord] -> [(Key clientRecord, a)])
-> [Entity clientRecord]
-> Map (Key clientRecord) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity clientRecord -> (Key clientRecord, a))
-> [Entity clientRecord] -> [(Key clientRecord, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Entity Key clientRecord
cid clientRecord
ct) -> (Key clientRecord
cid, clientRecord -> a
func clientRecord
ct))
      ([Entity clientRecord] -> Map (Key clientRecord) a)
-> ReaderT SqlBackend m [Entity clientRecord]
-> ReaderT SqlBackend m (Map (Key clientRecord) a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter clientRecord]
-> [SelectOpt clientRecord]
-> ReaderT SqlBackend m [Entity clientRecord]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList
        [ EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Maybe sid
forall a. Maybe a
Nothing,
          EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
False
        ]
        []
  Set sid
syncRequestSynced <-
    [sid] -> Set sid
forall a. Ord a => [a] -> Set a
S.fromList ([sid] -> Set sid)
-> ([Entity clientRecord] -> [sid])
-> [Entity clientRecord]
-> Set sid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity clientRecord -> Maybe sid)
-> [Entity clientRecord] -> [sid]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\Entity clientRecord
e -> Entity clientRecord
e Entity clientRecord
-> Getting (Maybe sid) (Entity clientRecord) (Maybe sid)
-> Maybe sid
forall s a. s -> Getting a s a -> a
^. EntityField clientRecord (Maybe sid)
-> forall (f :: * -> *).
   Functor f =>
   (Maybe sid -> f (Maybe sid))
   -> Entity clientRecord -> f (Entity clientRecord)
forall record field.
PersistEntity record =>
EntityField record field
-> forall (f :: * -> *).
   Functor f =>
   (field -> f field) -> Entity record -> f (Entity record)
fieldLens EntityField clientRecord (Maybe sid)
serverIdField)
      ([Entity clientRecord] -> Set sid)
-> ReaderT SqlBackend m [Entity clientRecord]
-> ReaderT SqlBackend m (Set sid)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter clientRecord]
-> [SelectOpt clientRecord]
-> ReaderT SqlBackend m [Entity clientRecord]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList
        [ EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
!=. Maybe sid
forall a. Maybe a
Nothing,
          EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
False
        ]
        []
  Set sid
syncRequestDeleted <-
    [sid] -> Set sid
forall a. Ord a => [a] -> Set a
S.fromList ([sid] -> Set sid)
-> ([Entity clientRecord] -> [sid])
-> [Entity clientRecord]
-> Set sid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity clientRecord -> Maybe sid)
-> [Entity clientRecord] -> [sid]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\Entity clientRecord
e -> Entity clientRecord
e Entity clientRecord
-> Getting (Maybe sid) (Entity clientRecord) (Maybe sid)
-> Maybe sid
forall s a. s -> Getting a s a -> a
^. EntityField clientRecord (Maybe sid)
-> forall (f :: * -> *).
   Functor f =>
   (Maybe sid -> f (Maybe sid))
   -> Entity clientRecord -> f (Entity clientRecord)
forall record field.
PersistEntity record =>
EntityField record field
-> forall (f :: * -> *).
   Functor f =>
   (field -> f field) -> Entity record -> f (Entity record)
fieldLens EntityField clientRecord (Maybe sid)
serverIdField)
      ([Entity clientRecord] -> Set sid)
-> ReaderT SqlBackend m [Entity clientRecord]
-> ReaderT SqlBackend m (Set sid)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter clientRecord]
-> [SelectOpt clientRecord]
-> ReaderT SqlBackend m [Entity clientRecord]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList
        [ EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
!=. Maybe sid
forall a. Maybe a
Nothing,
          EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
True
        ]
        []
  SyncRequest (Key clientRecord) sid a
-> SqlPersistT m (SyncRequest (Key clientRecord) sid a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure SyncRequest :: forall ci si a. Map ci a -> Set si -> Set si -> SyncRequest ci si a
SyncRequest {Map (Key clientRecord) a
Set sid
syncRequestAdded :: Map (Key clientRecord) a
syncRequestSynced :: Set sid
syncRequestDeleted :: Set sid
syncRequestDeleted :: Set sid
syncRequestSynced :: Set sid
syncRequestAdded :: Map (Key clientRecord) a
..}

-- | Merge a sync response on the client side
clientMergeSyncResponseQuery ::
  ( PersistEntity clientRecord,
    PersistField sid,
    PersistEntityBackend clientRecord ~ SqlBackend,
    MonadIO m
  ) =>
  -- | Create an un-deleted synced record on the client side
  (sid -> a -> clientRecord) ->
  -- | The server id field
  EntityField clientRecord (Maybe sid) ->
  -- | The deleted field
  EntityField clientRecord Bool ->
  SyncResponse (Key clientRecord) sid a ->
  SqlPersistT m ()
clientMergeSyncResponseQuery :: (sid -> a -> clientRecord)
-> EntityField clientRecord (Maybe sid)
-> EntityField clientRecord Bool
-> SyncResponse (Key clientRecord) sid a
-> SqlPersistT m ()
clientMergeSyncResponseQuery sid -> a -> clientRecord
func EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord Bool
deletedField = ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
-> SyncResponse (Key clientRecord) sid a -> SqlPersistT m ()
forall (m :: * -> *) ci si a.
Monad m =>
ClientSyncProcessor ci si a m -> SyncResponse ci si a -> m ()
mergeSyncResponseCustom (ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
 -> SyncResponse (Key clientRecord) sid a -> SqlPersistT m ())
-> ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
-> SyncResponse (Key clientRecord) sid a
-> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ (sid -> a -> clientRecord)
-> EntityField clientRecord (Maybe sid)
-> EntityField clientRecord Bool
-> ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
forall clientRecord sid (m :: * -> *) a.
(PersistEntity clientRecord, PersistField sid,
 PersistEntityBackend clientRecord ~ SqlBackend, MonadIO m) =>
(sid -> a -> clientRecord)
-> EntityField clientRecord (Maybe sid)
-> EntityField clientRecord Bool
-> ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
clientSyncProcessor sid -> a -> clientRecord
func EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord Bool
deletedField

clientSyncProcessor ::
  ( PersistEntity clientRecord,
    PersistField sid,
    PersistEntityBackend clientRecord ~ SqlBackend,
    MonadIO m
  ) =>
  -- | Create an un-deleted synced record on the client side
  (sid -> a -> clientRecord) ->
  -- | The server id field
  EntityField clientRecord (Maybe sid) ->
  -- | The deleted field
  EntityField clientRecord Bool ->
  ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
clientSyncProcessor :: (sid -> a -> clientRecord)
-> EntityField clientRecord (Maybe sid)
-> EntityField clientRecord Bool
-> ClientSyncProcessor (Key clientRecord) sid a (SqlPersistT m)
clientSyncProcessor sid -> a -> clientRecord
func EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord Bool
deletedField = ClientSyncProcessor :: forall ci si a (m :: * -> *).
(Map si a -> m ())
-> (Map ci si -> m ())
-> (Set si -> m ())
-> (Set si -> m ())
-> ClientSyncProcessor ci si a m
ClientSyncProcessor {Map sid a -> ReaderT SqlBackend m ()
Map (Key clientRecord) sid -> ReaderT SqlBackend m ()
Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncServerAdded :: Map sid a -> ReaderT SqlBackend m ()
clientSyncProcessorSyncClientAdded :: Map (Key clientRecord) sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncServerDeleted :: Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncClientDeleted :: Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncClientDeleted :: Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncServerDeleted :: Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncClientAdded :: Map (Key clientRecord) sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncServerAdded :: Map sid a -> ReaderT SqlBackend m ()
..}
  where
    clientSyncProcessorSyncServerAdded :: Map sid a -> ReaderT SqlBackend m ()
clientSyncProcessorSyncServerAdded Map sid a
m = [(sid, a)]
-> ((sid, a) -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Map sid a -> [(sid, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map sid a
m) (((sid, a) -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ())
-> ((sid, a) -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall a b. (a -> b) -> a -> b
$ \(sid
si, a
st) ->
      clientRecord -> ReaderT SqlBackend m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m ()
insert_ (clientRecord -> ReaderT SqlBackend m ())
-> clientRecord -> ReaderT SqlBackend m ()
forall a b. (a -> b) -> a -> b
$ sid -> a -> clientRecord
func sid
si a
st
    clientSyncProcessorSyncClientAdded :: Map (Key clientRecord) sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncClientAdded Map (Key clientRecord) sid
m = [(Key clientRecord, sid)]
-> ((Key clientRecord, sid) -> ReaderT SqlBackend m ())
-> ReaderT SqlBackend m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Map (Key clientRecord) sid -> [(Key clientRecord, sid)]
forall k a. Map k a -> [(k, a)]
M.toList Map (Key clientRecord) sid
m) (((Key clientRecord, sid) -> ReaderT SqlBackend m ())
 -> ReaderT SqlBackend m ())
-> ((Key clientRecord, sid) -> ReaderT SqlBackend m ())
-> ReaderT SqlBackend m ()
forall a b. (a -> b) -> a -> b
$ \(Key clientRecord
cid, sid
sid) ->
      Key clientRecord
-> [Update clientRecord] -> ReaderT SqlBackend m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> [Update record] -> ReaderT backend m ()
update Key clientRecord
cid [EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Update clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. sid -> Maybe sid
forall a. a -> Maybe a
Just sid
sid]
    clientSyncProcessorSyncServerDeleted :: Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncServerDeleted Set sid
s = [sid]
-> (sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Set sid -> [sid]
forall a. Set a -> [a]
S.toList Set sid
s) ((sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ())
-> (sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall a b. (a -> b) -> a -> b
$ \sid
sid ->
      [Filter clientRecord] -> ReaderT SqlBackend m ()
forall backend (m :: * -> *) record.
(PersistQueryWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m ()
deleteWhere [EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. sid -> Maybe sid
forall a. a -> Maybe a
Just sid
sid]
    clientSyncProcessorSyncClientDeleted :: Set sid -> ReaderT SqlBackend m ()
clientSyncProcessorSyncClientDeleted Set sid
s = [sid]
-> (sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Set sid -> [sid]
forall a. Set a -> [a]
S.toList Set sid
s) ((sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ())
-> (sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall a b. (a -> b) -> a -> b
$ \sid
sid ->
      [Filter clientRecord] -> ReaderT SqlBackend m ()
forall backend (m :: * -> *) record.
(PersistQueryWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m ()
deleteWhere [EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. sid -> Maybe sid
forall a. a -> Maybe a
Just sid
sid, EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
True]

-- | Process a sync query on the server side.
serverProcessSyncQuery ::
  ( PersistEntity record,
    PersistEntityBackend record ~ SqlBackend,
    MonadIO m
  ) =>
  -- | Filters to select the relevant items
  --
  -- Use these if you have multiple users and you want to sync per-user
  [Filter record] ->
  -- | How to read a record
  (record -> a) ->
  -- | How to insert a _new_ record
  (a -> record) ->
  SyncRequest ci (Key record) a ->
  SqlPersistT m (SyncResponse ci (Key record) a)
serverProcessSyncQuery :: [Filter record]
-> (record -> a)
-> (a -> record)
-> SyncRequest ci (Key record) a
-> SqlPersistT m (SyncResponse ci (Key record) a)
serverProcessSyncQuery [Filter record]
filters record -> a
funcTo a -> record
funcFrom = ServerSyncProcessor ci (Key record) a (SqlPersistT m)
-> SyncRequest ci (Key record) a
-> SqlPersistT m (SyncResponse ci (Key record) a)
forall ci si a (m :: * -> *).
(Ord si, Monad m) =>
ServerSyncProcessor ci si a m
-> SyncRequest ci si a -> m (SyncResponse ci si a)
processServerSyncCustom (ServerSyncProcessor ci (Key record) a (SqlPersistT m)
 -> SyncRequest ci (Key record) a
 -> SqlPersistT m (SyncResponse ci (Key record) a))
-> ServerSyncProcessor ci (Key record) a (SqlPersistT m)
-> SyncRequest ci (Key record) a
-> SqlPersistT m (SyncResponse ci (Key record) a)
forall a b. (a -> b) -> a -> b
$ [Filter record]
-> (record -> a)
-> (a -> record)
-> ServerSyncProcessor ci (Key record) a (SqlPersistT m)
forall record (m :: * -> *) a ci.
(PersistEntity record, PersistEntityBackend record ~ SqlBackend,
 MonadIO m) =>
[Filter record]
-> (record -> a)
-> (a -> record)
-> ServerSyncProcessor ci (Key record) a (SqlPersistT m)
serverSyncProcessor [Filter record]
filters record -> a
funcTo a -> record
funcFrom

-- | A server sync processor that uses the sqlkey of the record as the name
serverSyncProcessor ::
  ( PersistEntity record,
    PersistEntityBackend record ~ SqlBackend,
    MonadIO m
  ) =>
  -- | Filters to select the relevant items
  --
  -- Use these if you have multiple users and you want to sync per-user
  [Filter record] ->
  -- | How to read a record
  (record -> a) ->
  -- | How to insert a _new_ record
  (a -> record) ->
  ServerSyncProcessor ci (Key record) a (SqlPersistT m)
serverSyncProcessor :: [Filter record]
-> (record -> a)
-> (a -> record)
-> ServerSyncProcessor ci (Key record) a (SqlPersistT m)
serverSyncProcessor [Filter record]
filters record -> a
funcTo a -> record
funcFrom =
  ServerSyncProcessor :: forall ci si a (m :: * -> *).
m (Map si a)
-> (Map ci a -> m (Map ci si))
-> (Set si -> m (Set si))
-> ServerSyncProcessor ci si a m
ServerSyncProcessor {ReaderT SqlBackend m (Map (Key record) a)
Map ci a -> ReaderT SqlBackend m (Map ci (Key record))
Set (Key record) -> ReaderT SqlBackend m (Set (Key record))
forall (m :: * -> *) backend (t :: * -> *) record.
(MonadIO m, PersistStoreWrite backend, Foldable t,
 PersistEntity record,
 PersistEntityBackend record ~ BaseBackend backend) =>
t (Key record) -> ReaderT backend m (t (Key record))
serverSyncProcessorRead :: ReaderT SqlBackend m (Map (Key record) a)
serverSyncProcessorAddItems :: Map ci a -> ReaderT SqlBackend m (Map ci (Key record))
serverSyncProcessorDeleteItems :: Set (Key record) -> ReaderT SqlBackend m (Set (Key record))
serverSyncProcessorDeleteItems :: forall (m :: * -> *) backend (t :: * -> *) record.
(MonadIO m, PersistStoreWrite backend, Foldable t,
 PersistEntity record,
 PersistEntityBackend record ~ BaseBackend backend) =>
t (Key record) -> ReaderT backend m (t (Key record))
serverSyncProcessorAddItems :: Map ci a -> ReaderT SqlBackend m (Map ci (Key record))
serverSyncProcessorRead :: ReaderT SqlBackend m (Map (Key record) a)
..}
  where
    serverSyncProcessorRead :: ReaderT SqlBackend m (Map (Key record) a)
serverSyncProcessorRead = [(Key record, a)] -> Map (Key record) a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Key record, a)] -> Map (Key record) a)
-> ([Entity record] -> [(Key record, a)])
-> [Entity record]
-> Map (Key record) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity record -> (Key record, a))
-> [Entity record] -> [(Key record, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Entity Key record
i record
record) -> (Key record
i, record -> a
funcTo record
record)) ([Entity record] -> Map (Key record) a)
-> ReaderT SqlBackend m [Entity record]
-> ReaderT SqlBackend m (Map (Key record) a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter record]
-> [SelectOpt record] -> ReaderT SqlBackend m [Entity record]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList [Filter record]
filters []
    serverSyncProcessorAddItems :: Map ci a -> ReaderT SqlBackend m (Map ci (Key record))
serverSyncProcessorAddItems = (a -> ReaderT SqlBackend m (Key record))
-> Map ci a -> ReaderT SqlBackend m (Map ci (Key record))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((a -> ReaderT SqlBackend m (Key record))
 -> Map ci a -> ReaderT SqlBackend m (Map ci (Key record)))
-> (a -> ReaderT SqlBackend m (Key record))
-> Map ci a
-> ReaderT SqlBackend m (Map ci (Key record))
forall a b. (a -> b) -> a -> b
$ record -> ReaderT SqlBackend m (Key record)
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m (Key record)
insert (record -> ReaderT SqlBackend m (Key record))
-> (a -> record) -> a -> ReaderT SqlBackend m (Key record)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> record
funcFrom
    serverSyncProcessorDeleteItems :: t (Key record) -> ReaderT backend m (t (Key record))
serverSyncProcessorDeleteItems t (Key record)
s = do
      (Key record -> ReaderT backend m ())
-> t (Key record) -> ReaderT backend m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Key record -> ReaderT backend m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> ReaderT backend m ()
delete t (Key record)
s
      t (Key record) -> ReaderT backend m (t (Key record))
forall (f :: * -> *) a. Applicative f => a -> f a
pure t (Key record)
s

-- | Process a sync query on the server side with a custom id.
serverProcessSyncWithCustomIdQuery ::
  ( Ord sid,
    PersistEntity record,
    PersistField sid,
    PersistEntityBackend record ~ SqlBackend,
    MonadIO m
  ) =>
  -- | The action to generate new identifiers
  SqlPersistT m sid ->
  -- | The id field
  EntityField record sid ->
  -- | Filters to select the relevant items
  --
  -- Use these if you have multiple users and you want to sync per-user
  [Filter record] ->
  -- | How to read a record
  (record -> (sid, a)) ->
  -- | How to insert a _new_ record
  (sid -> a -> record) ->
  SyncRequest ci sid a ->
  SqlPersistT m (SyncResponse ci sid a)
serverProcessSyncWithCustomIdQuery :: SqlPersistT m sid
-> EntityField record sid
-> [Filter record]
-> (record -> (sid, a))
-> (sid -> a -> record)
-> SyncRequest ci sid a
-> SqlPersistT m (SyncResponse ci sid a)
serverProcessSyncWithCustomIdQuery SqlPersistT m sid
genId EntityField record sid
idField [Filter record]
filters record -> (sid, a)
funcTo sid -> a -> record
funcFrom = ServerSyncProcessor ci sid a (SqlPersistT m)
-> SyncRequest ci sid a -> SqlPersistT m (SyncResponse ci sid a)
forall ci si a (m :: * -> *).
(Ord si, Monad m) =>
ServerSyncProcessor ci si a m
-> SyncRequest ci si a -> m (SyncResponse ci si a)
processServerSyncCustom (ServerSyncProcessor ci sid a (SqlPersistT m)
 -> SyncRequest ci sid a -> SqlPersistT m (SyncResponse ci sid a))
-> ServerSyncProcessor ci sid a (SqlPersistT m)
-> SyncRequest ci sid a
-> SqlPersistT m (SyncResponse ci sid a)
forall a b. (a -> b) -> a -> b
$ SqlPersistT m sid
-> EntityField record sid
-> [Filter record]
-> (record -> (sid, a))
-> (sid -> a -> record)
-> ServerSyncProcessor ci sid a (SqlPersistT m)
forall sid record (m :: * -> *) a ci.
(Ord sid, PersistEntity record, PersistField sid,
 PersistEntityBackend record ~ SqlBackend, MonadIO m) =>
SqlPersistT m sid
-> EntityField record sid
-> [Filter record]
-> (record -> (sid, a))
-> (sid -> a -> record)
-> ServerSyncProcessor ci sid a (SqlPersistT m)
serverSyncProcessorWithCustomId SqlPersistT m sid
genId EntityField record sid
idField [Filter record]
filters record -> (sid, a)
funcTo sid -> a -> record
funcFrom

-- | A server sync processor that uses a custom key as the name
serverSyncProcessorWithCustomId ::
  ( Ord sid,
    PersistEntity record,
    PersistField sid,
    PersistEntityBackend record ~ SqlBackend,
    MonadIO m
  ) =>
  -- | The action to generate new identifiers
  SqlPersistT m sid ->
  -- | The id field
  EntityField record sid ->
  -- | Filters to select the relevant items
  --
  -- Use these if you have multiple users and you want to sync per-user
  [Filter record] ->
  -- | How to read a record
  (record -> (sid, a)) ->
  -- | How to insert a _new_ record
  (sid -> a -> record) ->
  ServerSyncProcessor ci sid a (SqlPersistT m)
serverSyncProcessorWithCustomId :: SqlPersistT m sid
-> EntityField record sid
-> [Filter record]
-> (record -> (sid, a))
-> (sid -> a -> record)
-> ServerSyncProcessor ci sid a (SqlPersistT m)
serverSyncProcessorWithCustomId SqlPersistT m sid
genId EntityField record sid
idField [Filter record]
filters record -> (sid, a)
funcTo sid -> a -> record
funcFrom =
  ServerSyncProcessor :: forall ci si a (m :: * -> *).
m (Map si a)
-> (Map ci a -> m (Map ci si))
-> (Set si -> m (Set si))
-> ServerSyncProcessor ci si a m
ServerSyncProcessor {ReaderT SqlBackend m (Map sid a)
Map ci a -> ReaderT SqlBackend m (Map ci sid)
Set sid -> ReaderT SqlBackend m (Set sid)
serverSyncProcessorDeleteItems :: Set sid -> ReaderT SqlBackend m (Set sid)
serverSyncProcessorAddItems :: Map ci a -> ReaderT SqlBackend m (Map ci sid)
serverSyncProcessorRead :: ReaderT SqlBackend m (Map sid a)
serverSyncProcessorRead :: ReaderT SqlBackend m (Map sid a)
serverSyncProcessorAddItems :: Map ci a -> ReaderT SqlBackend m (Map ci sid)
serverSyncProcessorDeleteItems :: Set sid -> ReaderT SqlBackend m (Set sid)
..}
  where
    serverSyncProcessorRead :: ReaderT SqlBackend m (Map sid a)
serverSyncProcessorRead = [(sid, a)] -> Map sid a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(sid, a)] -> Map sid a)
-> ([Entity record] -> [(sid, a)]) -> [Entity record] -> Map sid a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity record -> (sid, a)) -> [Entity record] -> [(sid, a)]
forall a b. (a -> b) -> [a] -> [b]
map (record -> (sid, a)
funcTo (record -> (sid, a))
-> (Entity record -> record) -> Entity record -> (sid, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Entity record -> record
forall record. Entity record -> record
entityVal) ([Entity record] -> Map sid a)
-> ReaderT SqlBackend m [Entity record]
-> ReaderT SqlBackend m (Map sid a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter record]
-> [SelectOpt record] -> ReaderT SqlBackend m [Entity record]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList [Filter record]
filters []
    serverSyncProcessorAddItems :: Map ci a -> ReaderT SqlBackend m (Map ci sid)
serverSyncProcessorAddItems = (a -> SqlPersistT m sid)
-> Map ci a -> ReaderT SqlBackend m (Map ci sid)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((a -> SqlPersistT m sid)
 -> Map ci a -> ReaderT SqlBackend m (Map ci sid))
-> (a -> SqlPersistT m sid)
-> Map ci a
-> ReaderT SqlBackend m (Map ci sid)
forall a b. (a -> b) -> a -> b
$ \a
a -> do
      sid
sid <- SqlPersistT m sid
genId
      let record :: record
record = sid -> a -> record
funcFrom sid
sid a
a
      record -> ReaderT SqlBackend m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m ()
insert_ record
record
      sid -> SqlPersistT m sid
forall (f :: * -> *) a. Applicative f => a -> f a
pure sid
sid
    serverSyncProcessorDeleteItems :: Set sid -> ReaderT SqlBackend m (Set sid)
serverSyncProcessorDeleteItems Set sid
s = do
      Set sid
-> (sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Set sid
s ((sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ())
-> (sid -> ReaderT SqlBackend m ()) -> ReaderT SqlBackend m ()
forall a b. (a -> b) -> a -> b
$ \sid
sid -> [Filter record] -> ReaderT SqlBackend m ()
forall backend (m :: * -> *) record.
(PersistQueryWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record] -> ReaderT backend m ()
deleteWhere [EntityField record sid
idField EntityField record sid -> sid -> Filter record
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. sid
sid]
      Set sid -> ReaderT SqlBackend m (Set sid)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Set sid
s

-- | Setup an unsynced client store
--
-- You shouldn't need this.
setupUnsyncedClientQuery ::
  ( PersistEntity clientRecord,
    PersistEntityBackend clientRecord ~ SqlBackend,
    MonadIO m
  ) =>
  -- | How to insert a _new_ record
  (a -> clientRecord) ->
  [a] ->
  SqlPersistT m ()
setupUnsyncedClientQuery :: (a -> clientRecord) -> [a] -> SqlPersistT m ()
setupUnsyncedClientQuery a -> clientRecord
func = (a -> ReaderT SqlBackend m (Key clientRecord))
-> [a] -> SqlPersistT m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (clientRecord -> ReaderT SqlBackend m (Key clientRecord)
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m (Key record)
insert (clientRecord -> ReaderT SqlBackend m (Key clientRecord))
-> (a -> clientRecord)
-> a
-> ReaderT SqlBackend m (Key clientRecord)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> clientRecord
func)

-- | Setup a client store
--
-- You shouldn't need this.
setupClientQuery ::
  ( PersistEntity clientRecord,
    PersistEntityBackend clientRecord ~ SqlBackend,
    MonadIO m
  ) =>
  -- | Create an un-deleted unsynced record on the client side
  (a -> clientRecord) ->
  -- | Create an un-deleted synced record on the client side
  (sid -> a -> clientRecord) ->
  -- | Create an deleted synced record on the client side
  (sid -> clientRecord) ->
  ClientStore (Key clientRecord) sid a ->
  SqlPersistT m ()
setupClientQuery :: (a -> clientRecord)
-> (sid -> a -> clientRecord)
-> (sid -> clientRecord)
-> ClientStore (Key clientRecord) sid a
-> SqlPersistT m ()
setupClientQuery a -> clientRecord
funcU sid -> a -> clientRecord
funcS sid -> clientRecord
funcD ClientStore {Map sid a
Map (Key clientRecord) a
Set sid
clientStoreAdded :: forall ci si a. ClientStore ci si a -> Map ci a
clientStoreSynced :: forall ci si a. ClientStore ci si a -> Map si a
clientStoreDeleted :: forall ci si a. ClientStore ci si a -> Set si
clientStoreDeleted :: Set sid
clientStoreSynced :: Map sid a
clientStoreAdded :: Map (Key clientRecord) a
..} = do
  [(Key clientRecord, a)]
-> ((Key clientRecord, a) -> SqlPersistT m ()) -> SqlPersistT m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Map (Key clientRecord) a -> [(Key clientRecord, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map (Key clientRecord) a
clientStoreAdded) (((Key clientRecord, a) -> SqlPersistT m ()) -> SqlPersistT m ())
-> ((Key clientRecord, a) -> SqlPersistT m ()) -> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ \(Key clientRecord
cid, a
st) ->
    Key clientRecord -> clientRecord -> SqlPersistT m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> record -> ReaderT backend m ()
insertKey
      Key clientRecord
cid
      (a -> clientRecord
funcU a
st)
  [(sid, a)] -> ((sid, a) -> SqlPersistT m ()) -> SqlPersistT m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Map sid a -> [(sid, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map sid a
clientStoreSynced) (((sid, a) -> SqlPersistT m ()) -> SqlPersistT m ())
-> ((sid, a) -> SqlPersistT m ()) -> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ \(sid
sid, a
st) ->
    clientRecord -> SqlPersistT m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m ()
insert_ (sid -> a -> clientRecord
funcS sid
sid a
st)
  [sid] -> (sid -> SqlPersistT m ()) -> SqlPersistT m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Set sid -> [sid]
forall a. Set a -> [a]
S.toList Set sid
clientStoreDeleted) ((sid -> SqlPersistT m ()) -> SqlPersistT m ())
-> (sid -> SqlPersistT m ()) -> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ \sid
sid ->
    clientRecord -> SqlPersistT m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m ()
insert_ (sid -> clientRecord
funcD sid
sid)

-- | Get a client store
--
-- You shouldn't need this.
clientGetStoreQuery ::
  ( Ord sid,
    PersistEntity clientRecord,
    PersistField sid,
    PersistEntityBackend clientRecord ~ SqlBackend,
    MonadIO m
  ) =>
  -- | How to red a record
  (clientRecord -> a) ->
  -- | The server id field
  EntityField clientRecord (Maybe sid) ->
  -- | The deleted field
  EntityField clientRecord Bool ->
  SqlPersistT m (ClientStore (Key clientRecord) sid a)
clientGetStoreQuery :: (clientRecord -> a)
-> EntityField clientRecord (Maybe sid)
-> EntityField clientRecord Bool
-> SqlPersistT m (ClientStore (Key clientRecord) sid a)
clientGetStoreQuery clientRecord -> a
func EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord Bool
deletedField = do
  Map (Key clientRecord) a
clientStoreAdded <-
    [(Key clientRecord, a)] -> Map (Key clientRecord) a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Key clientRecord, a)] -> Map (Key clientRecord) a)
-> ([Entity clientRecord] -> [(Key clientRecord, a)])
-> [Entity clientRecord]
-> Map (Key clientRecord) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity clientRecord -> (Key clientRecord, a))
-> [Entity clientRecord] -> [(Key clientRecord, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Entity Key clientRecord
cid clientRecord
ct) -> (Key clientRecord
cid, clientRecord -> a
func clientRecord
ct))
      ([Entity clientRecord] -> Map (Key clientRecord) a)
-> ReaderT SqlBackend m [Entity clientRecord]
-> ReaderT SqlBackend m (Map (Key clientRecord) a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter clientRecord]
-> [SelectOpt clientRecord]
-> ReaderT SqlBackend m [Entity clientRecord]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList
        [ EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Maybe sid
forall a. Maybe a
Nothing,
          EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
False
        ]
        []
  Map sid a
clientStoreSynced <-
    [(sid, a)] -> Map sid a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(sid, a)] -> Map sid a)
-> ([Entity clientRecord] -> [(sid, a)])
-> [Entity clientRecord]
-> Map sid a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity clientRecord -> Maybe (sid, a))
-> [Entity clientRecord] -> [(sid, a)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\e :: Entity clientRecord
e@(Entity Key clientRecord
_ clientRecord
ct) -> (,) (sid -> a -> (sid, a)) -> Maybe sid -> Maybe (a -> (sid, a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Entity clientRecord
e Entity clientRecord
-> Getting (Maybe sid) (Entity clientRecord) (Maybe sid)
-> Maybe sid
forall s a. s -> Getting a s a -> a
^. EntityField clientRecord (Maybe sid)
-> forall (f :: * -> *).
   Functor f =>
   (Maybe sid -> f (Maybe sid))
   -> Entity clientRecord -> f (Entity clientRecord)
forall record field.
PersistEntity record =>
EntityField record field
-> forall (f :: * -> *).
   Functor f =>
   (field -> f field) -> Entity record -> f (Entity record)
fieldLens EntityField clientRecord (Maybe sid)
serverIdField) Maybe (a -> (sid, a)) -> Maybe a -> Maybe (sid, a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (clientRecord -> a
func clientRecord
ct))
      ([Entity clientRecord] -> Map sid a)
-> ReaderT SqlBackend m [Entity clientRecord]
-> ReaderT SqlBackend m (Map sid a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter clientRecord]
-> [SelectOpt clientRecord]
-> ReaderT SqlBackend m [Entity clientRecord]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList
        [ EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
!=. Maybe sid
forall a. Maybe a
Nothing,
          EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
False
        ]
        []
  Set sid
clientStoreDeleted <-
    [sid] -> Set sid
forall a. Ord a => [a] -> Set a
S.fromList ([sid] -> Set sid)
-> ([Entity clientRecord] -> [sid])
-> [Entity clientRecord]
-> Set sid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity clientRecord -> Maybe sid)
-> [Entity clientRecord] -> [sid]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\Entity clientRecord
e -> Entity clientRecord
e Entity clientRecord
-> Getting (Maybe sid) (Entity clientRecord) (Maybe sid)
-> Maybe sid
forall s a. s -> Getting a s a -> a
^. EntityField clientRecord (Maybe sid)
-> forall (f :: * -> *).
   Functor f =>
   (Maybe sid -> f (Maybe sid))
   -> Entity clientRecord -> f (Entity clientRecord)
forall record field.
PersistEntity record =>
EntityField record field
-> forall (f :: * -> *).
   Functor f =>
   (field -> f field) -> Entity record -> f (Entity record)
fieldLens EntityField clientRecord (Maybe sid)
serverIdField)
      ([Entity clientRecord] -> Set sid)
-> ReaderT SqlBackend m [Entity clientRecord]
-> ReaderT SqlBackend m (Set sid)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter clientRecord]
-> [SelectOpt clientRecord]
-> ReaderT SqlBackend m [Entity clientRecord]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList
        [ EntityField clientRecord (Maybe sid)
serverIdField EntityField clientRecord (Maybe sid)
-> Maybe sid -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
!=. Maybe sid
forall a. Maybe a
Nothing,
          EntityField clientRecord Bool
deletedField EntityField clientRecord Bool -> Bool -> Filter clientRecord
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Bool
True
        ]
        []
  ClientStore (Key clientRecord) sid a
-> SqlPersistT m (ClientStore (Key clientRecord) sid a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ClientStore :: forall ci si a.
Map ci a -> Map si a -> Set si -> ClientStore ci si a
ClientStore {Map sid a
Map (Key clientRecord) a
Set sid
clientStoreDeleted :: Set sid
clientStoreSynced :: Map sid a
clientStoreAdded :: Map (Key clientRecord) a
clientStoreAdded :: Map (Key clientRecord) a
clientStoreSynced :: Map sid a
clientStoreDeleted :: Set sid
..}

-- | Get the server store from the database
--
-- You shouldn't need this.
serverGetStoreQuery ::
  ( PersistEntity record,
    PersistEntityBackend record ~ SqlBackend,
    MonadIO m
  ) =>
  -- | How to read a record
  (record -> a) ->
  SqlPersistT m (ServerStore (Key record) a)
serverGetStoreQuery :: (record -> a) -> SqlPersistT m (ServerStore (Key record) a)
serverGetStoreQuery record -> a
func = Map (Key record) a -> ServerStore (Key record) a
forall si a. Map si a -> ServerStore si a
ServerStore (Map (Key record) a -> ServerStore (Key record) a)
-> ([Entity record] -> Map (Key record) a)
-> [Entity record]
-> ServerStore (Key record) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Key record, a)] -> Map (Key record) a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Key record, a)] -> Map (Key record) a)
-> ([Entity record] -> [(Key record, a)])
-> [Entity record]
-> Map (Key record) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Entity record -> (Key record, a))
-> [Entity record] -> [(Key record, a)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Entity Key record
stid record
st) -> (Key record
stid, record -> a
func record
st)) ([Entity record] -> ServerStore (Key record) a)
-> ReaderT SqlBackend m [Entity record]
-> SqlPersistT m (ServerStore (Key record) a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Filter record]
-> [SelectOpt record] -> ReaderT SqlBackend m [Entity record]
forall record backend (m :: * -> *).
(MonadIO m, PersistQueryRead backend,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m [Entity record]
selectList [] []

-- | Set up a server store in the database.
--
-- You shouldn't need this.
-- This uses 'insertKey' function and is therefore unsafe.
setupServerQuery ::
  ( PersistEntity record,
    PersistEntityBackend record ~ SqlBackend,
    MonadIO m
  ) =>
  -- | How to write a record
  (a -> record) ->
  ServerStore (Key record) a ->
  SqlPersistT m ()
setupServerQuery :: (a -> record) -> ServerStore (Key record) a -> SqlPersistT m ()
setupServerQuery a -> record
func ServerStore {Map (Key record) a
serverStoreItems :: forall si a. ServerStore si a -> Map si a
serverStoreItems :: Map (Key record) a
..} = [(Key record, a)]
-> ((Key record, a) -> SqlPersistT m ()) -> SqlPersistT m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Map (Key record) a -> [(Key record, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map (Key record) a
serverStoreItems) (((Key record, a) -> SqlPersistT m ()) -> SqlPersistT m ())
-> ((Key record, a) -> SqlPersistT m ()) -> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ \(Key record
i, a
e) -> SqlPersistT m () -> SqlPersistT m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (SqlPersistT m () -> SqlPersistT m ())
-> SqlPersistT m () -> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ Key record -> record -> SqlPersistT m ()
forall backend record (m :: * -> *).
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> record -> ReaderT backend m ()
insertKey Key record
i (record -> SqlPersistT m ()) -> record -> SqlPersistT m ()
forall a b. (a -> b) -> a -> b
$ a -> record
func a
e