servant-jquery 0.2.1 → 0.2.2
raw patch · 5 files changed
+128/−6 lines, 5 filesdep +hspecdep +language-ecmascriptdep ~basedep ~servantdep ~servant-jquery
Dependencies added: hspec, language-ecmascript
Dependency ranges changed: base, servant, servant-jquery
Files
- CHANGELOG.md +5/−0
- README.md +96/−0
- servant-jquery.cabal +19/−3
- src/Servant/JQuery/Internal.hs +6/−3
- test/Spec.hs +2/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+0.2.2+-----++* Fix an issue where toplevel Raw endpoints would generate a JS function with no name (https://github.com/haskell-servant/servant-jquery/issues/2)+* Replace dots by _ in paths (https://github.com/haskell-servant/servant-jquery/issues/1)
+ README.md view
@@ -0,0 +1,96 @@+# servant-jquery++[](http://travis-ci.org/haskell-servant/servant-jquery)++++This library lets you derive automatically (JQuery based) Javascript functions that let you query each endpoint of a *servant* webservice.++## Example++Read more about the following example [here](https://github.com/haskell-servant/servant-jquery/tree/master/examples#examples).++``` haskell+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++import Control.Concurrent.STM+import Control.Monad.IO.Class+import Data.Aeson+import Data.Proxy+import GHC.Generics+import Network.Wai.Handler.Warp (run)+import Servant+import Servant.JQuery+import System.FilePath++-- * A simple Counter data type+newtype Counter = Counter { value :: Int }+ deriving (Generic, Show, Num)++instance ToJSON Counter++-- * Shared counter operations++-- Creating a counter that starts from 0+newCounter :: IO (TVar Counter)+newCounter = newTVarIO 0++-- Increasing the counter by 1+counterPlusOne :: MonadIO m => TVar Counter -> m Counter+counterPlusOne counter = liftIO . atomically $ do+ oldValue <- readTVar counter+ let newValue = oldValue + 1+ writeTVar counter newValue+ return newValue++currentValue :: MonadIO m => TVar Counter -> m Counter+currentValue counter = liftIO $ readTVarIO counter++-- * Our API type+type TestApi = "counter" :> Post Counter -- endpoint for increasing the counter+ :<|> "counter" :> Get Counter -- endpoint to get the current value+ :<|> Raw -- used for serving static files ++testApi :: Proxy TestApi+testApi = Proxy++-- * Server-side handler++-- where our static files reside+www :: FilePath+www = "examples/www"++-- defining handlers+server :: TVar Counter -> Server TestApi+server counter = counterPlusOne counter -- (+1) on the TVar+ :<|> currentValue counter -- read the TVar+ :<|> serveDirectory www -- serve static files++runServer :: TVar Counter -- ^ shared variable for the counter+ -> Int -- ^ port the server should listen on+ -> IO ()+runServer var port = run port (serve testApi $ server var)++-- * Generating the JQuery code++incCounterJS :<|> currentValueJS :<|> _ = jquery testApi++writeJS :: FilePath -> [AjaxReq] -> IO ()+writeJS fp functions = writeFile fp $+ concatMap generateJS functions++main :: IO ()+main = do+ -- write the JS code to www/api.js at startup+ writeJS (www </> "api.js")+ [ incCounterJS, currentValueJS ]++ -- setup a shared counter+ cnt <- newCounter++ -- listen to requests on port 8080+ runServer cnt 8080+```
servant-jquery.cabal view
@@ -1,6 +1,6 @@ name: servant-jquery-version: 0.2.1-synopsis: Automatically derive jquery-based javascript functions to query servant webservices+version: 0.2.2+synopsis: Automatically derive (jquery) javascript functions to query servant webservices description: Automatically derive jquery-based javascript functions to query servant webservices. .@@ -16,6 +16,9 @@ cabal-version: >=1.10 homepage: http://haskell-servant.github.io/ Bug-reports: http://github.com/haskell-servant/servant-jquery/issues+extra-source-files:+ CHANGELOG.md+ README.md source-repository head type: git location: http://github.com/haskell-servant/servant-jquery.git@@ -37,7 +40,7 @@ main-is: counter.hs ghc-options: -O2 -Wall hs-source-dirs: examples- + if flag(example) buildable: True else@@ -53,4 +56,17 @@ , stm , transformers , warp+ default-language: Haskell2010++test-suite spec+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ ghc-options: -Wall+ main-is: Spec.hs+ build-depends:+ base == 4.*+ , servant-jquery+ , servant+ , hspec >= 2.0+ , language-ecmascript == 0.16.* default-language: Haskell2010
src/Servant/JQuery/Internal.hs view
@@ -6,7 +6,9 @@ {-# LANGUAGE ScopedTypeVariables #-} module Servant.JQuery.Internal where +import Control.Applicative import Control.Lens+import Data.Char (toLower) import Data.Monoid import Data.Proxy import GHC.TypeLits@@ -28,7 +30,7 @@ captureArg _ = error "captureArg called on non capture" jsSegments :: [Segment] -> String-jsSegments [] = ""+jsSegments [] = "/'" jsSegments [x] = "/" ++ segmentToStr x False jsSegments (x:xs) = "/" ++ segmentToStr x True ++ jsSegments xs @@ -196,7 +198,8 @@ type JQ Raw = Method -> AjaxReq jqueryFor Proxy req method =- req & reqMethod .~ method+ req & funcName %~ ((toLower <$> method) <>)+ & reqMethod .~ method instance HasJQ sublayout => HasJQ (ReqBody a :> sublayout) where type JQ (ReqBody a :> sublayout) = JQ sublayout@@ -214,4 +217,4 @@ req & reqUrl.path <>~ [Static str] & funcName %~ (str <>) - where str = symbolVal (Proxy :: Proxy path)+ where str = map (\c -> if c == '.' then '_' else c) $ symbolVal (Proxy :: Proxy path)
+ test/Spec.hs view
@@ -0,0 +1,2 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+