This library lets you derive automatically Javascript functions that let you query each endpoint of a servant webservice.
It contains a powerful system allowing you to generate functions for several frameworks (Angular, AXios, JQuery) as well as
vanilla (framework-free) javascript code.
{-# LANGUAGE DataKinds #-}{-# LANGUAGE TypeOperators #-}{-# LANGUAGE DeriveGeneric #-}{-# LANGUAGE GeneralizedNewtypeDeriving #-}import Control.Concurrent.STMimport Control.Monad.IO.Classimport Data.Aesonimport Data.Proxyimport GHC.Genericsimport Network.Wai.Handler.Warp (run)import Servantimport Servant.JSimport System.FilePath-- * A simple Counter data typenewtypeCounter = Counter{ value :: Int }deriving (Generic, Show, Num)
instanceToJSONCounter-- * Shared counter operations-- Creating a counter that starts from 0
newCounter :: IO(TVarCounter)
newCounter = newTVarIO 0
-- Increasing the counter by 1
counterPlusOne :: MonadIO m => TVarCounter -> m Counter
counterPlusOne counter = liftIO . atomically $ do
oldValue <- readTVar counter
let newValue = oldValue + 1
writeTVar counter newValue
return newValue
currentValue :: MonadIO m => TVarCounter -> m Counter
currentValue counter = liftIO $ readTVarIO counter
-- * Our API type
type TestApi = "counter" :> Post '[JSON] Counter-- endpoint for increasing the counter
:<|> "counter" :> Get '[JSON] Counter-- endpoint to get the current value
type TestApi' = TestApi-- The API we want a JS handler for
:<|> Raw-- used for serving static files-- this proxy only targets the proper endpoints of our API,-- not the static file serving bit
testApi :: ProxyTestApi
testApi = Proxy-- this proxy targets everything
testApi' :: ProxyTestApi'
testApi' = Proxy-- * Server-side handler-- where our static files reside
www :: FilePath
www = "examples/www"
-- defining handlers
server :: TVarCounter -> ServerTestApi
server counter = counterPlusOne counter -- (+1) on the TVar
:<|> currentValue counter -- read the TVar
server' :: TVarCounter -> ServerTestApi'
server' counter = server counter
:<|> serveDirectory www -- serve static files
runServer :: TVarCounter-- ^ shared variable for the counter
-> Int-- ^ port the server should listen on
-> IO()
runServer var port = run port (servetestApi' $ server'var)
main :: IO()
main = do
-- write the JS code to www/api.js at startup
writeJSForAPI testApi jquery (www </> "api.js")-- setup a shared counter
cnt <- newCounter
-- listen to requests on port 8080
runServer cnt 8080
Changes
0.9.4
servant-0.15 support
0.9.3
Remove check of responseType in vanilla backend
(#13, #14)