servant 0.11 → 0.12
raw patch · 11 files changed
+198/−9 lines, 11 filesdep ~http-types
Dependency ranges changed: http-types
Files
- CHANGELOG.md +91/−0
- servant.cabal +13/−6
- src/Servant/API.hs +4/−0
- src/Servant/API/Alternative.hs +1/−1
- src/Servant/API/Description.hs +39/−0
- src/Servant/API/Internal/Test/ComprehensiveAPI.hs +2/−0
- src/Servant/API/Sub.hs +1/−1
- src/Servant/Utils/Enter.hs +1/−1
- src/Servant/Utils/Links.hs +32/−0
- test/Servant/Utils/EnterSpec.hs +1/−0
- test/Servant/Utils/LinksSpec.hs +13/−0
CHANGELOG.md view
@@ -1,3 +1,94 @@+[The latest version of this document is on GitHub.](https://github.com/haskell-servant/servant/blob/master/servant/CHANGELOG.md)++0.12+---++### Significant changes++- *servant-client* *servant-client-core*+ Factored out of `servant-client` all the functionality that was+ independent of the `http-client` backend.+ ([#803](https://github.com/haskell-servant/servant/pull/803)+ [#821](https://github.com/haskell-servant/servant/issues/821))++ If you have own combinators, you'll need to add an additional `m` argument+ in `HasClient`, `Client` and `clientWithRoute`:++ ```diff+ -class HasClient api+ - type Client (api :: *) :: *+ - clientWithRoute :: Proxy api -> Req -> Client api+ +class HasClient m api+ + type Client (m :: * -> *) (api :: *) :: *+ + clientWithRoute :: Proxy m -> Proxy api -> Request -> Client m api+ ```++ See https://github.com/haskell-servant/servant-auth/pull/67/commits/f777818e3cc0fa3ed2346baff8328e96d62b1790 for a real world example.++- *servant-server* Added `hoistServer` member to the `HasServer` class, which is `HasServer`+ specific `enter`.+ ([#804](https://github.com/haskell-servant/servant/pull/804)+ [#824](https://github.com/haskell-servant/servant/pull/824))++ `enter` isn't exported from `Servant` module anymore. You can change+ `enter` to `hoistServer` in a straight forward way.+ Unwrap natural transformation and add a api type `Proxy`:++ ```diff+ -server = enter (NT nt) impl+ +server = hoistServer (Proxy :: Proxy MyApi) nt impl+ ```++ If you have own combinators, you'll need to define a new method of+ `HasServer` class, for example:++ ```haskell+ type ServerT (MyCombinator :> api) m = MyValue -> ServerT api m+ hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s+ ```++ See https://github.com/haskell-servant/servant-auth/pull/67/commits/8ee3b6315247ac076516213fd7cfcdbfdb583ac9 for a real world example.++- Add `Description` and `Summary` combinators+ ([#767](https://github.com/haskell-servant/servant/pull/767))++ It's possible to annotate endpoints with free form text.+ This information is used by e.g. by `servant-swagger`, see screenshot in+ https://github.com/phadej/servant-swagger-ui++- Lower `:>` and `:<|>` infix precedence to 4 and 3 respectively+ ([#761](https://github.com/haskell-servant/servant/issues/761))++ This should affect you, except if you define your own infix operators+ for Servant type-level DSL.++### Other changes++- *servant-foreign* Derive `Data` for all types+ ([#809](https://github.com/haskell-servant/servant/pull/809))+- *servant-docs* Add authentication lenses+ ([#787](https://github.com/haskell-servant/servant/pull/787))+- *servant-docs* Generated markdown improvements+ ([#813](https://github.com/haskell-servant/servant/pull/787)+ [#767](https://github.com/haskell-servant/servant/pull/767)+ [#790](https://github.com/haskell-servant/servant/pull/790)+ [#788](https://github.com/haskell-servant/servant/pull/788))+- Add `addLinks` to generate all links for unnested APIs.+ ([#851](https://github.com/haskell-servant/servant/pull/851))+- Allow newest dependencies+ ([#772](https://github.com/haskell-servant/servant/pull/772)+ [#842](https://github.com/haskell-servant/servant/pull/842))+- Documentation improvements and typo fixes+ ([#757](https://github.com/haskell-servant/servant/pull/757)+ [#771](https://github.com/haskell-servant/servant/pull/771)+ [#775](https://github.com/haskell-servant/servant/pull/775)+ [#790](https://github.com/haskell-servant/servant/pull/790)+ [#791](https://github.com/haskell-servant/servant/pull/791)+ [#806](https://github.com/haskell-servant/servant/pull/806))+- Development process improvements+ ([#764](https://github.com/haskell-servant/servant/pull/764)+ [#839](https://github.com/haskell-servant/servant/pull/839))+ 0.11 ----
servant.cabal view
@@ -1,5 +1,5 @@ name: servant-version: 0.11+version: 0.12 synopsis: A family of combinators for defining webservices APIs description: A family of combinators for defining webservices APIs and serving them@@ -14,10 +14,14 @@ author: Servant Contributors maintainer: haskell-servant-maintainers@googlegroups.com copyright: 2014-2016 Zalora South East Asia Pte Ltd, Servant Contributors-category: Servant Web+category: Servant, Web build-type: Custom cabal-version: >=1.10-tested-with: GHC >= 7.8+tested-with:+ GHC==7.8.4+ GHC==7.10.3+ GHC==8.0.2+ GHC==8.2.1 extra-source-files: include/*.h CHANGELOG.md@@ -38,6 +42,7 @@ Servant.API.BasicAuth Servant.API.Capture Servant.API.ContentTypes+ Servant.API.Description Servant.API.Empty Servant.API.Experimental.Auth Servant.API.Header@@ -57,15 +62,15 @@ Servant.Utils.Links Servant.Utils.Enter build-depends:- base >= 4.7 && < 4.10+ base >= 4.7 && < 4.11 , base-compat >= 0.9 && < 0.10 , aeson >= 0.7 && < 1.3 , attoparsec >= 0.12 && < 0.14 , bytestring >= 0.10 && < 0.11 , case-insensitive >= 1.2 && < 1.3 , http-api-data >= 0.3 && < 0.4- , http-media >= 0.4 && < 0.7- , http-types >= 0.8 && < 0.10+ , http-media >= 0.4 && < 0.8+ , http-types >= 0.8 && < 0.11 , natural-transformation >= 0.4 && < 0.5 , mtl >= 2.0 && < 2.3 , mmorph >= 1 && < 1.2@@ -117,6 +122,8 @@ Servant.API.ResponseHeadersSpec Servant.Utils.LinksSpec Servant.Utils.EnterSpec+ build-tool-depends:+ hspec-discover:hspec-discover build-depends: base == 4.* , base-compat
src/Servant/API.hs view
@@ -34,6 +34,9 @@ -- * Authentication module Servant.API.BasicAuth, + -- * Endpoints description+ module Servant.API.Description,+ -- * Content Types module Servant.API.ContentTypes, -- | Serializing and deserializing types based on @Accept@ and@@ -68,6 +71,7 @@ MimeRender (..), NoContent (NoContent), MimeUnrender (..), OctetStream, PlainText)+import Servant.API.Description (Description, Summary) import Servant.API.Empty (EmptyAPI (..)) import Servant.API.Experimental.Auth (AuthProtect) import Servant.API.Header (Header (..))
src/Servant/API/Alternative.hs view
@@ -22,7 +22,7 @@ -- :} data a :<|> b = a :<|> b deriving (Typeable, Eq, Show, Functor, Traversable, Foldable, Bounded)-infixr 8 :<|>+infixr 3 :<|> instance (Semigroup a, Semigroup b) => Semigroup (a :<|> b) where (a :<|> b) <> (a' :<|> b') = (a <> a') :<|> (b <> b')
+ src/Servant/API/Description.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE PolyKinds #-}+{-# OPTIONS_HADDOCK not-home #-}+module Servant.API.Description (Description, Summary) where++import Data.Typeable (Typeable)+import GHC.TypeLits (Symbol)+-- | Add a short summary for (part of) API.+--+-- Example:+--+-- >>> type MyApi = Summary "Get book by ISBN." :> "books" :> Capture "isbn" Text :> Get '[JSON] Book+data Summary (sym :: Symbol)+ deriving (Typeable)++-- | Add more verbose description for (part of) API.+--+-- Example:+--+-- >>> :{+--type MyApi = Description+-- "This comment is visible in multiple Servant interpretations \+-- \and can be really long if necessary. \+-- \Haskell multiline support is not perfect \+-- \but it's still very readable."+-- :> Get '[JSON] Book+-- :}+data Description (sym :: Symbol)+ deriving (Typeable)++-- $setup+-- >>> import Servant.API+-- >>> import Data.Aeson+-- >>> import Data.Text+-- >>> data Book+-- >>> instance ToJSON Book where { toJSON = undefined }+-- >>> data SourceFile+-- >>> instance ToJSON SourceFile where { toJSON = undefined }
src/Servant/API/Internal/Test/ComprehensiveAPI.hs view
@@ -38,6 +38,8 @@ Verb 'POST 204 '[JSON] Int :<|> WithNamedContext "foo" '[] GET :<|> CaptureAll "foo" Int :> GET :<|>+ Summary "foo" :> GET :<|>+ Description "foo" :> GET :<|> EmptyAPI comprehensiveAPIWithoutRaw :: Proxy ComprehensiveAPIWithoutRaw
src/Servant/API/Sub.hs view
@@ -16,7 +16,7 @@ -- >>> type MyApi = "hello" :> "world" :> Get '[JSON] World data (path :: k) :> a deriving (Typeable)-infixr 9 :>+infixr 4 :> -- $setup -- >>> import Servant.API
src/Servant/Utils/Enter.hs view
@@ -8,7 +8,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}-module Servant.Utils.Enter (+module Servant.Utils.Enter {-# DEPRECATED "Use hoistServer or hoistServerWithContext from servant-server" #-} ( module Servant.Utils.Enter, -- * natural-transformation re-exports (:~>)(..),
src/Servant/Utils/Links.hs view
@@ -84,6 +84,7 @@ -- -- | Note that 'URI' is from the "Network.URI" module in the @network-uri@ package. safeLink+ , allLinks , URI(..) -- * Adding custom types , HasLink(..)@@ -108,6 +109,7 @@ import Prelude.Compat import Web.HttpApiData+import Servant.API.Alternative ( (:<|>)((:<|>)) ) import Servant.API.BasicAuth ( BasicAuth ) import Servant.API.Capture ( Capture, CaptureAll ) import Servant.API.ReqBody ( ReqBody )@@ -220,6 +222,30 @@ -> MkLink endpoint safeLink _ endpoint = toLink endpoint (Link mempty mempty) +-- | Create all links in an API.+--+-- Note that the @api@ type must be restricted to the endpoints that have+-- valid links to them.+--+-- >>> type API = "foo" :> Capture "name" Text :> Get '[JSON] Text :<|> "bar" :> Capture "name" Int :> Get '[JSON] Double+-- >>> let fooLink :<|> barLink = allLinks (Proxy :: Proxy API)+-- >>> :t fooLink+-- fooLink :: Text -> Link+-- >>> :t barLink+-- barLink :: Int -> Link+--+-- Note: nested APIs don't work well with this approach+--+-- >>> :kind! MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double))+-- MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double)) :: *+-- = Char -> (Int -> Link) :<|> (Double -> Link)+--+allLinks+ :: forall api. HasLink api+ => Proxy api+ -> MkLink api+allLinks api = toLink api (Link mempty mempty)+ -- | Construct a toLink for an endpoint. class HasLink endpoint where type MkLink endpoint@@ -266,6 +292,11 @@ where k = symbolVal (Proxy :: Proxy sym) +-- :<|> instance - Generate all links at once+instance (HasLink a, HasLink b) => HasLink (a :<|> b) where+ type MkLink (a :<|> b) = MkLink a :<|> MkLink b+ toLink _ l = toLink (Proxy :: Proxy a) l :<|> toLink (Proxy :: Proxy b) l+ -- Misc instances instance HasLink sub => HasLink (ReqBody ct a :> sub) where type MkLink (ReqBody ct a :> sub) = MkLink sub@@ -313,3 +344,4 @@ -- $setup -- >>> import Servant.API+-- >>> import Data.Text (Text)
test/Servant/Utils/EnterSpec.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-deprecations #-} module Servant.Utils.EnterSpec where import Test.Hspec (Spec)
test/Servant/Utils/LinksSpec.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ScopedTypeVariables #-} module Servant.Utils.LinksSpec where import Data.Proxy (Proxy (..))@@ -10,6 +11,7 @@ import Data.String (fromString) import Servant.API+import Servant.Utils.Links (allLinks) type TestApi = -- Capture and query params@@ -27,7 +29,11 @@ :<|> "raw" :> Raw :<|> NoEndpoint +type LinkableApi =+ "all" :> CaptureAll "names" String :> Get '[JSON] NoContent+ :<|> "get" :> Get '[JSON] NoContent + apiLink :: (IsElem endpoint TestApi, HasLink endpoint) => Proxy endpoint -> MkLink endpoint apiLink = safeLink (Proxy :: Proxy TestApi)@@ -66,6 +72,13 @@ apiLink (Proxy :: Proxy ("post" :> Post '[JSON] NoContent)) `shouldBeLink` "post" apiLink (Proxy :: Proxy ("delete" :> Delete '[JSON] NoContent)) `shouldBeLink` "delete" apiLink (Proxy :: Proxy ("raw" :> Raw)) `shouldBeLink` "raw"++ it "can generate all links for an API that has only linkable endpoints" $ do+ let (allNames :<|> simple) = allLinks (Proxy :: Proxy LinkableApi)+ simple+ `shouldBeLink` "get"+ allNames ["Seneca", "Aurelius"]+ `shouldBeLink` "all/Seneca/Aurelius" -- |