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


-- | Another Haskell web framework for rapid development
--   
--   This toolbox provides everything you need to get a quick start into
--   web hacking with haskell:
--   
--   <ul>
--   <li>fast routing</li>
--   <li>middleware</li>
--   <li>json</li>
--   <li>sessions</li>
--   <li>cookies</li>
--   <li>database helper</li>
--   <li>csrf-protection</li>
--   </ul>
--   
--   A tutorial is available at <a>spock.li</a>
@package Spock
@version 0.13.0.0

module Web.Spock.Internal.SessionVault
class (Eq (SessionKey s), Hashable (SessionKey s)) => IsSession s where {
    type family SessionKey s :: *;
}
getSessionKey :: IsSession s => s -> SessionKey s
newtype SessionVault s
SessionVault :: Map (SessionKey s) s -> SessionVault s
[unSessionVault] :: SessionVault s -> Map (SessionKey s) s

-- | Create a new session vault
newSessionVault :: STM (SessionVault s)

-- | Load a session
loadSession :: IsSession s => SessionKey s -> SessionVault s -> STM (Maybe s)

-- | Store a session, overwriting any previous values
storeSession :: IsSession s => s -> SessionVault s -> STM ()

-- | Removea session
deleteSession :: IsSession s => SessionKey s -> SessionVault s -> STM ()

-- | Get all sessions as list
toList :: SessionVault s -> STM [s]

-- | Remove all sessions that do not match the predicate
filterSessions :: IsSession s => (s -> Bool) -> SessionVault s -> STM ()

-- | Perform action on all sessions
mapSessions :: IsSession s => (s -> STM s) -> SessionVault s -> STM ()
newStmSessionStore' :: IO (SessionStore (Session conn sess st) STM)
newStmSessionStore :: IO (SessionStoreInstance (Session conn sess st))
instance Web.Spock.Internal.SessionVault.IsSession (Web.Spock.Internal.Types.Session conn sess st)

module Web.Spock.Internal.SessionManager
createSessionManager :: MonadIO m => SessionCfg conn sess st -> SessionIf m -> IO (SessionManager m conn sess st)
withSessionManager :: MonadIO m => SessionCfg conn sess st -> SessionIf m -> (SessionManager m conn sess st -> IO a) -> IO a
type SessionId = Text
data Session conn sess st
Session :: !SessionId -> !Text -> !UTCTime -> !sess -> Session conn sess st
[sess_id] :: Session conn sess st -> !SessionId
[sess_csrfToken] :: Session conn sess st -> !Text
[sess_validUntil] :: Session conn sess st -> !UTCTime
[sess_data] :: Session conn sess st -> !sess
data SessionManager m conn sess st
SessionManager :: m SessionId -> m Text -> m () -> m sess -> sess -> m () -> forall a. (sess -> (sess, a)) -> m a -> (forall n. Monad n => sess -> n sess) -> m () -> MonadIO m => m () -> Middleware -> IO () -> SessionManager m conn sess st
[sm_getSessionId] :: SessionManager m conn sess st -> m SessionId
[sm_getCsrfToken] :: SessionManager m conn sess st -> m Text
[sm_regenerateSessionId] :: SessionManager m conn sess st -> m ()
[sm_readSession] :: SessionManager m conn sess st -> m sess
[sm_writeSession] :: SessionManager m conn sess st -> sess -> m ()
[sm_modifySession] :: SessionManager m conn sess st -> forall a. (sess -> (sess, a)) -> m a
[sm_mapSessions] :: SessionManager m conn sess st -> (forall n. Monad n => sess -> n sess) -> m ()
[sm_clearAllSessions] :: SessionManager m conn sess st -> MonadIO m => m ()
[sm_middleware] :: SessionManager m conn sess st -> Middleware
[sm_closeSessionManager] :: SessionManager m conn sess st -> IO ()
data SessionIf m
SessionIf :: forall a. Key a -> m (Maybe a) -> (Vault -> Vault) -> m () -> MultiHeader -> ByteString -> m () -> IO (Key SessionId) -> SessionIf m
[si_queryVault] :: SessionIf m -> forall a. Key a -> m (Maybe a)
[si_modifyVault] :: SessionIf m -> (Vault -> Vault) -> m ()
[si_setRawMultiHeader] :: SessionIf m -> MultiHeader -> ByteString -> m ()
[si_vaultKey] :: SessionIf m -> IO (Key SessionId)

module Web.Spock.Config

-- | Spock configuration, use <tt>defaultSpockCfg</tt> and change single
--   values if needed
data SpockCfg conn sess st
SpockCfg :: st -> PoolOrConn conn -> SessionCfg conn sess st -> Maybe Word64 -> Status -> ActionCtxT () IO () -> Text -> IO () -> Bool -> Text -> Text -> SpockCfg conn sess st

-- | initial application global state
[spc_initialState] :: SpockCfg conn sess st -> st

-- | See <a>PoolOrConn</a>
[spc_database] :: SpockCfg conn sess st -> PoolOrConn conn

-- | See <a>SessionCfg</a>
[spc_sessionCfg] :: SpockCfg conn sess st -> SessionCfg conn sess st

-- | Maximum request size in bytes. <a>Nothing</a> means no limit. Defaults
--   to 5 MB in <tt>defaultSpockCfg</tt>.
[spc_maxRequestSize] :: SpockCfg conn sess st -> Maybe Word64

-- | Custom error handlers for implicit errors such as not matching routes
--   or exceptions during a request handler run.
[spc_errorHandler] :: SpockCfg conn sess st -> Status -> ActionCtxT () IO ()

-- | Function that should be called to log errors.
[spc_logError] :: SpockCfg conn sess st -> Text -> IO ()

-- | When set to true, all non GET request will require either an
--   HTTP-Header <a>spc_csrfHeaderName</a> or a POST-Parameter
--   <a>spc_csrfPostName</a> to be set to the value aquired by
--   <tt>getCsrfToken</tt>
[spc_csrfProtection] :: SpockCfg conn sess st -> Bool

-- | see <a>spc_csrfHeaderName</a>
[spc_csrfHeaderName] :: SpockCfg conn sess st -> Text

-- | see <a>spc_csrfPostName</a>
[spc_csrfPostName] :: SpockCfg conn sess st -> Text

-- | Spock configuration with reasonable defaults such as a basic error
--   page and 5MB request body limit. IMPORTANT: CSRF Protection is turned
--   off by default for now to not break any existing Spock applications.
--   Consider turning it on manually as it will become the default in the
--   future.
defaultSpockCfg :: sess -> PoolOrConn conn -> st -> IO (SpockCfg conn sess st)

-- | You can feed Spock with either a connection pool, or instructions on
--   how to build a connection pool. See <a>ConnBuilder</a>
data PoolOrConn a
[PCPool] :: Pool a -> PoolOrConn a
[PCConn] :: ConnBuilder a -> PoolOrConn a
[PCNoDatabase] :: PoolOrConn ()

-- | The ConnBuilder instructs Spock how to create or close a database
--   connection.
data ConnBuilder a
ConnBuilder :: IO a -> a -> IO () -> PoolCfg -> ConnBuilder a
[cb_createConn] :: ConnBuilder a -> IO a
[cb_destroyConn] :: ConnBuilder a -> a -> IO ()
[cb_poolConfiguration] :: ConnBuilder a -> PoolCfg

-- | If Spock should take care of connection pooling, you need to configure
--   it depending on what you need.
data PoolCfg
PoolCfg :: Int -> Int -> NominalDiffTime -> PoolCfg
[pc_stripes] :: PoolCfg -> Int
[pc_resPerStripe] :: PoolCfg -> Int
[pc_keepOpenTime] :: PoolCfg -> NominalDiffTime

-- | Session configuration with reasonable defaults and an stm based
--   session store
defaultSessionCfg :: a -> IO (SessionCfg conn a st)

-- | Configuration for the session manager
data SessionCfg conn a st
SessionCfg :: Text -> NominalDiffTime -> Int -> Bool -> a -> SessionStoreInstance (Session conn a st) -> NominalDiffTime -> SessionHooks a -> SessionCfg conn a st

-- | name of the client side cookie
[sc_cookieName] :: SessionCfg conn a st -> Text

-- | how long shoud a client session live
[sc_sessionTTL] :: SessionCfg conn a st -> NominalDiffTime

-- | entropy of the session id sent to the client
[sc_sessionIdEntropy] :: SessionCfg conn a st -> Int

-- | if this is true, every page reload will renew the session time to live
--   counter
[sc_sessionExpandTTL] :: SessionCfg conn a st -> Bool

-- | initial session for visitors
[sc_emptySession] :: SessionCfg conn a st -> a

-- | storage interface for sessions
[sc_store] :: SessionCfg conn a st -> SessionStoreInstance (Session conn a st)

-- | how often should the session manager check for dangeling dead sessions
[sc_housekeepingInterval] :: SessionCfg conn a st -> NominalDiffTime

-- | hooks into the session manager
[sc_hooks] :: SessionCfg conn a st -> SessionHooks a

-- | NOP session hooks
defaultSessionHooks :: SessionHooks a

-- | Hook into the session manager to trigger custom behavior
data SessionHooks a
SessionHooks :: HashMap SessionId a -> IO () -> SessionHooks a
[sh_removed] :: SessionHooks a -> HashMap SessionId a -> IO ()
data SessionStore sess tx
SessionStore :: forall a. tx a -> IO a -> SessionId -> tx (Maybe sess) -> SessionId -> tx () -> sess -> tx () -> tx [sess] -> (sess -> Bool) -> tx () -> (sess -> tx sess) -> tx () -> SessionStore sess tx
[ss_runTx] :: SessionStore sess tx -> forall a. tx a -> IO a
[ss_loadSession] :: SessionStore sess tx -> SessionId -> tx (Maybe sess)
[ss_deleteSession] :: SessionStore sess tx -> SessionId -> tx ()
[ss_storeSession] :: SessionStore sess tx -> sess -> tx ()
[ss_toList] :: SessionStore sess tx -> tx [sess]
[ss_filterSessions] :: SessionStore sess tx -> (sess -> Bool) -> tx ()
[ss_mapSessions] :: SessionStore sess tx -> (sess -> tx sess) -> tx ()
data SessionStoreInstance sess
[SessionStoreInstance] :: forall sess tx. (Monad tx, Functor tx, Applicative tx) => SessionStore sess tx -> SessionStoreInstance sess
newStmSessionStore :: IO (SessionStoreInstance (Session conn sess st))

module Web.Spock.SessionActions
type SessionId = Text

-- | Regenerate the users sessionId. This preserves all stored data. Call
--   this prior to logging in a user to prevent session fixation attacks.
sessionRegenerateId :: SpockActionCtx ctx conn sess st ()

-- | Get the current users sessionId. Note that this ID should only be
--   shown to it's owner as otherwise sessions can be hijacked.
getSessionId :: SpockActionCtx ctx conn sess st SessionId

-- | Read the stored session
readSession :: SpockActionCtx ctx conn sess st sess

-- | Write to the current session. Note that all data is stored on the
--   server. The user only reciedes a sessionId to be identified.
writeSession :: forall sess ctx conn st. sess -> SpockActionCtx ctx conn sess st ()

-- | Modify the stored session
modifySession :: (sess -> sess) -> SpockActionCtx ctx conn sess st ()

-- | Modify the stored session and return a value
modifySession' :: (sess -> (sess, a)) -> SpockActionCtx ctx conn sess st a

-- | Modify the stored session and return the new value after modification
modifyReadSession :: (sess -> sess) -> SpockActionCtx ctx conn sess st sess

-- | Apply a transformation to all sessions. Be careful with this, as this
--   may cause many STM transaction retries.
mapAllSessions :: (forall m. Monad m => sess -> m sess) -> SpockActionCtx ctx conn sess st ()

-- | Globally delete all existing sessions. This is useful for example if
--   you want to require all users to relogin
clearAllSessions :: SpockActionCtx ctx conn sess st ()

module Web.Spock

-- | Run a Spock application. Basically just a wrapper around <a>run</a>.
runSpock :: Port -> IO Middleware -> IO ()

-- | Like <a>runSpock</a>, but does not display the banner "Spock is
--   running on port XXX" on stdout.
runSpockNoBanner :: Port -> IO Middleware -> IO ()

-- | Convert a middleware to an application. All failing requests will
--   result in a 404 page
spockAsApp :: IO Middleware -> IO Application

-- | Create a spock application using a given db storageLayer and an
--   initial state. Spock works with database libraries that already
--   implement connection pooling and with those that don't come with it
--   out of the box. For more see the <a>PoolOrConn</a> type. Use
--   <tt>runSpock</tt> to run the app or <tt>spockAsApp</tt> to create a
--   <tt>Wai.Application</tt>
spock :: forall conn sess st. SpockCfg conn sess st -> SpockM conn sess st () -> IO Middleware
type SpockM conn sess st = SpockCtxM () conn sess st
type SpockCtxM ctx conn sess st = SpockCtxT ctx (WebStateM conn sess st)
data Path (as :: [*]) (pathState :: PathState)

-- | The root of a path piece. Use to define a handler for "/"
root :: Path ([] :: [*]) Open
type Var a = Path a : ([] :: [*]) Open

-- | A route parameter
var :: (Typeable a, FromHttpApiData a) => Path a : ([] :: [*]) Open

-- | A static route piece
static :: String -> Path ([] :: [*]) Open

-- | Combine two path components
(<//>) :: () => Path as Open -> Path bs ps -> Path Append as bs ps

-- | Matches the rest of the route. Should be the last part of the path.
wildcard :: Path Text : ([] :: [*]) Closed

-- | Render a route applying path pieces
renderRoute :: AllHave ToHttpApiData as => Path as Open -> HVectElim as Text

-- | Specify an action that will be run before all subroutes. It can modify
--   the requests current context
prehook :: (RouteM t, MonadIO m) => ActionCtxT ctx m ctx' -> t ctx' m () -> t ctx m ()
type RouteSpec xs ps ctx conn sess st = Path xs ps -> HVectElim xs (SpockActionCtx ctx conn sess st ()) -> SpockCtxM ctx conn sess st ()

-- | Specify an action that will be run when the HTTP verb <a>GET</a> and
--   the given route match
get :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when the HTTP verb <a>POST</a> and
--   the given route match
post :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when the HTTP verb 'GET'/'POST' and
--   the given route match
getpost :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when the HTTP verb <a>HEAD</a> and
--   the given route match
head :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when the HTTP verb <a>PUT</a> and
--   the given route match
put :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when the HTTP verb <a>DELETE</a>
--   and the given route match
delete :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when the HTTP verb <a>PATCH</a> and
--   the given route match
patch :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when a standard HTTP verb and the
--   given route match
hookRoute :: HasRep xs => StdMethod -> RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when a custom HTTP verb and the
--   given route match
hookRouteCustom :: HasRep xs => Text -> RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run when a standard HTTP verb matches
--   but no defined route matches. The full path is passed as an argument
hookAny :: StdMethod -> ([Text] -> SpockActionCtx ctx conn sess st ()) -> SpockCtxM ctx conn sess st ()

-- | Specify an action that will be run when a custom HTTP verb matches but
--   no defined route matches. The full path is passed as an argument
hookAnyCustom :: Text -> ([Text] -> SpockActionCtx ctx conn sess st ()) -> SpockCtxM ctx conn sess st ()

-- | Specify an action that will be run regardless of the HTTP verb
hookRouteAll :: HasRep xs => RouteSpec xs ps ctx conn sess st

-- | Specify an action that will be run regardless of the HTTP verb and no
--   defined route matches. The full path is passed as an argument
hookAnyAll :: ([Text] -> SpockActionCtx ctx conn sess st ()) -> SpockCtxM ctx conn sess st ()

-- | HTTP standard method (as defined by RFC 2616, and PATCH which is
--   defined by RFC 5789).
data StdMethod
GET :: StdMethod
POST :: StdMethod
HEAD :: StdMethod
PUT :: StdMethod
DELETE :: StdMethod
TRACE :: StdMethod
CONNECT :: StdMethod
OPTIONS :: StdMethod
PATCH :: StdMethod

-- | Hook wai middleware into Spock
middleware :: (RouteM t, Monad m) => Middleware -> t ctx m ()

-- | The <a>SpockAction</a> is a specialisation of <a>SpockActionCtx</a>
--   with a '()' context.
type SpockAction conn sess st = SpockActionCtx () conn sess st

-- | The <a>SpockActionCtx</a> is the monad of all route-actions. You have
--   access to the context of the request and database, session and state
--   of your application.
type SpockActionCtx ctx conn sess st = ActionCtxT ctx (WebStateM conn sess st)
class HasSpock m where {
    type family SpockConn m :: *;
    type family SpockState m :: *;
    type family SpockSession m :: *;
}

-- | Give you access to a database connectin from the connection pool. The
--   connection is released back to the pool once the function terminates.
runQuery :: HasSpock m => (SpockConn m -> IO a) -> m a

-- | Read the application's state. If you wish to have mutable state, you
--   could use a <tt>TVar</tt> from the STM packge.
getState :: HasSpock m => m (SpockState m)

-- | Get the session manager
getSessMgr :: HasSpock m => m (SpockSessionManager (SpockConn m) (SpockSession m) (SpockState m))

-- | Get the Spock configuration
getSpockCfg :: HasSpock m => m (SpockCfg (SpockConn m) (SpockSession m) (SpockState m))
data SessionManager m conn sess st

-- | Get the CSRF token for the current user. This token must be sent on
--   all non GET requests via a post parameter or HTTP-Header if
--   <a>spc_csrfProtection</a> is turned on. See configuration
--   <a>SpockCfg</a> documentation for more information
getCsrfToken :: SpockActionCtx ctx conn sess st Text

-- | Get the CSRF token sent by the client. You should not need to call
--   this manually if <a>spc_csrfProtection</a> is turned on.
getClientCsrfToken :: SpockActionCtx ctx conn sess st (Maybe Text)

-- | Check that the client sent a valid CSRF token. You should not need to
--   call this manually in non GET requests if <a>spc_csrfProtection</a> is
--   turned on.
csrfCheck :: SpockActionCtx ctx conn sess st ()
type WebStateM conn sess st = WebStateT conn sess st (ResourceT IO)
data WebStateT conn sess st m a
data WebState conn sess st

-- | Read the heart of Spock. This is useful if you want to construct your
--   own monads that work with <a>runQuery</a> and <a>getState</a> using
--   <a>runSpockIO</a>
getSpockHeart :: MonadTrans t => t (WebStateM conn sess st) (WebState conn sess st)

-- | Run an action inside of Spocks core monad. This allows you to use
--   <a>runQuery</a> and <a>getState</a>
runSpockIO :: WebState conn sess st -> WebStateM conn sess st a -> IO a

-- | Read the connection pool of Spock. This is useful if you want to
--   construct your own monads that work with <a>runQuery</a> and
--   <a>getState</a> using <a>runSpockIO</a>
getSpockPool :: MonadTrans t => t (WebStateM conn sess st) (Pool conn)
