haskell-servant/servant-js

Name: servant-js

Owner: servant

Description: Automatically derive javascript functions to query servant webservices.

Created: 2016-10-08 13:33:15.0

Updated: 2018-05-18 09:20:01.0

Pushed: 2018-05-23 07:58:16.0

Homepage: null

Size: 217

Language: Haskell

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

servant-js

servant

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.

Example

Read more about the following example here.

LANGUAGE DataKinds #-}
LANGUAGE TypeOperators #-}
LANGUAGE DeriveGeneric #-}
LANGUAGE GeneralizedNewtypeDeriving #-}

rt Control.Concurrent.STM
rt Control.Monad.IO.Class
rt Data.Aeson
rt Data.Proxy
rt GHC.Generics
rt Network.Wai.Handler.Warp (run)
rt Servant
rt Servant.JS
rt System.FilePath

 A simple Counter data type
ype Counter = Counter { value :: Int }
riving (Generic, Show, Num)

ance ToJSON Counter

 Shared counter operations

reating a counter that starts from 0
ounter :: IO (TVar Counter)
ounter = newTVarIO 0

ncreasing the counter by 1
terPlusOne :: MonadIO m => TVar Counter -> m Counter
terPlusOne counter = liftIO . atomically $ do
dValue <- readTVar counter
t newValue = oldValue + 1
iteTVar counter newValue
turn newValue

entValue :: MonadIO m => TVar Counter -> m Counter
entValue counter = liftIO $ readTVarIO counter

 Our API type
 TestApi = "counter" :> Post '[JSON] Counter -- endpoint for increasing the counter
      :<|> "counter" :> Get  '[JSON] Counter -- endpoint to get the current value

 TestApi' = TestApi -- The API we want a JS handler for
       :<|> Raw     -- used for serving static files

his proxy only targets the proper endpoints of our API,
ot the static file serving bit
Api :: Proxy TestApi
Api = Proxy

his proxy targets everything
Api' :: Proxy TestApi'
Api' = Proxy

 Server-side handler

here our static files reside
:: FilePath
= "examples/www"

efining handlers
er :: TVar Counter -> Server TestApi
er counter = counterPlusOne counter     -- (+1) on the TVar
        :<|> currentValue counter       -- read the TVar

er' :: TVar Counter -> Server TestApi'
er' counter = server counter
         :<|> serveDirectory www         -- serve static files

erver :: TVar Counter -- ^ shared variable for the counter
      -> Int          -- ^ port the server should listen on
      -> IO ()
erver var port = run port (serve testApi' $ server' var)

 :: IO ()
 = do
 write the JS code to www/api.js at startup
iteJSForAPI testApi jquery (www </> "api.js")

 setup a shared counter
t <- newCounter

 listen to requests on port 8080
nServer cnt 8080

This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.