eved: A value level web framework

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

A value level web framework in the style of servant


[Skip to Readme]

Properties

Versions 0.0.1.0, 0.0.1.1, 0.0.2.0, 0.0.2.1, 0.0.3.0, 0.0.4.0
Change log None available
Dependencies aeson (>=1.3.1.1 && <1.6), base (>=4.7 && <5), bytestring (>=0.10.8.2 && <0.11), case-insensitive (>=1.2.0.20 && <1.3), http-api-data (>=0.3.8.1 && <0.5), http-client (>=0.5.14 && <0.7), http-media (>=0.7.1.3 && <0.9), http-types (>=0.12.2 && <0.13), invariant (>=0.5 && <0.6), mtl (>=2.2.2 && <2.3), text (>=1.2.3.1 && <1.3), wai (>=3.2.1.2 && <3.3) [details]
License BSD-3-Clause
Copyright 2021 Ben Levy
Author Ben Levy
Maintainer ben@foxhound.systems
Category Web
Home page https://github.com/foxhound-systems/eved#readme
Source repo head: git clone https://github.com/foxhound-systems/eved
Uploaded by belevy at 2021-10-25T22:08:28Z

Modules

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for eved-0.0.4.0

[back to package description]

Eved - A Value Level Servant Replacement

Eved is an API definition eDSL in the spirit of Servant. The main difference from Servant is that Eved is a value level API, whereas Servant relies very heavily on fancy type level programming.

Eved is highly extensible (both in terms of implementations and new terms) thanks to its utilization of the so called final tagless encoding.

Example

Api Definition

import           Data.Text              (Text)
import           Web.Eved
import qualified Web.Eved.ContentType   as CT
import qualified Web.Eved.QueryParam    as QP
import qualified Web.Eved.UrlElement    as UE

type Api m =
       (Integer -> Integer -> m Integer)
  :<|> (Text    -> Integer -> m Integer)
  :<|> (Text    -> Integer -> m Integer)

api :: Eved api m => api (Api m)
api =
      (lit "v1" .</> capture "captureNum" UE.integer .</> queryParam "arg1" QP.integer .</> get [CT.json @Integer])
 .<|> (lit "v1" .</> capture "captureText" UE.text .</> reqBody [CT.json @Integer] .</> post [CT.json @Integer])
 .<|> (lit "v2" .</> capture "captureText" UE.text .</> queryParam "arg1" QP.integer .</> get [CT.json @Integer])

Client

import           Web.Eved.Client

v1CaptureNum :<|> v1CaptureText :<|> v2CaptureText = getClient api "http://localhost:3000"

Server

import           Control.Monad.IO.Class
import           Control.Monad.Reader
import           Web.Eved.Server
import           Network.Wai.Handler.Warp

serve :: IO ()
serve = run 3000 $ server (`runReaderT` (Env 100)) handlers api

data Env = Env
    { envSecret :: Integer
    }

handlers :: (MonadIO m, MonadReader Env m) => Api m
handlers =   (\a b -> pure $ a + b)
        :<|> (\_ i -> fmap ((+) i) (asks envSecret))
        :<|> (\_ i -> pure i)

Prior Art

TODO

How to extend the language

TODO