git.iko.soy/typeable/servant
on master help sign in
polish up cabal file, add README
commit0a2d3bc12c2bba0e66e4a2238818567d351f6a48 authorAlp Mestanogullari <alpmestan@gmail.com> dateMon 8 Dec 2014, 12:01 (12 years ago) parentffb3392
2 files changed+190−4
README.md+96 servant-jquery.cabal+94−4
README.mdnew file+96
@@ -0,0 +1,96 @@
1+# servant-jquery
2+
3+[![Build Status](https://secure.travis-ci.org/haskell-servant/servant-jquery.svg)](http://travis-ci.org/haskell-servant/servant-jquery)
4+
5+![servant](https://raw.githubusercontent.com/haskell-servant/servant/master/servant.png)
6+
7+This library lets you derive automatically (JQuery based) Javascript functions that let you query each endpoint of a *servant* webservice.
8+
9+## Example
10+
11+Read more about the following example [here](https://github.com/haskell-servant/servant-jquery/tree/master/examples#examples).
12+
13+``` haskell
14+{-# LANGUAGE DataKinds #-}
15+{-# LANGUAGE TypeOperators #-}
16+{-# LANGUAGE DeriveGeneric #-}
17+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
18+
19+import Control.Concurrent.STM
20+import Control.Monad.IO.Class
21+import Data.Aeson
22+import Data.Proxy
23+import GHC.Generics
24+import Network.Wai.Handler.Warp (run)
25+import Servant
26+import Servant.JQuery
27+import System.FilePath
28+
29+-- * A simple Counter data type
30+newtype Counter = Counter { value :: Int }
31+ deriving (Generic, Show, Num)
32+
33+instance ToJSON Counter
34+
35+-- * Shared counter operations
36+
37+-- Creating a counter that starts from 0
38+newCounter :: IO (TVar Counter)
39+newCounter = newTVarIO 0
40+
41+-- Increasing the counter by 1
42+counterPlusOne :: MonadIO m => TVar Counter -> m Counter
43+counterPlusOne counter = liftIO . atomically $ do
44+ oldValue <- readTVar counter
45+ let newValue = oldValue + 1
46+ writeTVar counter newValue
47+ return newValue
48+
49+currentValue :: MonadIO m => TVar Counter -> m Counter
50+currentValue counter = liftIO $ readTVarIO counter
51+
52+-- * Our API type
53+type TestApi = "counter" :> Post Counter -- endpoint for increasing the counter
54+ :<|> "counter" :> Get Counter -- endpoint to get the current value
55+ :<|> Raw -- used for serving static files
56+
57+testApi :: Proxy TestApi
58+testApi = Proxy
59+
60+-- * Server-side handler
61+
62+-- where our static files reside
63+www :: FilePath
64+www = "examples/www"
65+
66+-- defining handlers
67+server :: TVar Counter -> Server TestApi
68+server counter = counterPlusOne counter -- (+1) on the TVar
69+ :<|> currentValue counter -- read the TVar
70+ :<|> serveDirectory www -- serve static files
71+
72+runServer :: TVar Counter -- ^ shared variable for the counter
73+ -> Int -- ^ port the server should listen on
74+ -> IO ()
75+runServer var port = run port (serve testApi $ server var)
76+
77+-- * Generating the JQuery code
78+
79+incCounterJS :<|> currentValueJS :<|> _ = jquery testApi
80+
81+writeJS :: FilePath -> [AjaxReq] -> IO ()
82+writeJS fp functions = writeFile fp $
83+ concatMap generateJS functions
84+
85+main :: IO ()
86+main = do
87+ -- write the JS code to www/api.js at startup
88+ writeJS (www </> "api.js")
89+ [ incCounterJS, currentValueJS ]
90+
91+ -- setup a shared counter
92+ cnt <- newCounter
93+
94+ -- listen to requests on port 8080
95+ runServer cnt 8080
96+```
servant-jquery.cabal+94−4
@@ -1,8 +1,94 @@
11name: servant-jquery
22version: 0.2
33synopsis: Automatically derive jquery-based javascript functions to query servant webservices
4−description: Automatically derive jquery-based javascript functions to query servant webservices
5−homepage: http://github.com/alpmestan/servant
4+description:
5+ Automatically derive jquery-based javascript functions to query servant webservices.
6+ .
7+ Example below that serves the generated javascript to a webpage that lets you
8+ trigger webservice calls.
9+ .
10+ > {-# LANGUAGE DataKinds #-}
11+ > {-# LANGUAGE TypeOperators #-}
12+ > {-# LANGUAGE DeriveGeneric #-}
13+ > {-# LANGUAGE GeneralizedNewtypeDeriving #-}
14+ >
15+ > import Control.Concurrent.STM
16+ > import Control.Monad.IO.Class
17+ > import Data.Aeson
18+ > import Data.Proxy
19+ > import GHC.Generics
20+ > import Network.Wai.Handler.Warp (run)
21+ > import Servant
22+ > import Servant.JQuery
23+ > import System.FilePath
24+ >
25+ > -- * A simple Counter data type
26+ > newtype Counter = Counter { value :: Int }
27+ > deriving (Generic, Show, Num)
28+ >
29+ > instance ToJSON Counter
30+ >
31+ > -- * Shared counter operations
32+ >
33+ > -- Creating a counter that starts from 0
34+ > newCounter :: IO (TVar Counter)
35+ > newCounter = newTVarIO 0
36+ >
37+ > -- Increasing the counter by 1
38+ > counterPlusOne :: MonadIO m => TVar Counter -> m Counter
39+ > counterPlusOne counter = liftIO . atomically $ do
40+ > oldValue <- readTVar counter
41+ > let newValue = oldValue + 1
42+ > writeTVar counter newValue
43+ > return newValue
44+ >
45+ > currentValue :: MonadIO m => TVar Counter -> m Counter
46+ > currentValue counter = liftIO $ readTVarIO counter
47+ >
48+ > -- * Our API type
49+ > type TestApi = "counter" :> Post Counter -- endpoint for increasing the counter
50+ > :<|> "counter" :> Get Counter -- endpoint to get the current value
51+ > :<|> Raw -- used for serving static files
52+ >
53+ > testApi :: Proxy TestApi
54+ > testApi = Proxy
55+ >
56+ > -- * Server-side handler
57+ >
58+ > -- where our static files reside
59+ > www :: FilePath
60+ > www = "examples/www"
61+ >
62+ > -- defining handlers
63+ > server :: TVar Counter -> Server TestApi
64+ > server counter = counterPlusOne counter -- (+1) on the TVar
65+ > :<|> currentValue counter -- read the TVar
66+ > :<|> serveDirectory www -- serve static files
67+ >
68+ > runServer :: TVar Counter -- ^ shared variable for the counter
69+ > -> Int -- ^ port the server should listen on
70+ > -> IO ()
71+ > runServer var port = run port (serve testApi $ server var)
72+ >
73+ > -- * Generating the JQuery code
74+ >
75+ > incCounterJS :<|> currentValueJS :<|> _ = jquery testApi
76+ >
77+ > writeJS :: FilePath -> [AjaxReq] -> IO ()
78+ > writeJS fp functions = writeFile fp $
79+ > concatMap generateJS functions
80+ >
81+ > main :: IO ()
82+ > main = do
83+ > -- write the JS code to www/api.js at startup
84+ > writeJS (www </> "api.js")
85+ > [ incCounterJS, currentValueJS ]
86+ >
87+ > -- setup a shared counter
88+ > cnt <- newCounter
89+ >
90+ > -- listen to requests on port 8080
91+ > runServer cnt 8080
692license: BSD3
793license-file: LICENSE
894author: Alp Mestanogullari
@@ -11,15 +97,19 @@ copyright: 2014 Alp Mestanogullari
1197category: Web
1298build-type: Simple
1399cabal-version: >=1.10
100+homepage: http://haskell-servant.github.io/
101+Bug-reports: http://github.com/haskell-servant/servant-jquery/issues
102+source-repository head
103+ type: git
104+ location: http://github.com/haskell-servant/servant-jquery.git
14105
15106library
16107 exposed-modules: Servant.JQuery
17108 other-modules: Servant.JQuery.Internal
18− -- other-extensions:
19109 build-depends: base >=4.5 && <5, servant >= 0.2, lens >= 4
20110 hs-source-dirs: src
21111 default-language: Haskell2010
22− ghc-options: -O2 -Wall
112+ ghc-options: -Wall
23113
24114executable counter
25115 main-is: counter.hs