on master help sign in
Merge pull request #196 from haskell-servant/jkarni/contributing
90d837dAlp Mestanogullari
.stylish-haskell.yamlnew file+77
@@ -0,0 +1,77 @@
1+# stylish-haskell configuration file
2+# ==================================
3+
4+# The stylish-haskell tool is mainly configured by specifying steps. These steps
5+# are a list, so they have an order, and one specific step may appear more than
6+# once (if needed). Each file is processed by these steps in the given order.
7+steps:
8+ # Convert some ASCII sequences to their Unicode equivalents. This is disabled
9+ # by default.
10+ # - unicode_syntax:
11+ # # In order to make this work, we also need to insert the UnicodeSyntax
12+ # # language pragma. If this flag is set to true, we insert it when it's
13+ # # not already present. You may want to disable it if you configure
14+ # # language extensions using some other method than pragmas. Default:
15+ # # true.
16+ # add_language_pragma: true
17+
18+ # Import cleanup
19+ - imports:
20+ # There are different ways we can align names and lists.
21+ #
22+ # - global: Align the import names and import list throughout the entire
23+ # file.
24+ #
25+ # - file: Like global, but don't add padding when there are no qualified
26+ # imports in the file.
27+ #
28+ # - group: Only align the imports per group (a group is formed by adjacent
29+ # import lines).
30+ #
31+ # - none: Do not perform any alignment.
32+ #
33+ # Default: global.
34+ align: global
35+
36+ # Language pragmas
37+ - language_pragmas:
38+ # We can generate different styles of language pragma lists.
39+ #
40+ # - vertical: Vertical-spaced language pragmas, one per line.
41+ #
42+ # - compact: A more compact style.
43+ #
44+ # - compact_line: Similar to compact, but wrap each line with
45+ # `{-#LANGUAGE #-}'.
46+ #
47+ # Default: vertical.
48+ style: vertical
49+
50+ # stylish-haskell can detect redundancy of some language pragmas. If this
51+ # is set to true, it will remove those redundant pragmas. Default: true.
52+ remove_redundant: true
53+
54+ # Align the types in record declarations
55+ - records: {}
56+
57+ # Replace tabs by spaces. This is disabled by default.
58+ # - tabs:
59+ # # Number of spaces to use for each tab. Default: 8, as specified by the
60+ # # Haskell report.
61+ # spaces: 8
62+
63+ # Remove trailing whitespace
64+ - trailing_whitespace: {}
65+
66+# A common setting is the number of columns (parts of) code will be wrapped
67+# to. Different steps take this into account. Default: 80.
68+columns: 80
69+
70+# Sometimes, language extensions are specified in a cabal file or from the
71+# command line instead of using language pragmas in the file. stylish-haskell
72+# needs to be aware of these, so it can parse the file correctly.
73+#
74+# No language extensions are enabled by default.
75+language_extensions:
76+ - TemplateHaskell
77+ - QuasiQuotes
HLint.hsnew file+6
@@ -0,0 +1,6 @@
1+import "hint" HLint.Default
2+
3+ignore "Redundant do"
4+ignore "Parse error"
5+ignore "Use list comprehension"
6+ignore "Use liftM"
README.md+46−7
@@ -5,17 +5,56 @@
5
5
6![servant](https://raw.githubusercontent.com/haskell-servant/servant/master/servant.png)
6![servant](https://raw.githubusercontent.com/haskell-servant/servant/master/servant.png)
7
7
8+These libraries provides a family of combinators to define webservices and
8−These libraries provides a family of combinators to define webservices and automatically generate the documentation and client-side querying functions for each endpoint.
9+automatically generate the documentation and client-side querying functions for
10+each endpoint.
9
11
10−In order to minimize the dependencies depending on your needs, we provide these features under different packages.
12+In order to minimize the dependencies depending on your needs, we provide these
13+features under different packages.
11
14
12- `servant`, which contains everything you need to *declare* a webservice API.
15- `servant`, which contains everything you need to *declare* a webservice API.
13−- `servant-server`, which lets you *implement* an HTTP server with handlers for each endpoint of an API.
16+- `servant-server`, which lets you *implement* an HTTP server with handlers for
17+each endpoint of an API.
14−- `servant-client`, which lets you derive automatically Haskell functions that let you query each endpoint of a `servant` webservice.
18+- `servant-client`, which lets you derive automatically Haskell functions that
19+let you query each endpoint of a `servant` webservice.
15- `servant-docs`, which lets you generate API docs for your webservice.
20- `servant-docs`, which lets you generate API docs for your webservice.
16−- `servant-js`, which lets you derive Javascript functions (using vanilla JS ajax requests, angular or jquery) to query your API's endpoints, in the same spirit as `servant-client`.
21+- `servant-js`, which lets you derive Javascript functions (using vanilla JS
22+ajax requests, angular or jquery) to query your API's endpoints, in the same
23+spirit as `servant-client`.
17−- `servant-blaze` and `servant-lucid` provide easy HTML rendering of your data as an `HTML` content-type "combinator".
24+- `servant-blaze` and `servant-lucid` provide easy HTML rendering of your data
25+as an `HTML` content-type "combinator".
18
26
19## Tutorial
27## Tutorial
20
28
29+We have a [tutorial](http://haskell-servant.github.io/tutorial) guide that
30+introduces the core types and features of servant. After this article, you
21−We have a [tutorial](http://haskell-servant.github.io/tutorial) guide that introduces the core types and features of servant. After this article, you should be able to write your first servant webservices, learning the rest from the haddocks' examples.
31+should be able to write your first servant webservices, learning the rest from
32+the haddocks' examples.
33+
34+## Contributing
35+
36+Contributions are very welcome! To hack on the github version, clone the
37+repository. You can use `cabal`:
38+
39+```shell
40+./scripts/start-sandbox.sh # Initialize the sandbox and add-source the packages
41+./scripts/test-all.sh # Run all the tests
42+```
43+
44+`stack`:
45+
46+```shell
47+stack build # Install and build packages
48+stack test # Run all the tests
49+```
50+
51+Or `nix`:
52+```shell
53+./scripts/update-nix-files.sh # Get up-to-date shell.nix files
54+```
55+
56+Though we aren't sticklers for style, the `.stylish-haskel.yaml` and `HLint.hs`
57+files in the repository provide a good baseline for consistency.
58+
59+Please include a description of the changes in your PR in the `CHANGELOG.md` of
60+the packages you've changed. And of course, write tests!
servant-blaze/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-client/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-client/src/Servant/Common/BaseUrl.hs+9−9
@@ -11,13 +11,13 @@ module Servant.Common.BaseUrl (
11 , showBaseUrl
11 , showBaseUrl
12) where
12) where
13
13
14−import Control.Monad.Catch (MonadThrow, throwM, Exception)
14+import Control.Monad.Catch (Exception, MonadThrow, throwM)
15−import Data.List
15+import Data.List
16−import Data.Typeable
16+import Data.Typeable
17−import GHC.Generics
17+import GHC.Generics
18−import Network.URI
18+import Network.URI
19−import Safe
19+import Safe
20−import Text.Read
20+import Text.Read
21
21
22-- | URI scheme to use
22-- | URI scheme to use
23data Scheme =
23data Scheme =
@@ -29,8 +29,8 @@ data Scheme =
29-- for servant's automatically-generated clients.
29-- for servant's automatically-generated clients.
30data BaseUrl = BaseUrl
30data BaseUrl = BaseUrl
31 { baseUrlScheme :: Scheme -- ^ URI scheme to use
31 { baseUrlScheme :: Scheme -- ^ URI scheme to use
32− , baseUrlHost :: String -- ^ host (eg "haskell.org")
32+ , baseUrlHost :: String -- ^ host (eg "haskell.org")
33− , baseUrlPort :: Int -- ^ port (eg 80)
33+ , baseUrlPort :: Int -- ^ port (eg 80)
34 } deriving (Show, Eq, Ord, Generic)
34 } deriving (Show, Eq, Ord, Generic)
35
35
36showBaseUrl :: BaseUrl -> String
36showBaseUrl :: BaseUrl -> String
servant-client/src/Servant/Common/Req.hs+1−1
@@ -99,7 +99,7 @@ setRQBody b t req = req { reqBody = Just (b, t) }
99
99
100reqToRequest :: (Functor m, MonadThrow m) => Req -> BaseUrl -> m Request
100reqToRequest :: (Functor m, MonadThrow m) => Req -> BaseUrl -> m Request
101reqToRequest req (BaseUrl reqScheme reqHost reqPort) =
101reqToRequest req (BaseUrl reqScheme reqHost reqPort) =
102− fmap (setheaders . setAccept . setrqb . setQS ) $ parseUrl url
102+ setheaders . setAccept . setrqb . setQS <$> parseUrl url
103
103
104 where url = show $ nullURI { uriScheme = case reqScheme of
104 where url = show $ nullURI { uriScheme = case reqScheme of
105 Http -> "http:"
105 Http -> "http:"
servant-client/test/Servant/Common/BaseUrlSpec.hs+6−6
@@ -1,15 +1,15 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
3module Servant.Common.BaseUrlSpec where
3module Servant.Common.BaseUrlSpec where
4
4
5#if !MIN_VERSION_base(4,8,0)
5#if !MIN_VERSION_base(4,8,0)
6−import Control.Applicative
6+import Control.Applicative
7#endif
7#endif
8−import Control.DeepSeq
8+import Control.DeepSeq
9−import Test.Hspec
9+import Test.Hspec
10−import Test.QuickCheck
10+import Test.QuickCheck
11
11
12−import Servant.Common.BaseUrl
12+import Servant.Common.BaseUrl
13
13
14spec :: Spec
14spec :: Spec
15spec = do
15spec = do
servant-client/test/Spec.hs+1−1
@@ -1,4 +1,4 @@
1−import Servant.ClientSpec (spec, failSpec)
1+import Servant.ClientSpec (failSpec, spec)
2
2
3main :: IO ()
3main :: IO ()
4main = do
4main = do
servant-docs/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-docs/src/Servant/Docs.hs+1−1
@@ -166,4 +166,4 @@ module Servant.Docs
166 , single
166 , single
167 ) where
167 ) where
168
168
169−import Servant.Docs.Internal
169+import Servant.Docs.Internal
servant-docs/src/Servant/Docs/Internal.hs+2−2
@@ -1,5 +1,5 @@
1−{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2+{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE DeriveGeneric #-}
4{-# LANGUAGE DeriveGeneric #-}
5{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
@@ -23,6 +23,7 @@ module Servant.Docs.Internal where
23import Control.Applicative
23import Control.Applicative
24#endif
24#endif
25import Control.Lens
25import Control.Lens
26+import Data.ByteString.Conversion (ToByteString, toByteString)
26import Data.ByteString.Lazy.Char8 (ByteString)
27import Data.ByteString.Lazy.Char8 (ByteString)
27import qualified Data.CaseInsensitive as CI
28import qualified Data.CaseInsensitive as CI
28import Data.Hashable
29import Data.Hashable
@@ -32,7 +33,6 @@ import Data.Maybe
32import Data.Monoid
33import Data.Monoid
33import Data.Ord (comparing)
34import Data.Ord (comparing)
34import Data.Proxy
35import Data.Proxy
35−import Data.ByteString.Conversion (ToByteString, toByteString)
36import Data.String.Conversions
36import Data.String.Conversions
37import Data.Text (Text, pack, unpack)
37import Data.Text (Text, pack, unpack)
38import GHC.Exts (Constraint)
38import GHC.Exts (Constraint)
servant-examples/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-examples/auth-combinator/auth-combinator.hs+15−15
@@ -1,19 +1,19 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
4−{-# LANGUAGE TypeOperators #-}
5−{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE TypeFamilies #-}
7+{-# LANGUAGE TypeOperators #-}
8−import Data.Aeson
8+import Data.Aeson
9−import Data.ByteString (ByteString)
9+import Data.ByteString (ByteString)
10−import Data.Text (Text)
10+import Data.Text (Text)
11−import GHC.Generics
11+import GHC.Generics
12−import Network.HTTP.Types
12+import Network.HTTP.Types
13−import Network.Wai
13+import Network.Wai
14−import Network.Wai.Handler.Warp
14+import Network.Wai.Handler.Warp
15−import Servant
15+import Servant
16−import Servant.Server.Internal
16+import Servant.Server.Internal
17
17
18-- Pretty much stolen/adapted from
18-- Pretty much stolen/adapted from
19-- https://github.com/haskell-servant/HaskellSGMeetup2015/blob/master/examples/authentication-combinator/AuthenticationCombinator.hs
19-- https://github.com/haskell-servant/HaskellSGMeetup2015/blob/master/examples/authentication-combinator/AuthenticationCombinator.hs
servant-examples/hackage/hackage.hs+17−17
@@ -1,21 +1,21 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
3−{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TypeOperators #-}
5−import Control.Applicative
5+import Control.Applicative
6−import Control.Monad
6+import Control.Monad
7−import Control.Monad.IO.Class
7+import Control.Monad.IO.Class
8−import Control.Monad.Trans.Either
8+import Control.Monad.Trans.Either
9−import Data.Aeson
9+import Data.Aeson
10−import Data.Monoid
10+import Data.Monoid
11−import Data.Proxy
11+import Data.Proxy
12−import Data.Text (Text)
12+import Data.Text (Text)
13−import GHC.Generics
13+import GHC.Generics
14−import Servant.API
14+import Servant.API
15−import Servant.Client
15+import Servant.Client
16−
16+
17−import qualified Data.Text as T
17+import qualified Data.Text as T
18−import qualified Data.Text.IO as T
18+import qualified Data.Text.IO as T
19
19
20type HackageAPI =
20type HackageAPI =
21 "users" :> Get '[JSON] [UserSummary]
21 "users" :> Get '[JSON] [UserSummary]
servant-examples/socket-io-chat/socket-io-chat.hs+12−12
@@ -1,24 +1,24 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE DataKinds #-}
4−{-# LANGUAGE TypeOperators #-}
4+{-# LANGUAGE TypeOperators #-}
5
5
6
6
7−import Data.Monoid ((<>))
7+import Data.Monoid ((<>))
8#if !MIN_VERSION_base(4,8,0)
8#if !MIN_VERSION_base(4,8,0)
9−import Control.Applicative((<$>))
9+import Control.Applicative ((<$>))
10#endif
10#endif
11−import Network.Wai
12−import Servant
13−import Network.EngineIO.Wai
11+import Network.EngineIO.Wai
12+import Network.Wai
14−import Network.Wai.Handler.Warp (run)
13+import Network.Wai.Handler.Warp (run)
14+import Servant
15
15
16
16
17−import qualified Control.Concurrent.STM as STM
17+import qualified Control.Concurrent.STM as STM
18−import qualified Network.SocketIO as SocketIO
18+import qualified Network.SocketIO as SocketIO
19
19
20
20
21−import Chat (eioServer, ServerState (..))
21+import Chat (ServerState (..), eioServer)
22
22
23
23
24type API = "socket.io" :> Raw
24type API = "socket.io" :> Raw
servant-examples/tutorial/T1.hs+11−11
@@ -1,19 +1,19 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE DeriveGeneric #-}
3+{-# LANGUAGE TypeFamilies #-}
4{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE TypeOperators #-}
5module T1 where
5module T1 where
6
6
7−import Data.Aeson
7+import Data.Aeson
8−import Data.Time.Calendar
8+import Data.Time.Calendar
9−import GHC.Generics
9+import GHC.Generics
10−import Network.Wai
10+import Network.Wai
11−import Servant
11+import Servant
12
12
13data User = User
13data User = User
14− { name :: String
14+ { name :: String
15− , age :: Int
15+ , age :: Int
16− , email :: String
16+ , email :: String
17 , registration_date :: Day
17 , registration_date :: Day
18 } deriving (Eq, Show, Generic)
18 } deriving (Eq, Show, Generic)
19
19
@@ -27,7 +27,7 @@ instance ToJSON User
27type UserAPI = "users" :> Get '[JSON] [User]
27type UserAPI = "users" :> Get '[JSON] [User]
28
28
29users :: [User]
29users :: [User]
30−users =
30+users =
31 [ User "Isaac Newton" 372 "isaac@newton.co.uk" (fromGregorian 1683 3 1)
31 [ User "Isaac Newton" 372 "isaac@newton.co.uk" (fromGregorian 1683 3 1)
32 , User "Albert Einstein" 136 "ae@mc2.org" (fromGregorian 1905 12 1)
32 , User "Albert Einstein" 136 "ae@mc2.org" (fromGregorian 1905 12 1)
33 ]
33 ]
servant-examples/tutorial/T10.hs+12−12
@@ -1,18 +1,18 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE TypeOperators #-}
4−{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE FlexibleInstances #-}
5−{-# LANGUAGE OverloadedStrings #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
4+{-# LANGUAGE OverloadedStrings #-}
5+{-# LANGUAGE TypeFamilies #-}
6+{-# LANGUAGE TypeOperators #-}
7module T10 where
7module T10 where
8
8
9−import Data.ByteString.Lazy (ByteString)
9+import Data.ByteString.Lazy (ByteString)
10−import Data.Text.Lazy (pack)
10+import Data.Text.Lazy (pack)
11−import Data.Text.Lazy.Encoding (encodeUtf8)
11+import Data.Text.Lazy.Encoding (encodeUtf8)
12−import Network.HTTP.Types
12+import Network.HTTP.Types
13−import Network.Wai
13+import Network.Wai
14−import Servant
14+import Servant
15−import Servant.Docs
15+import Servant.Docs
16import qualified T3
16import qualified T3
17
17
18type DocsAPI = T3.API :<|> Raw
18type DocsAPI = T3.API :<|> Raw
servant-examples/tutorial/T2.hs+10−10
@@ -1,19 +1,19 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE DeriveGeneric #-}
3+{-# LANGUAGE TypeFamilies #-}
4{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE TypeOperators #-}
5module T2 where
5module T2 where
6
6
7−import Data.Aeson
7+import Data.Aeson
8−import Data.Time.Calendar
8+import Data.Time.Calendar
9−import GHC.Generics
9+import GHC.Generics
10−import Network.Wai
10+import Network.Wai
11−import Servant
11+import Servant
12
12
13data User = User
13data User = User
14− { name :: String
14+ { name :: String
15− , age :: Int
15+ , age :: Int
16− , email :: String
16+ , email :: String
17 , registration_date :: Day
17 , registration_date :: Day
18 } deriving (Eq, Show, Generic)
18 } deriving (Eq, Show, Generic)
19
19
servant-examples/tutorial/T3.hs+14−14
@@ -1,15 +1,15 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE DeriveGeneric #-}
3+{-# LANGUAGE TypeFamilies #-}
4{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE TypeOperators #-}
5module T3 where
5module T3 where
6
6
7−import Control.Monad.Trans.Either
7+import Control.Monad.Trans.Either
8−import Data.Aeson
8+import Data.Aeson
9−import Data.List
9+import Data.List
10−import GHC.Generics
10+import GHC.Generics
11−import Network.Wai
11+import Network.Wai
12−import Servant
12+import Servant
13
13
14data Position = Position
14data Position = Position
15 { x :: Int
15 { x :: Int
@@ -26,9 +26,9 @@ instance FromJSON HelloMessage
26instance ToJSON HelloMessage
26instance ToJSON HelloMessage
27
27
28data ClientInfo = ClientInfo
28data ClientInfo = ClientInfo
29− { name :: String
29+ { name :: String
30− , email :: String
30+ , email :: String
31− , age :: Int
31+ , age :: Int
32 , interested_in :: [String]
32 , interested_in :: [String]
33 } deriving (Show, Generic)
33 } deriving (Show, Generic)
34
34
@@ -36,10 +36,10 @@ instance FromJSON ClientInfo
36instance ToJSON ClientInfo
36instance ToJSON ClientInfo
37
37
38data Email = Email
38data Email = Email
39− { from :: String
39+ { from :: String
40− , to :: String
40+ , to :: String
41 , subject :: String
41 , subject :: String
42− , body :: String
42+ , body :: String
43 } deriving (Show, Generic)
43 } deriving (Show, Generic)
44
44
45instance FromJSON Email
45instance FromJSON Email
servant-examples/tutorial/T4.hs+11−11
@@ -1,18 +1,18 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
4−{-# LANGUAGE TypeOperators #-}
5{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
5+{-# LANGUAGE TypeFamilies #-}
6+{-# LANGUAGE TypeOperators #-}
7module T4 where
7module T4 where
8
8
9−import Data.Aeson
9+import Data.Aeson
10−import Data.Foldable (foldMap)
10+import Data.Foldable (foldMap)
11−import GHC.Generics
11+import GHC.Generics
12−import Lucid
12+import Lucid
13−import Network.Wai
13+import Network.Wai
14−import Servant
14+import Servant
15−import Servant.HTML.Lucid
15+import Servant.HTML.Lucid
16
16
17data Person = Person
17data Person = Person
18 { firstName :: String
18 { firstName :: String
servant-examples/tutorial/T5.hs+11−11
@@ -1,17 +1,17 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
4−{-# LANGUAGE TypeOperators #-}
5{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TypeFamilies #-}
5+{-# LANGUAGE TypeOperators #-}
6module T5 where
6module T5 where
7
7
8−import Control.Monad.IO.Class
8+import Control.Monad.IO.Class
9−import Control.Monad.Trans.Either
9+import Control.Monad.Trans.Either
10−import Data.Aeson
10+import Data.Aeson
11−import GHC.Generics
11+import GHC.Generics
12−import Network.Wai
12+import Network.Wai
13−import Servant
13+import Servant
14−import System.Directory
14+import System.Directory
15
15
16type IOAPI = "myfile.txt" :> Get '[JSON] FileContent
16type IOAPI = "myfile.txt" :> Get '[JSON] FileContent
17
17
servant-examples/tutorial/T6.hs+4−4
@@ -1,10 +1,10 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE TypeOperators #-}
3{-# LANGUAGE TypeOperators #-}
4module T6 where
4module T6 where
5
5
6−import Network.Wai
6+import Network.Wai
7−import Servant
7+import Servant
8
8
9type API = "code" :> Raw
9type API = "code" :> Raw
10
10
servant-examples/tutorial/T7.hs+6−6
@@ -1,12 +1,12 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE TypeOperators #-}
3{-# LANGUAGE TypeOperators #-}
4module T7 where
4module T7 where
5
5
6−import Control.Monad.Trans.Either
6+import Control.Monad.Trans.Either
7−import Control.Monad.Trans.Reader
7+import Control.Monad.Trans.Reader
8−import Network.Wai
8+import Network.Wai
9−import Servant
9+import Servant
10
10
11type ReaderAPI = "a" :> Get '[JSON] Int
11type ReaderAPI = "a" :> Get '[JSON] Int
12 :<|> "b" :> Get '[JSON] String
12 :<|> "b" :> Get '[JSON] String
servant-examples/tutorial/T8.hs+7−7
@@ -1,14 +1,14 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE TypeOperators #-}
3{-# LANGUAGE TypeOperators #-}
4module T8 where
4module T8 where
5
5
6−import Control.Monad.Trans.Either
6+import Control.Monad.Trans.Either
7−import Data.Aeson
7+import Data.Aeson
8−import Servant
8+import Servant
9−import Servant.Client
9+import Servant.Client
10
10
11−import T3
11+import T3
12
12
13position :: Int -- ^ value for "x"
13position :: Int -- ^ value for "x"
14 -> Int -- ^ value for "y"
14 -> Int -- ^ value for "y"
servant-examples/tutorial/T9.hs+14−14
@@ -1,20 +1,20 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
4−{-# LANGUAGE TypeOperators #-}
5{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TypeFamilies #-}
5+{-# LANGUAGE TypeOperators #-}
6module T9 where
6module T9 where
7
7
8−import Control.Applicative
8+import Control.Applicative
9−import Control.Monad.IO.Class
9+import Control.Monad.IO.Class
10−import Data.Aeson
10+import Data.Aeson
11−import Data.Text (Text)
11+import Data.Text (Text)
12−import GHC.Generics
12+import GHC.Generics
13−import Network.Wai
13+import Network.Wai
14−import Servant
14+import Servant
15−import Servant.JS
15+import Servant.JS
16−import Servant.JS.JQuery
16+import Servant.JS.JQuery
17−import System.Random
17+import System.Random
18
18
19import qualified Data.Text as T
19import qualified Data.Text as T
20import qualified Language.Javascript.JQuery as JQ
20import qualified Language.Javascript.JQuery as JQ
servant-examples/tutorial/t8-main.hs+1−1
@@ -1,4 +1,4 @@
1−import T8
1+import T8
2
2
3main :: IO ()
3main :: IO ()
4main = run
4main = run
servant-examples/tutorial/tutorial.hs+4−4
@@ -1,8 +1,9 @@
1−import Network.Wai
1+import Network.Wai
2−import Network.Wai.Handler.Warp
2+import Network.Wai.Handler.Warp
3−import System.Environment
3+import System.Environment
4
4
5import qualified T1
5import qualified T1
6+import qualified T10
6import qualified T2
7import qualified T2
7import qualified T3
8import qualified T3
8import qualified T4
9import qualified T4
@@ -10,7 +11,6 @@ import qualified T5
10import qualified T6
11import qualified T6
11import qualified T7
12import qualified T7
12import qualified T9
13import qualified T9
13−import qualified T10
14
14
15app :: String -> (Application -> IO ()) -> IO ()
15app :: String -> (Application -> IO ()) -> IO ()
16app n f = case n of
16app n f = case n of
servant-examples/wai-middleware/wai-middleware.hs+9−9
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4−import Data.Aeson
4+import Data.Aeson
5−import Data.Text
5+import Data.Text
6−import GHC.Generics
6+import GHC.Generics
7−import Network.Wai
7+import Network.Wai
8−import Network.Wai.Handler.Warp
8+import Network.Wai.Handler.Warp
9−import Network.Wai.Middleware.RequestLogger
9+import Network.Wai.Middleware.RequestLogger
10−import Servant
10+import Servant
11
11
12data Product = Product
12data Product = Product
13 { name :: Text
13 { name :: Text
servant-js/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-js/examples/counter.hs+17−17
@@ -1,19 +1,19 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeOperators #-}
3−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5−
4+{-# LANGUAGE TypeOperators #-}
5+
6−import Control.Concurrent.STM
6+import Control.Concurrent.STM
7−import Control.Monad.IO.Class
7+import Control.Monad.IO.Class
8−import Data.Aeson
8+import Data.Aeson
9−import Data.Proxy
9+import Data.Proxy
10−import GHC.Generics
10+import GHC.Generics
11−import Network.Wai.Handler.Warp (run)
11+import Network.Wai.Handler.Warp (run)
12−import Servant
12+import Servant
13−import Servant.JS
13+import Servant.JS
14−import qualified Servant.JS as SJS
14+import qualified Servant.JS as SJS
15−import qualified Servant.JS.Angular as NG
15+import qualified Servant.JS.Angular as NG
16−import System.FilePath
16+import System.FilePath
17
17
18-- * A simple Counter data type
18-- * A simple Counter data type
19newtype Counter = Counter { value :: Int }
19newtype Counter = Counter { value :: Int }
@@ -43,7 +43,7 @@ type TestApi = "counter" :> Post '[JSON] Counter -- endpoint for increasing the
43 :<|> "counter" :> Get '[JSON] Counter -- endpoint to get the current value
43 :<|> "counter" :> Get '[JSON] Counter -- endpoint to get the current value
44
44
45type TestApi' = TestApi
45type TestApi' = TestApi
46− :<|> Raw -- used for serving static files
46+ :<|> Raw -- used for serving static files
47
47
48-- this proxy only targets the proper endpoints of our API,
48-- this proxy only targets the proper endpoints of our API,
49-- not the static file serving bit
49-- not the static file serving bit
@@ -82,7 +82,7 @@ writeServiceJS fp =
82 (defCommonGeneratorOptions { SJS.moduleName = "counterApp" })
82 (defCommonGeneratorOptions { SJS.moduleName = "counterApp" })
83 )
83 )
84 fp
84 fp
85−
85+
86main :: IO ()
86main :: IO ()
87main = do
87main = do
88 -- write the JS code to www/api.js at startup
88 -- write the JS code to www/api.js at startup
servant-js/src/Servant/JS.hs+11−11
@@ -1,7 +1,7 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeOperators #-}
3−{-# LANGUAGE FlexibleContexts #-}
2+{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE TypeOperators #-}
5-----------------------------------------------------------------------------
5-----------------------------------------------------------------------------
6-- |
6-- |
7-- Module : Servant.JS
7-- Module : Servant.JS
@@ -114,13 +114,13 @@ module Servant.JS
114 , AjaxReq
114 , AjaxReq
115 ) where
115 ) where
116
116
117−import Data.Proxy
117+import Data.Proxy
118−import Servant.API
118+import Servant.API
119−import Servant.JS.Angular
119+import Servant.JS.Angular
120−import Servant.JS.Axios
120+import Servant.JS.Axios
121−import Servant.JS.Internal
121+import Servant.JS.Internal
122−import Servant.JS.JQuery
122+import Servant.JS.JQuery
123−import Servant.JS.Vanilla
123+import Servant.JS.Vanilla
124
124
125-- | Generate the data necessary to generate javascript code
125-- | Generate the data necessary to generate javascript code
126-- for all the endpoints of an API, as ':<|>'-separated values
126-- for all the endpoints of an API, as ':<|>'-separated values
@@ -160,6 +160,6 @@ instance (GenerateList start, GenerateList rest) => GenerateList (start :<|> res
160 generateList (start :<|> rest) = (generateList start) ++ (generateList rest)
160 generateList (start :<|> rest) = (generateList start) ++ (generateList rest)
161
161
162-- | Generate the necessary data for JS codegen as a list, each 'AjaxReq'
162-- | Generate the necessary data for JS codegen as a list, each 'AjaxReq'
163−-- describing one endpoint from your API type.
163+-- describing one endpoint from your API type.
164listFromAPI :: (HasJS api, GenerateList (JS api)) => Proxy api -> [AjaxReq]
164listFromAPI :: (HasJS api, GenerateList (JS api)) => Proxy api -> [AjaxReq]
165listFromAPI p = generateList (javascript p)
165listFromAPI p = generateList (javascript p)
servant-js/src/Servant/JS/Angular.hs+13−13
@@ -1,16 +1,16 @@
1module Servant.JS.Angular where
1module Servant.JS.Angular where
2
2
3−import Servant.JS.Internal
4−import Control.Lens
3+import Control.Lens
5−import Data.List
4+import Data.List
6−import Data.Monoid
5+import Data.Monoid
6+import Servant.JS.Internal
7
7
8-- | Options specific to the angular code generator
8-- | Options specific to the angular code generator
9data AngularOptions = AngularOptions
9data AngularOptions = AngularOptions
10 { serviceName :: String -- ^ When generating code with wrapInService,
10 { serviceName :: String -- ^ When generating code with wrapInService,
11 -- name of the service to generate
11 -- name of the service to generate
12− , prologue :: String -> String -> String -- ^ beginning of the service definition
12+ , prologue :: String -> String -> String -- ^ beginning of the service definition
13− , epilogue :: String -- ^ end of the service definition
13+ , epilogue :: String -- ^ end of the service definition
14 }
14 }
15
15
16-- | Default options for the Angular codegen. Used by 'wrapInService'.
16-- | Default options for the Angular codegen. Used by 'wrapInService'.
@@ -31,7 +31,7 @@ angularService ngOpts = angularServiceWith ngOpts defCommonGeneratorOptions
31-- | Instead of simply generating top level functions, generates a service instance
31-- | Instead of simply generating top level functions, generates a service instance
32-- on which your controllers can depend to access your API
32-- on which your controllers can depend to access your API
33angularServiceWith :: AngularOptions -> CommonGeneratorOptions -> JavaScriptGenerator
33angularServiceWith :: AngularOptions -> CommonGeneratorOptions -> JavaScriptGenerator
34−angularServiceWith ngOpts opts reqs =
34+angularServiceWith ngOpts opts reqs =
35 prologue ngOpts svc mName
35 prologue ngOpts svc mName
36 <> intercalate "," (map generator reqs) <>
36 <> intercalate "," (map generator reqs) <>
37 epilogue ngOpts
37 epilogue ngOpts
@@ -54,7 +54,7 @@ angularWith ngopts opts = intercalate "\n\n" . map (generateAngularJSWith ngopts
54-- | js codegen using $http service from Angular using default options
54-- | js codegen using $http service from Angular using default options
55generateAngularJS :: AngularOptions -> AjaxReq -> String
55generateAngularJS :: AngularOptions -> AjaxReq -> String
56generateAngularJS ngOpts = generateAngularJSWith ngOpts defCommonGeneratorOptions
56generateAngularJS ngOpts = generateAngularJSWith ngOpts defCommonGeneratorOptions
57−
57+
58-- | js codegen using $http service from Angular
58-- | js codegen using $http service from Angular
59generateAngularJSWith :: AngularOptions -> CommonGeneratorOptions -> AjaxReq -> String
59generateAngularJSWith :: AngularOptions -> CommonGeneratorOptions -> AjaxReq -> String
60generateAngularJSWith ngOptions opts req = "\n" <>
60generateAngularJSWith ngOptions opts req = "\n" <>
@@ -74,7 +74,7 @@ generateAngularJSWith ngOptions opts req = "\n" <>
74 ++ map (view argName) queryparams
74 ++ map (view argName) queryparams
75 ++ body
75 ++ body
76 ++ map (toValidFunctionName . (<>) "header" . headerArgName) hs
76 ++ map (toValidFunctionName . (<>) "header" . headerArgName) hs
77−
77+
78 -- If we want to generate Top Level Function, they must depend on
78 -- If we want to generate Top Level Function, they must depend on
79 -- the $http service, if we generate a service, the functions will
79 -- the $http service, if we generate a service, the functions will
80 -- inherit this dependency from the service
80 -- inherit this dependency from the service
@@ -118,13 +118,13 @@ generateAngularJSWith ngOptions opts req = "\n" <>
118 else (moduleName opts) <> "."
118 else (moduleName opts) <> "."
119 where
119 where
120 hasNoModule = null (moduleName opts)
120 hasNoModule = null (moduleName opts)
121−
121+
122 hasService = not $ null (serviceName ngOptions)
122 hasService = not $ null (serviceName ngOptions)
123−
123+
124 fsep = if hasService then ":" else " ="
124 fsep = if hasService then ":" else " ="
125−
125+
126 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
126 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
127−
127+
128 method = req ^. reqMethod
128 method = req ^. reqMethod
129 url = if url' == "'" then "'/'" else url'
129 url = if url' == "'" then "'/'" else url'
130 url' = "'"
130 url' = "'"
servant-js/src/Servant/JS/Axios.hs+12−12
@@ -1,10 +1,10 @@
1module Servant.JS.Axios where
1module Servant.JS.Axios where
2
2
3−import Servant.JS.Internal
4−import Control.Lens
3+import Control.Lens
5−import Data.Char (toLower)
4+import Data.Char (toLower)
6−import Data.List
5+import Data.List
7−import Data.Monoid
6+import Data.Monoid
7+import Servant.JS.Internal
8
8
9-- | Axios 'configuration' type
9-- | Axios 'configuration' type
10-- Let you customize the generation using Axios capabilities
10-- Let you customize the generation using Axios capabilities
@@ -13,9 +13,9 @@ data AxiosOptions = AxiosOptions
13 -- should be made using credentials
13 -- should be made using credentials
14 withCredentials :: !Bool
14 withCredentials :: !Bool
15 -- | the name of the cookie to use as a value for xsrf token
15 -- | the name of the cookie to use as a value for xsrf token
16− , xsrfCookieName :: !(Maybe String)
16+ , xsrfCookieName :: !(Maybe String)
17 -- | the name of the header to use as a value for xsrf token
17 -- | the name of the header to use as a value for xsrf token
18− , xsrfHeaderName :: !(Maybe String)
18+ , xsrfHeaderName :: !(Maybe String)
19 }
19 }
20
20
21-- | Default instance of the AxiosOptions
21-- | Default instance of the AxiosOptions
@@ -40,7 +40,7 @@ axiosWith aopts opts = intercalate "\n\n" . map (generateAxiosJSWith aopts opts)
40-- | js codegen using axios library using default options
40-- | js codegen using axios library using default options
41generateAxiosJS :: AxiosOptions -> AjaxReq -> String
41generateAxiosJS :: AxiosOptions -> AjaxReq -> String
42generateAxiosJS aopts = generateAxiosJSWith aopts defCommonGeneratorOptions
42generateAxiosJS aopts = generateAxiosJSWith aopts defCommonGeneratorOptions
43−
43+
44-- | js codegen using axios library
44-- | js codegen using axios library
45generateAxiosJSWith :: AxiosOptions -> CommonGeneratorOptions -> AjaxReq -> String
45generateAxiosJSWith :: AxiosOptions -> CommonGeneratorOptions -> AjaxReq -> String
46generateAxiosJSWith aopts opts req = "\n" <>
46generateAxiosJSWith aopts opts req = "\n" <>
@@ -61,7 +61,7 @@ generateAxiosJSWith aopts opts req = "\n" <>
61 ++ map (view argName) queryparams
61 ++ map (view argName) queryparams
62 ++ body
62 ++ body
63 ++ map (toValidFunctionName . (<>) "header" . headerArgName) hs
63 ++ map (toValidFunctionName . (<>) "header" . headerArgName) hs
64−
64+
65 captures = map captureArg
65 captures = map captureArg
66 . filter isCapture
66 . filter isCapture
67 $ req ^. reqUrl.path
67 $ req ^. reqUrl.path
@@ -85,7 +85,7 @@ generateAxiosJSWith aopts opts req = "\n" <>
85 then " , withCredentials: true\n"
85 then " , withCredentials: true\n"
86 else ""
86 else ""
87
87
88− xsrfCookie =
88+ xsrfCookie =
89 case xsrfCookieName aopts of
89 case xsrfCookieName aopts of
90 Just name -> " , xsrfCookieName: '" <> name <> "'\n"
90 Just name -> " , xsrfCookieName: '" <> name <> "'\n"
91 Nothing -> ""
91 Nothing -> ""
@@ -111,9 +111,9 @@ generateAxiosJSWith aopts opts req = "\n" <>
111 else (moduleName opts) <> "."
111 else (moduleName opts) <> "."
112 where
112 where
113 hasNoModule = null (moduleName opts)
113 hasNoModule = null (moduleName opts)
114−
114+
115 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
115 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
116−
116+
117 method = map toLower $ req ^. reqMethod
117 method = map toLower $ req ^. reqMethod
118 url = if url' == "'" then "'/'" else url'
118 url = if url' == "'" then "'/'" else url'
119 url' = "'"
119 url' = "'"
servant-js/src/Servant/JS/Internal.hs+6−6
@@ -28,7 +28,7 @@ import Servant.API
28-- | this structure is used by JavaScriptGenerator implementations to let you
28-- | this structure is used by JavaScriptGenerator implementations to let you
29-- customize the output
29-- customize the output
30data CommonGeneratorOptions = CommonGeneratorOptions
30data CommonGeneratorOptions = CommonGeneratorOptions
31− {
31+ {
32 functionNameBuilder :: FunctionName -> String -- ^ function generating function names
32 functionNameBuilder :: FunctionName -> String -- ^ function generating function names
33 , requestBody :: String -- ^ name used when a user want to send the request body (to let you redefine it)
33 , requestBody :: String -- ^ name used when a user want to send the request body (to let you redefine it)
34 , successCallback :: String -- ^ name of the callback parameter when the request was successful
34 , successCallback :: String -- ^ name of the callback parameter when the request was successful
@@ -63,12 +63,12 @@ defCommonGeneratorOptions = CommonGeneratorOptions
63-- | Function name builder that simply concat each part together
63-- | Function name builder that simply concat each part together
64concatCase :: FunctionName -> String
64concatCase :: FunctionName -> String
65concatCase = concat
65concatCase = concat
66−
66+
67-- | Function name builder using the snake_case convention.
67-- | Function name builder using the snake_case convention.
68-- each part is separated by a single underscore character.
68-- each part is separated by a single underscore character.
69snakeCase :: FunctionName -> String
69snakeCase :: FunctionName -> String
70snakeCase = intercalate "_"
70snakeCase = intercalate "_"
71−
71+
72-- | Function name builder using the CamelCase convention.
72-- | Function name builder using the CamelCase convention.
73-- each part begins with an upper case character.
73-- each part begins with an upper case character.
74camelCase :: FunctionName -> String
74camelCase :: FunctionName -> String
@@ -78,7 +78,7 @@ camelCase (p:ps) = concat $ p : camelCase' ps
78 camelCase' (r:rs) = capitalize r : camelCase' rs
78 camelCase' (r:rs) = capitalize r : camelCase' rs
79 capitalize [] = []
79 capitalize [] = []
80 capitalize (x:xs) = toUpper x : xs
80 capitalize (x:xs) = toUpper x : xs
81−
81+
82type Arg = String
82type Arg = String
83
83
84-- A 'JavascriptGenerator' just takes the data found in the API type
84-- A 'JavascriptGenerator' just takes the data found in the API type
@@ -141,8 +141,8 @@ toValidFunctionName (x:xs) = [setFirstChar x] <> filter remainder xs
141 setFirstChar c = if firstChar c
141 setFirstChar c = if firstChar c
142 then c
142 then c
143 else '_'
143 else '_'
144− firstChar c = (prefixOK c) || (or . map (Set.member c) $ firstLetterOK)
144+ firstChar c = prefixOK c || any (Set.member c) firstLetterOK
145− remainder c = (prefixOK c) || (or . map (Set.member c) $ remainderOK)
145+ remainder c = prefixOK c || any (Set.member c) remainderOK
146 -- Valid prefixes
146 -- Valid prefixes
147 prefixOK c = c `elem` ['$','_']
147 prefixOK c = c `elem` ['$','_']
148 -- Unicode character sets
148 -- Unicode character sets
servant-js/src/Servant/JS/JQuery.hs+8−8
@@ -1,20 +1,20 @@
1module Servant.JS.JQuery where
1module Servant.JS.JQuery where
2
2
3−import Servant.JS.Internal
4−import Control.Lens
3+import Control.Lens
5−import Data.List
4+import Data.List
6−import Data.Monoid
5+import Data.Monoid
6+import Servant.JS.Internal
7
7
8-- | Generate javascript functions that use the /jQuery/ library
8-- | Generate javascript functions that use the /jQuery/ library
9-- to make the AJAX calls. Uses 'defCommonGeneratorOptions'
9-- to make the AJAX calls. Uses 'defCommonGeneratorOptions'
10-- for the generator options.
10-- for the generator options.
11jquery :: JavaScriptGenerator
11jquery :: JavaScriptGenerator
12−jquery = concat . map generateJQueryJS
12+jquery = concatMap generateJQueryJS
13
13
14-- | Generate javascript functions that use the /jQuery/ library
14-- | Generate javascript functions that use the /jQuery/ library
15-- to make the AJAX calls. Lets you specify your own 'CommonGeneratorOptions'.
15-- to make the AJAX calls. Lets you specify your own 'CommonGeneratorOptions'.
16jqueryWith :: CommonGeneratorOptions -> JavaScriptGenerator
16jqueryWith :: CommonGeneratorOptions -> JavaScriptGenerator
17−jqueryWith opts = concat . map (generateJQueryJSWith opts)
17+jqueryWith opts = concatMap (generateJQueryJSWith opts)
18
18
19-- | js codegen using JQuery using default options
19-- | js codegen using JQuery using default options
20generateJQueryJS :: AjaxReq -> String
20generateJQueryJS :: AjaxReq -> String
@@ -53,7 +53,7 @@ generateJQueryJSWith opts req = "\n" <>
53 body = if req ^. reqBody
53 body = if req ^. reqBody
54 then [requestBody opts]
54 then [requestBody opts]
55 else []
55 else []
56−
56+
57 onSuccess = successCallback opts
57 onSuccess = successCallback opts
58 onError = errorCallback opts
58 onError = errorCallback opts
59
59
@@ -77,7 +77,7 @@ generateJQueryJSWith opts req = "\n" <>
77 then "var "
77 then "var "
78 else (moduleName opts) <> "."
78 else (moduleName opts) <> "."
79 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
79 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
80−
80+
81 method = req ^. reqMethod
81 method = req ^. reqMethod
82 url = if url' == "'" then "'/'" else url'
82 url = if url' == "'" then "'/'" else url'
83 url' = "'"
83 url' = "'"
servant-js/src/Servant/JS/Vanilla.hs+10−10
@@ -1,21 +1,21 @@
1module Servant.JS.Vanilla where
1module Servant.JS.Vanilla where
2
2
3−import Servant.JS.Internal
4−import Control.Lens
3+import Control.Lens
5−import Data.List
4+import Data.List
6−import Data.Monoid
5+import Data.Monoid
6+import Servant.JS.Internal
7
7
8-- | Generate vanilla javascript functions to make AJAX requests
8-- | Generate vanilla javascript functions to make AJAX requests
9-- to your API, using /XMLHttpRequest/. Uses 'defCommonGeneratorOptions'
9-- to your API, using /XMLHttpRequest/. Uses 'defCommonGeneratorOptions'
10-- for the 'CommonGeneratorOptions'.
10-- for the 'CommonGeneratorOptions'.
11vanillaJS :: JavaScriptGenerator
11vanillaJS :: JavaScriptGenerator
12−vanillaJS = concat . map generateVanillaJS
12+vanillaJS = concatMap generateVanillaJS
13
13
14-- | Generate vanilla javascript functions to make AJAX requests
14-- | Generate vanilla javascript functions to make AJAX requests
15-- to your API, using /XMLHttpRequest/. Lets you specify your
15-- to your API, using /XMLHttpRequest/. Lets you specify your
16-- own options.
16-- own options.
17vanillaJSWith :: CommonGeneratorOptions -> JavaScriptGenerator
17vanillaJSWith :: CommonGeneratorOptions -> JavaScriptGenerator
18−vanillaJSWith opts = concat . map (generateVanillaJSWith opts)
18+vanillaJSWith opts = concatMap (generateVanillaJSWith opts)
19
19
20-- | js codegen using XmlHttpRequest using default generation options
20-- | js codegen using XmlHttpRequest using default generation options
21generateVanillaJS :: AjaxReq -> String
21generateVanillaJS :: AjaxReq -> String
@@ -56,11 +56,11 @@ generateVanillaJSWith opts req = "\n" <>
56 hs = req ^. reqHeaders
56 hs = req ^. reqHeaders
57
57
58 queryparams = req ^.. reqUrl.queryStr.traverse
58 queryparams = req ^.. reqUrl.queryStr.traverse
59−
59+
60 body = if req ^. reqBody
60 body = if req ^. reqBody
61 then [requestBody opts]
61 then [requestBody opts]
62 else []
62 else []
63−
63+
64 onSuccess = successCallback opts
64 onSuccess = successCallback opts
65 onError = errorCallback opts
65 onError = errorCallback opts
66
66
@@ -68,7 +68,7 @@ generateVanillaJSWith opts req = "\n" <>
68 if req ^. reqBody
68 if req ^. reqBody
69 then "JSON.stringify(body)\n"
69 then "JSON.stringify(body)\n"
70 else "null"
70 else "null"
71−
71+
72
72
73 reqheaders =
73 reqheaders =
74 if null hs
74 if null hs
@@ -84,7 +84,7 @@ generateVanillaJSWith opts req = "\n" <>
84 then "var "
84 then "var "
85 else (moduleName opts) <> "."
85 else (moduleName opts) <> "."
86 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
86 fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
87−
87+
88 method = req ^. reqMethod
88 method = req ^. reqMethod
89 url = if url' == "'" then "'/'" else url'
89 url = if url' == "'" then "'/'" else url'
90 url' = "'"
90 url' = "'"
servant-js/test/Servant/JSSpec.hs+22−22
@@ -7,18 +7,18 @@
7{-# OPTIONS_GHC -fno-warn-orphans #-}
7{-# OPTIONS_GHC -fno-warn-orphans #-}
8module Servant.JSSpec where
8module Servant.JSSpec where
9
9
10−import Data.Either (isRight)
10+import Data.Either (isRight)
11−import Data.Proxy
11+import Data.Proxy
12−import Language.ECMAScript3.Parser (parseFromString)
12+import Language.ECMAScript3.Parser (parseFromString)
13−import Test.Hspec
13+import Test.Hspec
14−
14+
15−import Servant.API
15+import Servant.API
16−import Servant.JS
16+import Servant.JS
17−import qualified Servant.JS.Vanilla as JS
18−import qualified Servant.JS.JQuery as JQ
19−import qualified Servant.JS.Angular as NG
17+import qualified Servant.JS.Angular as NG
20−import qualified Servant.JS.Axios as AX
18+import qualified Servant.JS.Axios as AX
19+import qualified Servant.JS.JQuery as JQ
20+import qualified Servant.JS.Vanilla as JS
21−import Servant.JSSpec.CustomHeaders
21+import Servant.JSSpec.CustomHeaders
22
22
23type TestAPI = "simple" :> ReqBody '[JSON,FormUrlEncoded] String :> Post '[JSON] Bool
23type TestAPI = "simple" :> ReqBody '[JSON,FormUrlEncoded] String :> Post '[JSON] Bool
24 :<|> "has.extension" :> Get '[FormUrlEncoded,JSON] Bool
24 :<|> "has.extension" :> Get '[FormUrlEncoded,JSON] Bool
@@ -65,7 +65,7 @@ customOptions = defCommonGeneratorOptions
65 { successCallback = "okCallback"
65 { successCallback = "okCallback"
66 , errorCallback = "errorCallback"
66 , errorCallback = "errorCallback"
67 }
67 }
68−
68+
69spec :: Spec
69spec :: Spec
70spec = describe "Servant.JQuery" $ do
70spec = describe "Servant.JQuery" $ do
71 generateJSSpec Vanilla JS.generateVanillaJS
71 generateJSSpec Vanilla JS.generateVanillaJS
@@ -76,12 +76,12 @@ spec = describe "Servant.JQuery" $ do
76 generateJSSpec AngularCustom (NG.generateAngularJSWith NG.defAngularOptions customOptions)
76 generateJSSpec AngularCustom (NG.generateAngularJSWith NG.defAngularOptions customOptions)
77 generateJSSpec Axios (AX.generateAxiosJS AX.defAxiosOptions)
77 generateJSSpec Axios (AX.generateAxiosJS AX.defAxiosOptions)
78 generateJSSpec AxiosCustom (AX.generateAxiosJSWith (AX.defAxiosOptions { withCredentials = True }) customOptions)
78 generateJSSpec AxiosCustom (AX.generateAxiosJSWith (AX.defAxiosOptions { withCredentials = True }) customOptions)
79−
79+
80 angularSpec Angular
80 angularSpec Angular
81 axiosSpec
81 axiosSpec
82 --angularSpec AngularCustom
82 --angularSpec AngularCustom
83
83
84−axiosSpec :: Spec
84+axiosSpec :: Spec
85axiosSpec = describe specLabel $ do
85axiosSpec = describe specLabel $ do
86 it "should add withCredentials when needed" $ do
86 it "should add withCredentials when needed" $ do
87 let jsText = genJS withCredOpts $ listFromAPI (Proxy :: Proxy TestAPI)
87 let jsText = genJS withCredOpts $ listFromAPI (Proxy :: Proxy TestAPI)
@@ -102,20 +102,20 @@ axiosSpec = describe specLabel $ do
102 cookieOpts = AX.defAxiosOptions { AX.xsrfCookieName = Just "MyXSRFcookie" }
102 cookieOpts = AX.defAxiosOptions { AX.xsrfCookieName = Just "MyXSRFcookie" }
103 headerOpts = AX.defAxiosOptions { AX.xsrfHeaderName = Just "MyXSRFheader" }
103 headerOpts = AX.defAxiosOptions { AX.xsrfHeaderName = Just "MyXSRFheader" }
104 genJS :: AxiosOptions -> [AjaxReq] -> String
104 genJS :: AxiosOptions -> [AjaxReq] -> String
105− genJS opts req = concat $ map (AX.generateAxiosJS opts) req
105+ genJS opts req = concatMap (AX.generateAxiosJS opts) req
106
106
107−angularSpec :: TestNames -> Spec
107+angularSpec :: TestNames -> Spec
108angularSpec test = describe specLabel $ do
108angularSpec test = describe specLabel $ do
109 it "should implement a service globally" $ do
109 it "should implement a service globally" $ do
110 let jsText = genJS $ listFromAPI (Proxy :: Proxy TestAPI)
110 let jsText = genJS $ listFromAPI (Proxy :: Proxy TestAPI)
111 output jsText
111 output jsText
112 jsText `shouldContain` (".service('" ++ testName ++ "'")
112 jsText `shouldContain` (".service('" ++ testName ++ "'")
113−
113+
114 it "should depend on $http service globally" $ do
114 it "should depend on $http service globally" $ do
115 let jsText = genJS $ listFromAPI (Proxy :: Proxy TestAPI)
115 let jsText = genJS $ listFromAPI (Proxy :: Proxy TestAPI)
116 output jsText
116 output jsText
117 jsText `shouldContain` ("('" ++ testName ++ "', function($http) {")
117 jsText `shouldContain` ("('" ++ testName ++ "', function($http) {")
118−
118+
119 it "should not depend on $http service in handlers" $ do
119 it "should not depend on $http service in handlers" $ do
120 let jsText = genJS $ listFromAPI (Proxy :: Proxy TestAPI)
120 let jsText = genJS $ listFromAPI (Proxy :: Proxy TestAPI)
121 output jsText
121 output jsText
@@ -126,11 +126,11 @@ angularSpec test = describe specLabel $ do
126 testName = "MyService"
126 testName = "MyService"
127 ngOpts = NG.defAngularOptions { NG.serviceName = testName }
127 ngOpts = NG.defAngularOptions { NG.serviceName = testName }
128 genJS req = NG.angularService ngOpts req
128 genJS req = NG.angularService ngOpts req
129−
129+
130generateJSSpec :: TestNames -> (AjaxReq -> String) -> Spec
130generateJSSpec :: TestNames -> (AjaxReq -> String) -> Spec
131generateJSSpec n gen = describe specLabel $ do
131generateJSSpec n gen = describe specLabel $ do
132 it "should generate valid javascript" $ do
132 it "should generate valid javascript" $ do
133− let s = jsForAPI (Proxy :: Proxy TestAPI) (concat . map gen)
133+ let s = jsForAPI (Proxy :: Proxy TestAPI) (concatMap gen)
134 parseFromString s `shouldSatisfy` isRight
134 parseFromString s `shouldSatisfy` isRight
135
135
136 it "should use non-empty function names" $ do
136 it "should use non-empty function names" $ do
@@ -167,7 +167,7 @@ generateJSSpec n gen = describe specLabel $ do
167 jsText `shouldContain` (header n "X-WhatsForDinner" $ "\"I would like \" + headerXWhatsForDinner + \" with a cherry on top.\"")
167 jsText `shouldContain` (header n "X-WhatsForDinner" $ "\"I would like \" + headerXWhatsForDinner + \" with a cherry on top.\"")
168
168
169 it "can generate the whole javascript code string at once with jsForAPI" $ do
169 it "can generate the whole javascript code string at once with jsForAPI" $ do
170− let jsStr = jsForAPI (Proxy :: Proxy TestAPI) (concat . map gen)
170+ let jsStr = jsForAPI (Proxy :: Proxy TestAPI) (concatMap gen)
171 parseFromString jsStr `shouldSatisfy` isRight
171 parseFromString jsStr `shouldSatisfy` isRight
172 where
172 where
173 specLabel = "generateJS(" ++ (show n) ++ ")"
173 specLabel = "generateJS(" ++ (show n) ++ ")"
servant-js/test/Servant/JSSpec/CustomHeaders.hs+7−7
@@ -8,13 +8,13 @@
8
8
9module Servant.JSSpec.CustomHeaders where
9module Servant.JSSpec.CustomHeaders where
10
10
11−import Control.Lens
11+import Control.Lens
12−import Data.Monoid
12+import Data.Monoid
13−import Data.Proxy
13+import Data.Proxy
14−import GHC.TypeLits
14+import GHC.TypeLits
15−import Servant.API
15+import Servant.API
16−import Servant.JS
16+import Servant.JS
17−import Servant.JS.Internal
17+import Servant.JS.Internal
18
18
19-- | This is a hypothetical combinator that fetches an Authorization header.
19-- | This is a hypothetical combinator that fetches an Authorization header.
20-- The symbol in the header denotes what kind of authentication we are
20-- The symbol in the header denotes what kind of authentication we are
servant-lucid/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-mock/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-mock/example/main.hs+9−9
@@ -1,13 +1,13 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeOperators #-}
3−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+{-# LANGUAGE TypeOperators #-}
5−import Data.Aeson
5+import Data.Aeson
6−import GHC.Generics
6+import GHC.Generics
7−import Network.Wai.Handler.Warp
7+import Network.Wai.Handler.Warp
8−import Servant
8+import Servant
9−import Servant.Mock
9+import Servant.Mock
10−import Test.QuickCheck.Arbitrary
10+import Test.QuickCheck.Arbitrary
11
11
12newtype User = User { username :: String }
12newtype User = User { username :: String }
13 deriving (Eq, Show, Arbitrary, Generic)
13 deriving (Eq, Show, Arbitrary, Generic)
servant-mock/src/Servant/Mock.hs+18−18
@@ -1,10 +1,10 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE TypeFamilies #-}
4−{-# LANGUAGE TypeOperators #-}
5−{-# LANGUAGE FlexibleContexts #-}
3+{-# LANGUAGE FlexibleContexts #-}
6−{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE TypeFamilies #-}
7+{-# LANGUAGE TypeOperators #-}
8-- |
8-- |
9-- Module : Servant.Mock
9-- Module : Servant.Mock
10-- Copyright : 2015 Alp Mestanogullari
10-- Copyright : 2015 Alp Mestanogullari
@@ -51,18 +51,18 @@
51module Servant.Mock ( HasMock(..) ) where
51module Servant.Mock ( HasMock(..) ) where
52
52
53#if !MIN_VERSION_base(4,8,0)
53#if !MIN_VERSION_base(4,8,0)
54−import Control.Applicative
54+import Control.Applicative
55#endif
55#endif
56−import Control.Monad.IO.Class
56+import Control.Monad.IO.Class
57−import Data.ByteString.Lazy.Char8 (pack)
57+import Data.ByteString.Lazy.Char8 (pack)
58−import Data.Proxy
58+import Data.Proxy
59−import GHC.TypeLits
59+import GHC.TypeLits
60−import Network.HTTP.Types.Status
60+import Network.HTTP.Types.Status
61−import Network.Wai
61+import Network.Wai
62−import Servant
62+import Servant
63−import Servant.API.ContentTypes
63+import Servant.API.ContentTypes
64−import Test.QuickCheck.Arbitrary (Arbitrary(..), vector)
64+import Test.QuickCheck.Arbitrary (Arbitrary (..), vector)
65−import Test.QuickCheck.Gen (Gen, generate)
65+import Test.QuickCheck.Gen (Gen, generate)
66
66
67-- | 'HasMock' defines an interpretation of API types
67-- | 'HasMock' defines an interpretation of API types
68-- than turns them into random-response-generating
68-- than turns them into random-response-generating
@@ -169,7 +169,7 @@ instance HasMock Raw where
169 bdy <- genBody
169 bdy <- genBody
170 respond $ responseLBS status200 [] bdy
170 respond $ responseLBS status200 [] bdy
171
171
172− where genBody = fmap pack $ generate (vector 100 :: Gen [Char])
172+ where genBody = pack <$> generate (vector 100 :: Gen [Char])
173
173
174mockArbitrary :: (MonadIO m, Arbitrary a) => m a
174mockArbitrary :: (MonadIO m, Arbitrary a) => m a
175mockArbitrary = liftIO (generate arbitrary)
175mockArbitrary = liftIO (generate arbitrary)
servant-server/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant-server/example/greet.hs+15−15
@@ -1,19 +1,19 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE PolyKinds #-}
3−{-# LANGUAGE TypeFamilies #-}
4−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
5−{-# LANGUAGE TypeOperators #-}
6{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
7−
4+{-# LANGUAGE PolyKinds #-}
5+{-# LANGUAGE TypeFamilies #-}
6+{-# LANGUAGE TypeOperators #-}
7+
8−import Data.Aeson
8+import Data.Aeson
9−import Data.Monoid
9+import Data.Monoid
10−import Data.Proxy
10+import Data.Proxy
11−import Data.Text
11+import Data.Text
12−import GHC.Generics
12+import GHC.Generics
13−import Network.Wai
13+import Network.Wai
14−import Network.Wai.Handler.Warp
14+import Network.Wai.Handler.Warp
15−
15+
16−import Servant
16+import Servant
17
17
18-- * Example
18-- * Example
19
19
servant-server/src/Servant.hs+6−6
@@ -14,9 +14,9 @@ module Servant (
14 Proxy(..),
14 Proxy(..),
15 ) where
15 ) where
16
16
17−import Data.Proxy
17+import Data.Proxy
18−import Servant.API
18+import Servant.API
19−import Servant.Common.Text
19+import Servant.Common.Text
20−import Servant.Server
20+import Servant.Server
21−import Servant.Utils.Links
21+import Servant.Utils.Links
22−import Servant.Utils.StaticFiles
22+import Servant.Utils.StaticFiles
servant-server/src/Servant/Server.hs+2−2
@@ -77,8 +77,8 @@ module Servant.Server
77
77
78 ) where
78 ) where
79
79
80−import Data.Proxy (Proxy)
80+import Data.Proxy (Proxy)
81−import Network.Wai (Application)
81+import Network.Wai (Application)
82import Servant.Server.Internal
82import Servant.Server.Internal
83import Servant.Server.Internal.Enter
83import Servant.Server.Internal.Enter
84
84
servant-server/src/Servant/Server/Internal.hs+4−6
@@ -27,7 +27,7 @@ import Control.Monad.Trans.Either (EitherT)
27import qualified Data.ByteString as B
27import qualified Data.ByteString as B
28import qualified Data.ByteString.Lazy as BL
28import qualified Data.ByteString.Lazy as BL
29import qualified Data.Map as M
29import qualified Data.Map as M
30−import Data.Maybe (catMaybes, fromMaybe)
30+import Data.Maybe (mapMaybe, fromMaybe)
31import Data.String (fromString)
31import Data.String (fromString)
32import Data.String.Conversions (cs, (<>), ConvertibleStrings)
32import Data.String.Conversions (cs, (<>), ConvertibleStrings)
33import Data.Text (Text)
33import Data.Text (Text)
@@ -137,9 +137,7 @@ processMethodRouter handleA status method headers request = case handleA of
137 Nothing -> failWith UnsupportedMediaType
137 Nothing -> failWith UnsupportedMediaType
138 Just (contentT, body) -> succeedWith $ responseLBS status hdrs bdy
138 Just (contentT, body) -> succeedWith $ responseLBS status hdrs bdy
139 where
139 where
140− bdy = case allowedMethodHead method request of
140+ bdy = if allowedMethodHead method request then "" else body
141− True -> ""
142− False -> body
143 hdrs = (hContentType, cs contentT) : (fromMaybe [] headers)
141 hdrs = (hContentType, cs contentT) : (fromMaybe [] headers)
144
142
145methodRouter :: (AllCTRender ctypes a)
143methodRouter :: (AllCTRender ctypes a)
@@ -512,7 +510,7 @@ instance (KnownSymbol sym, FromText a, HasServer sublayout)
512 -- named "foo" or "foo[]" and call fromText on the
510 -- named "foo" or "foo[]" and call fromText on the
513 -- corresponding values
511 -- corresponding values
514 parameters = filter looksLikeParam querytext
512 parameters = filter looksLikeParam querytext
515− values = catMaybes $ map (convert . snd) parameters
513+ values = mapMaybe (convert . snd) parameters
516 in route (Proxy :: Proxy sublayout) (feedTo subserver values)
514 in route (Proxy :: Proxy sublayout) (feedTo subserver values)
517 where paramname = cs $ symbolVal (Proxy :: Proxy sym)
515 where paramname = cs $ symbolVal (Proxy :: Proxy sym)
518 looksLikeParam (name, _) = name == paramname || name == (paramname <> "[]")
516 looksLikeParam (name, _) = name == paramname || name == (paramname <> "[]")
@@ -625,7 +623,7 @@ instance (KnownSymbol sym, FromText a, HasServer sublayout)
625 -- named "foo" or "foo[]" and call fromText on the
623 -- named "foo" or "foo[]" and call fromText on the
626 -- corresponding values
624 -- corresponding values
627 parameters = filter looksLikeParam matrixtext
625 parameters = filter looksLikeParam matrixtext
628− values = catMaybes $ map (convert . snd) parameters
626+ values = mapMaybe (convert . snd) parameters
629 route (Proxy :: Proxy sublayout) (feedTo subserver values)
627 route (Proxy :: Proxy sublayout) (feedTo subserver values)
630 _ -> route (Proxy :: Proxy sublayout) (feedTo subserver [])
628 _ -> route (Proxy :: Proxy sublayout) (feedTo subserver [])
631 where paramname = cs $ symbolVal (Proxy :: Proxy sym)
629 where paramname = cs $ symbolVal (Proxy :: Proxy sym)
servant-server/src/Servant/Server/Internal/PathInfo.hs+5−5
@@ -1,10 +1,10 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE OverloadedStrings #-}
2module Servant.Server.Internal.PathInfo where
2module Servant.Server.Internal.PathInfo where
3
3
4−import Data.List (unfoldr)
4+import Data.List (unfoldr)
5−import Data.Text (Text)
5+import Data.Text (Text)
6−import qualified Data.Text as T
6+import qualified Data.Text as T
7−import Network.Wai (Request, pathInfo)
7+import Network.Wai (Request, pathInfo)
8
8
9-- | Like `null . pathInfo`, but works with redundant trailing slashes.
9-- | Like `null . pathInfo`, but works with redundant trailing slashes.
10pathIsEmpty :: Request -> Bool
10pathIsEmpty :: Request -> Bool
servant-server/src/Servant/Server/Internal/Router.hs+5−5
@@ -1,10 +1,10 @@
1module Servant.Server.Internal.Router where
1module Servant.Server.Internal.Router where
2
2
3−import Data.Map (Map)
3+import Data.Map (Map)
4−import qualified Data.Map as M
4+import qualified Data.Map as M
5−import Data.Monoid ((<>))
5+import Data.Monoid ((<>))
6−import Data.Text (Text)
6+import Data.Text (Text)
7−import Network.Wai (Request, pathInfo)
7+import Network.Wai (Request, pathInfo)
8import Servant.Server.Internal.PathInfo
8import Servant.Server.Internal.PathInfo
9import Servant.Server.Internal.RoutingApplication
9import Servant.Server.Internal.RoutingApplication
10
10
servant-server/src/Servant/Server/Internal/RoutingApplication.hs+17−16
@@ -5,23 +5,24 @@
5module Servant.Server.Internal.RoutingApplication where
5module Servant.Server.Internal.RoutingApplication where
6
6
7#if !MIN_VERSION_base(4,8,0)
7#if !MIN_VERSION_base(4,8,0)
8−import Control.Applicative (Applicative, (<$>))
8+import Control.Applicative (Applicative, (<$>))
9−import Data.Monoid (Monoid, mappend, mempty)
9+import Data.Monoid (Monoid, mappend, mempty)
10#endif
10#endif
11−import Control.Monad.Trans.Either (EitherT, runEitherT)
11+import Control.Monad.Trans.Either (EitherT, runEitherT)
12−import qualified Data.ByteString as B
12+import qualified Data.ByteString as B
13−import qualified Data.ByteString.Lazy as BL
13+import qualified Data.ByteString.Lazy as BL
14−import Data.IORef (newIORef, readIORef, writeIORef)
14+import Data.IORef (newIORef, readIORef,
15+ writeIORef)
15−import Data.Maybe (fromMaybe)
16+import Data.Maybe (fromMaybe)
16−import Data.Monoid ((<>))
17+import Data.Monoid ((<>))
17−import Data.String (fromString)
18+import Data.String (fromString)
18−import Network.HTTP.Types hiding (Header, ResponseHeaders)
19+import Network.HTTP.Types hiding (Header,
20+ ResponseHeaders)
19−import Network.Wai (Application, Request, Response,
21+import Network.Wai (Application, Request,
20− ResponseReceived,
22+ Response, ResponseReceived,
21− requestBody,
23+ requestBody, responseLBS,
22− responseLBS,
23− strictRequestBody)
24+ strictRequestBody)
24−import Servant.API ((:<|>) (..))
25+import Servant.API ((:<|>) (..))
25import Servant.Server.Internal.ServantErr
26import Servant.Server.Internal.ServantErr
26
27
27type RoutingApplication =
28type RoutingApplication =
servant-server/src/Servant/Server/Internal/ServantErr.hs+4−4
@@ -2,10 +2,10 @@
2{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE RecordWildCards #-}
3module Servant.Server.Internal.ServantErr where
3module Servant.Server.Internal.ServantErr where
4
4
5−import qualified Data.ByteString.Char8 as BS
5+import qualified Data.ByteString.Char8 as BS
6−import qualified Data.ByteString.Lazy as LBS
6+import qualified Data.ByteString.Lazy as LBS
7−import qualified Network.HTTP.Types as HTTP
7+import qualified Network.HTTP.Types as HTTP
8−import Network.Wai (responseLBS, Response)
8+import Network.Wai (Response, responseLBS)
9
9
10data ServantErr = ServantErr { errHTTPCode :: Int
10data ServantErr = ServantErr { errHTTPCode :: Int
11 , errReasonPhrase :: String
11 , errReasonPhrase :: String
servant-server/src/Servant/Utils/StaticFiles.hs+6−5
@@ -7,12 +7,13 @@ module Servant.Utils.StaticFiles (
7 serveDirectory,
7 serveDirectory,
8 ) where
8 ) where
9
9
10−import System.FilePath (addTrailingPathSeparator)
11−import Network.Wai.Application.Static (staticApp, defaultFileServerSettings)
10+import Network.Wai.Application.Static (defaultFileServerSettings,
11+ staticApp)
12−import Servant.API.Raw (Raw)
12+import Servant.API.Raw (Raw)
13−import Servant.Server (Server)
13+import Servant.Server (Server)
14+import System.FilePath (addTrailingPathSeparator)
14#if !MIN_VERSION_wai_app_static(3,1,0)
15#if !MIN_VERSION_wai_app_static(3,1,0)
15−import Filesystem.Path.CurrentOS (decodeString)
16+import Filesystem.Path.CurrentOS (decodeString)
16#endif
17#endif
17
18
18-- | Serve anything under the specified directory as a 'Raw' endpoint.
19-- | Serve anything under the specified directory as a 'Raw' endpoint.
servant-server/test/Doctests.hs+1−1
@@ -1,6 +1,6 @@
1module Main where
1module Main where
2
2
3−import Data.List (isPrefixOf)
3+import Data.List (isPrefixOf)
4import System.Directory
4import System.Directory
5import System.FilePath
5import System.FilePath
6import System.FilePath.Find
6import System.FilePath.Find
servant-server/test/Servant/Server/Internal/EnterSpec.hs+4−4
@@ -3,16 +3,16 @@
3{-# LANGUAGE TypeOperators #-}
3{-# LANGUAGE TypeOperators #-}
4module Servant.Server.Internal.EnterSpec where
4module Servant.Server.Internal.EnterSpec where
5
5
6−import qualified Control.Category as C
6+import qualified Control.Category as C
7import Control.Monad.Reader
7import Control.Monad.Reader
8import Control.Monad.Trans.Either
8import Control.Monad.Trans.Either
9import Data.Proxy
9import Data.Proxy
10import Servant.API
10import Servant.API
11import Servant.Server
11import Servant.Server
12
12
13−import Test.Hspec (Spec, describe, it)
13+import Test.Hspec (Spec, describe, it)
14−import Test.Hspec.Wai (get, matchStatus, post,
14+import Test.Hspec.Wai (get, matchStatus, post,
15− shouldRespondWith, with)
15+ shouldRespondWith, with)
16
16
17spec :: Spec
17spec :: Spec
18spec = describe "module Servant.Server.Enter" $ do
18spec = describe "module Servant.Server.Enter" $ do
servant-server/test/Servant/Utils/StaticFilesSpec.hs+20−18
@@ -1,27 +1,29 @@
1−{-# LANGUAGE DataKinds #-}
1+{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TypeOperators #-}
4+{-# LANGUAGE TypeOperators #-}
5{-# OPTIONS_GHC -fno-warn-orphans #-}
5{-# OPTIONS_GHC -fno-warn-orphans #-}
6module Servant.Utils.StaticFilesSpec where
6module Servant.Utils.StaticFilesSpec where
7
7
8−import Control.Exception (bracket)
8+import Control.Exception (bracket)
9−import Data.Proxy (Proxy(Proxy))
9+import Data.Proxy (Proxy (Proxy))
10−import Network.Wai (Application)
10+import Network.Wai (Application)
11+import System.Directory (createDirectory,
11−import System.Directory (getCurrentDirectory, setCurrentDirectory, createDirectory)
12+ getCurrentDirectory,
13+ setCurrentDirectory)
12−import System.IO.Temp (withSystemTempDirectory)
14+import System.IO.Temp (withSystemTempDirectory)
13−import Test.Hspec (Spec, describe, it, around_)
15+import Test.Hspec (Spec, around_, describe, it)
14−import Test.Hspec.Wai (with, get, shouldRespondWith)
16+import Test.Hspec.Wai (get, shouldRespondWith, with)
15
17
16−import Servant.API (JSON)
18+import Servant.API (JSON)
17−import Servant.API.Alternative ((:<|>)((:<|>)))
19+import Servant.API.Alternative ((:<|>) ((:<|>)))
18−import Servant.API.Capture (Capture)
20+import Servant.API.Capture (Capture)
19−import Servant.API.Get (Get)
21+import Servant.API.Get (Get)
20−import Servant.API.Raw (Raw)
22+import Servant.API.Raw (Raw)
21−import Servant.API.Sub ((:>))
23+import Servant.API.Sub ((:>))
22−import Servant.Server (Server, serve)
24+import Servant.Server (Server, serve)
23−import Servant.ServerSpec (Person(Person))
25+import Servant.ServerSpec (Person (Person))
24−import Servant.Utils.StaticFiles (serveDirectory)
26+import Servant.Utils.StaticFiles (serveDirectory)
25
27
26type Api =
28type Api =
27 "dummy_api" :> Capture "person_name" String :> Get '[JSON] Person
29 "dummy_api" :> Capture "person_name" String :> Get '[JSON] Person
servant/Setup.hs+1−1
@@ -1,2 +1,2 @@
1−import Distribution.Simple
1+import Distribution.Simple
2main = defaultMain
2main = defaultMain
servant/default.nix−24
@@ -1,24 +0,0 @@
1−{ mkDerivation, aeson, attoparsec, base, bytestring
2−, bytestring-conversion, case-insensitive, directory, doctest
3−, filemanip, filepath, hspec, http-media, http-types, network-uri
4−, parsec, QuickCheck, quickcheck-instances, stdenv
5−, string-conversions, text, url, vault
6−}:
7−mkDerivation {
8− pname = "servant";
9− version = "0.5";
10− src = ./.;
11− buildDepends = [
12− aeson attoparsec base bytestring bytestring-conversion
13− case-insensitive http-media http-types network-uri
14− string-conversions text vault
15− ];
16− testDepends = [
17− aeson attoparsec base bytestring directory doctest filemanip
18− filepath hspec parsec QuickCheck quickcheck-instances
19− string-conversions text url
20− ];
21− homepage = "http://haskell-servant.github.io/";
22− description = "A family of combinators for defining webservices APIs";
23− license = stdenv.lib.licenses.bsd3;
24−}
servant/src/Servant/API.hs+2−2
@@ -69,8 +69,8 @@ import Servant.API.ContentTypes (Accept (..), FormUrlEncoded,
69import Servant.API.Delete (Delete)
69import Servant.API.Delete (Delete)
70import Servant.API.Get (Get)
70import Servant.API.Get (Get)
71import Servant.API.Header (Header (..))
71import Servant.API.Header (Header (..))
72−import Servant.API.HttpVersion (HttpVersion(..))
72+import Servant.API.HttpVersion (HttpVersion (..))
73−import Servant.API.IsSecure (IsSecure(..))
73+import Servant.API.IsSecure (IsSecure (..))
74import Servant.API.MatrixParam (MatrixFlag, MatrixParam,
74import Servant.API.MatrixParam (MatrixFlag, MatrixParam,
75 MatrixParams)
75 MatrixParams)
76import Servant.API.Patch (Patch)
76import Servant.API.Patch (Patch)
servant/src/Servant/API/Delete.hs+1−1
@@ -4,7 +4,7 @@
4{-# OPTIONS_HADDOCK not-home #-}
4{-# OPTIONS_HADDOCK not-home #-}
5module Servant.API.Delete (Delete) where
5module Servant.API.Delete (Delete) where
6
6
7−import Data.Typeable ( Typeable )
7+import Data.Typeable (Typeable)
8
8
9-- | Combinator for DELETE requests.
9-- | Combinator for DELETE requests.
10--
10--
servant/src/Servant/API/HttpVersion.hs+1−1
@@ -3,7 +3,7 @@ module Servant.API.HttpVersion
3 HttpVersion(..)
3 HttpVersion(..)
4 ) where
4 ) where
5
5
6−import Network.HTTP.Types (HttpVersion(..))
6+import Network.HTTP.Types (HttpVersion (..))
7
7
8-- $httpversion
8-- $httpversion
9--
9--
servant/src/Servant/API/IsSecure.hs+1−1
@@ -4,7 +4,7 @@ module Servant.API.IsSecure
4 IsSecure(..)
4 IsSecure(..)
5 ) where
5 ) where
6
6
7−import Data.Typeable
7+import Data.Typeable
8
8
9-- | Was this request made over an SSL connection?
9-- | Was this request made over an SSL connection?
10--
10--
servant/src/Servant/API/Put.hs+1−1
@@ -4,7 +4,7 @@
4{-# OPTIONS_HADDOCK not-home #-}
4{-# OPTIONS_HADDOCK not-home #-}
5module Servant.API.Put (Put) where
5module Servant.API.Put (Put) where
6
6
7−import Data.Typeable ( Typeable )
7+import Data.Typeable (Typeable)
8
8
9-- | Endpoint for PUT requests, usually used to update a ressource.
9-- | Endpoint for PUT requests, usually used to update a ressource.
10-- The type @a@ is the type of the response body that's returned.
10-- The type @a@ is the type of the response body that's returned.
servant/src/Servant/API/Raw.hs+1−1
@@ -2,7 +2,7 @@
2{-# OPTIONS_HADDOCK not-home #-}
2{-# OPTIONS_HADDOCK not-home #-}
3module Servant.API.Raw where
3module Servant.API.Raw where
4
4
5−import Data.Typeable (Typeable)
5+import Data.Typeable (Typeable)
6-- | Endpoint for plugging in your own Wai 'Application's.
6-- | Endpoint for plugging in your own Wai 'Application's.
7--
7--
8-- The given 'Application' will get the request as received by the server, potentially with
8-- The given 'Application' will get the request as received by the server, potentially with
servant/src/Servant/API/RemoteHost.hs+1−1
@@ -4,7 +4,7 @@ module Servant.API.RemoteHost
4 RemoteHost
4 RemoteHost
5 ) where
5 ) where
6
6
7−import Data.Typeable
7+import Data.Typeable
8
8
9-- | Provides access to the host or IP address
9-- | Provides access to the host or IP address
10-- from which the HTTP request was sent.
10-- from which the HTTP request was sent.
servant/src/Servant/API/Vault.hs+1−1
@@ -3,7 +3,7 @@ module Servant.API.Vault
3 Vault
3 Vault
4 ) where
4 ) where
5
5
6−import Data.Vault.Lazy (Vault)
6+import Data.Vault.Lazy (Vault)
7
7
8-- $vault
8-- $vault
9--
9--
servant/test/Doctests.hs+1−1
@@ -1,6 +1,6 @@
1module Main where
1module Main where
2
2
3−import Data.List (isPrefixOf)
3+import Data.List (isPrefixOf)
4import System.Directory
4import System.Directory
5import System.FilePath
5import System.FilePath
6import System.FilePath.Find
6import System.FilePath.Find
servant/test/Servant/API/ContentTypesSpec.hs+14−14
@@ -12,22 +12,22 @@ import Data.Monoid
12#endif
12#endif
13import Control.Arrow
13import Control.Arrow
14import Data.Aeson
14import Data.Aeson
15+import Data.ByteString.Char8 (ByteString, append, pack)
16+import qualified Data.ByteString.Lazy as BSL
15import Data.Either
17import Data.Either
16−import Data.Function (on)
18+import Data.Function (on)
19+import Data.List (maximumBy)
20+import Data.Maybe (fromJust, isJust, isNothing)
17import Data.Proxy
21import Data.Proxy
18−import Data.ByteString.Char8 (ByteString, append, pack)
19−import qualified Data.ByteString.Lazy as BSL
20−import Data.List (maximumBy)
21−import Data.Maybe (fromJust, isJust, isNothing)
22−import Data.String (IsString (..))
22+import Data.String (IsString (..))
23−import Data.String.Conversions (cs)
23+import Data.String.Conversions (cs)
24−import qualified Data.Text as TextS
24+import qualified Data.Text as TextS
25−import qualified Data.Text.Lazy as TextL
25+import qualified Data.Text.Lazy as TextL
26import GHC.Generics
26import GHC.Generics
27−import Network.URL (exportParams, importParams)
27+import Network.URL (exportParams, importParams)
28import Test.Hspec
28import Test.Hspec
29import Test.QuickCheck
29import Test.QuickCheck
30−import Test.QuickCheck.Instances ()
30+import Test.QuickCheck.Instances ()
31
31
32import Servant.API.ContentTypes
32import Servant.API.ContentTypes
33
33
@@ -57,15 +57,15 @@ spec = describe "Servant.API.ContentTypes" $ do
57 let p = Proxy :: Proxy FormUrlEncoded
57 let p = Proxy :: Proxy FormUrlEncoded
58
58
59 it "has mimeUnrender reverse mimeRender" $ do
59 it "has mimeUnrender reverse mimeRender" $ do
60− property $ \x -> all (/= mempty) x
60+ property $ \x -> mempty `notElem` x
61 ==> mimeUnrender p (mimeRender p x) == Right (x::[(TextS.Text,TextS.Text)])
61 ==> mimeUnrender p (mimeRender p x) == Right (x::[(TextS.Text,TextS.Text)])
62
62
63 it "has mimeUnrender reverse exportParams (Network.URL)" $ do
63 it "has mimeUnrender reverse exportParams (Network.URL)" $ do
64− property $ \x -> all (/= mempty) x
64+ property $ \x -> mempty `notElem` x
65 ==> (mimeUnrender p . cs . exportParams . map (cs *** cs) $ x) == Right (x::[(TextS.Text,TextS.Text)])
65 ==> (mimeUnrender p . cs . exportParams . map (cs *** cs) $ x) == Right (x::[(TextS.Text,TextS.Text)])
66
66
67 it "has importParams (Network.URL) reverse mimeRender" $ do
67 it "has importParams (Network.URL) reverse mimeRender" $ do
68− property $ \x -> all (/= mempty) x
68+ property $ \x -> mempty `notElem` x
69 ==> (fmap (map (cs *** cs)) . importParams . cs . mimeRender p $ x) == Just (x::[(TextS.Text,TextS.Text)])
69 ==> (fmap (map (cs *** cs)) . importParams . cs . mimeRender p $ x) == Just (x::[(TextS.Text,TextS.Text)])
70
70
71 describe "The PlainText Content-Type type" $ do
71 describe "The PlainText Content-Type type" $ do