servant-elm 0.3.0.0 → 0.3.0.1
raw patch · 12 files changed
+149/−73 lines, 12 filesdep −data-defaultdep ~basedep ~servantPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
Dependencies removed: data-default
Dependency ranges changed: base, servant
API changes (from Hackage documentation)
+ Servant.Elm.Internal.Generate: elmBodyArg :: Doc
+ Servant.Elm.Internal.Generate: elmCaptureArg :: Segment ElmDatatype -> Doc
+ Servant.Elm.Internal.Generate: elmHeaderArg :: HeaderArg ElmDatatype -> Doc
+ Servant.Elm.Internal.Generate: elmQueryArg :: QueryArg ElmDatatype -> Doc
Files
- CHANGELOG.md +5/−0
- README.md +1/−0
- servant-elm.cabal +30/−10
- src/Servant/Elm/Internal/Generate.hs +33/−9
- test/Common.hs +52/−0
- test/CompileSpec.hs +7/−2
- test/GenerateSpec.hs +5/−35
- test/Spec.hs +0/−1
- test/elm-sources/getBooksByIdSource.elm +2/−2
- test/elm-sources/getBooksByTitleSource.elm +2/−2
- test/elm-sources/getBooksSource.elm +9/−9
- test/elm-sources/getWithaheaderSource.elm +3/−3
CHANGELOG.md view
@@ -1,3 +1,8 @@+0.3.0.1+-------+* Prefix generated function arguments to ensure valid Elm identifiers (#21)+* Put integration tests behind a Cabal flag. (#22)+ 0.3.0.0 ------- * Update for Elm 0.18 and the new elm-lang/http library.
README.md view
@@ -118,6 +118,7 @@ $ git clone https://github.com/mattjbray/servant-elm.git $ cd servant-elm $ stack test+$ stack test --flag servant-elm:integration ``` To build all examples:
servant-elm.cabal view
@@ -1,5 +1,5 @@ name: servant-elm-version: 0.3.0.0+version: 0.3.0.1 synopsis: Automatically derive Elm functions to query servant webservices. description: Please see README.md homepage: http://github.com/mattjbray/servant-elm#readme@@ -21,6 +21,10 @@ Description: Build the example programs. Default: False +flag integration+ Description: Build the integration tests (requires an Elm installation).+ Default: False+ library hs-source-dirs: src exposed-modules: Servant.Elm@@ -40,23 +44,39 @@ test-suite servant-elm-test type: exitcode-stdio-1.0 hs-source-dirs: test- main-is: Spec.hs- other-modules: CompileSpec- , GenerateSpec- build-depends: Diff+ main-is: GenerateSpec.hs+ other-modules: Common+ build-depends:+ Diff , HUnit , aeson >= 0.9 , base- , data-default- , directory , elm-export >= 0.5 , hspec- , interpolate- , mockery- , process , servant , servant-elm , text+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+ default-language: Haskell2010++test-suite servant-elm-test-integration+ if !flag(integration)+ Buildable: False+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: CompileSpec.hs+ other-modules: Common+ build-depends: aeson >= 0.9+ , base+ , directory+ , elm-export >= 0.5+ , hspec+ , interpolate+ , mockery+ , process+ , servant+ , servant-elm+ , text ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall default-language: Haskell2010
src/Servant/Elm/Internal/Generate.hs view
@@ -214,26 +214,49 @@ pure ("Http.Request" <+> parens result) +elmHeaderArg :: F.HeaderArg ElmDatatype -> Doc+elmHeaderArg header =+ "header_" <>+ header ^. F.headerArg . F.argName . to (stext . F.unPathSegment)+++elmCaptureArg :: F.Segment ElmDatatype -> Doc+elmCaptureArg segment =+ "capture_" <>+ F.captureArg segment ^. F.argName . to (stext . F.unPathSegment)+++elmQueryArg :: F.QueryArg ElmDatatype -> Doc+elmQueryArg arg =+ "query_" <>+ arg ^. F.queryArgName . F.argName . to (stext . F.unPathSegment)+++elmBodyArg :: Doc+elmBodyArg =+ "body"++ mkArgs :: F.Req ElmDatatype -> Doc mkArgs request = (hsep . concat) $ [ -- Headers- [ header ^. F.headerArg . F.argName . to (stext . F.unPathSegment)+ [ elmHeaderArg header | header <- request ^. F.reqHeaders ] , -- URL Captures- [ F.captureArg segment ^. F.argName . to (stext . F.unPathSegment)+ [ elmCaptureArg segment | segment <- request ^. F.reqUrl . F.path , F.isCapture segment ] , -- Query params- [ arg ^. F.queryArgName . F.argName . to (stext . F.unPathSegment)+ [ elmQueryArg arg | arg <- request ^. F.reqUrl . F.queryStr ] , -- Request body- maybe [] (const ["body"]) (request ^. F.reqBody)+ maybe [] (const [elmBodyArg]) (request ^. F.reqBody) ] @@ -278,7 +301,7 @@ "|> String.join" <+> dquotes "&") where name =- qarg ^. F.queryArgName . F.argName . to (stext . F.unPathSegment)+ elmQueryArg qarg mkRequest :: ElmOptions -> F.Req ElmDatatype -> Doc@@ -309,12 +332,13 @@ headers = [("Http.header" <+> dquotes headerName <+> (if isElmStringType opts (header ^. F.headerArg . F.argType) then- headerName+ headerArgName else- parens ("toString " <> headerName)+ parens ("toString " <> headerArgName) )) | header <- request ^. F.reqHeaders , headerName <- [header ^. F.headerArg . F.argName . to (stext . F.unPathSegment)]+ , headerArgName <- [elmHeaderArg header] ] url =@@ -331,7 +355,7 @@ encoderName = Elm.toElmEncoderRefWith (elmExportOptions opts) elmTypeExpr in- "Http.jsonBody" <+> parens (stext encoderName <+> "body")+ "Http.jsonBody" <+> parens (stext encoderName <+> elmBodyArg) expect = case request ^. F.reqReturnType of@@ -376,7 +400,7 @@ else " |> toString" in- (arg ^. F.argName . to (stext . F.unPathSegment )) <> toStringSrc <> " |> Http.encodeUri"+ (elmCaptureArg s) <> toStringSrc <> " |> Http.encodeUri" mkQueryParams
+ test/Common.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeOperators #-}+module Common where++import Data.Aeson (ToJSON)+import Data.Proxy (Proxy(Proxy))+import Elm (ElmType)+import GHC.Generics (Generic)+import Servant.API ((:<|>), (:>), Capture, Get, GetNoContent, Header,+ JSON, NoContent, Post, PostNoContent, Put,+ QueryFlag, QueryParam, QueryParams, ReqBody)++data Book = Book+ { title :: String+ } deriving (Generic)++instance ToJSON Book+instance ElmType Book++type TestApi =+ "one"+ :> Get '[JSON] Int+ :<|> "two"+ :> ReqBody '[JSON] String+ :> Post '[JSON] (Maybe Int)+ :<|> "books"+ :> Capture "id" Int+ :> Get '[JSON] Book+ :<|> "books"+ :> Capture "title" String+ :> Get '[JSON] Book+ :<|> "books"+ :> QueryFlag "published"+ :> QueryParam "sort" String+ :> QueryParam "year" Int+ :> QueryParams "filters" (Maybe Bool)+ :> Get '[JSON] [Book]+ :<|> "books"+ :> ReqBody '[JSON] Book+ :> PostNoContent '[JSON] NoContent+ :<|> "nothing"+ :> GetNoContent '[JSON] NoContent+ :<|> "nothing"+ :> Put '[JSON] () -- old way to specify no content+ :<|> "with-a-header"+ :> Header "myStringHeader" String+ :> Header "MyIntHeader" Int+ :> Get '[JSON] String++testApi :: Proxy TestApi+testApi = Proxy
test/CompileSpec.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} -module CompileSpec where+module Main where import Test.Hspec import Test.Mockery.Directory@@ -15,7 +15,6 @@ import Elm (toElmDecoderSource, toElmEncoderSource, toElmTypeSource)-import GenerateSpec import Servant.API (NoContent) import Servant.Elm import System.Directory (canonicalizePath,@@ -24,6 +23,12 @@ getCurrentDirectory, removeFile, setCurrentDirectory) import System.Process++import Common (Book, testApi)++main :: IO ()+main =+ hspec spec spec :: Test.Hspec.Spec spec = do
test/GenerateSpec.hs view
@@ -3,54 +3,24 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeOperators #-} -module GenerateSpec where+module Main where import Control.Monad (zipWithM_)-import Data.Aeson (ToJSON) import qualified Data.Algorithm.Diff as Diff import qualified Data.Algorithm.DiffOutput as Diff import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T-import GHC.Generics (Generic)-import Servant.API import Servant.Elm-import Test.Hspec (Spec, describe, it)+import Test.Hspec (Spec, describe, hspec, it) import Test.HUnit (Assertion, assertBool) --data Book = Book- { title :: String- } deriving (Generic)--instance ToJSON Book-instance ElmType Book+import Common (testApi) -type TestApi =- "one" :> Get '[JSON] Int- :<|> "two" :> ReqBody '[JSON] String- :> Post '[JSON] (Maybe Int)- :<|> "books" :> Capture "id" Int- :> Get '[JSON] Book- :<|> "books" :> Capture "title" String- :> Get '[JSON] Book- :<|> "books" :> QueryFlag "published"- :> QueryParam "sort" String- :> QueryParam "year" Int- :> QueryParams "filters" (Maybe Bool)- :> Get '[JSON] [Book]- :<|> "books" :> ReqBody '[JSON] Book- :> PostNoContent '[JSON] NoContent- :<|> "nothing" :> GetNoContent '[JSON] NoContent- :<|> "nothing" :> Put '[JSON] () -- old way to specify no content- :<|> "with-a-header" :> Header "myStringHeader" String- :> Header "myIntHeader" Int- :> Get '[JSON] String--testApi :: Proxy TestApi-testApi = Proxy+main :: IO ()+main = hspec spec spec :: Test.Hspec.Spec spec = do
− test/Spec.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
test/elm-sources/getBooksByIdSource.elm view
@@ -4,7 +4,7 @@ getBooksById : Int -> Http.Request (Book)-getBooksById id =+getBooksById capture_id = Http.request { method = "GET"@@ -14,7 +14,7 @@ String.join "/" [ "" , "books"- , id |> toString |> Http.encodeUri+ , capture_id |> toString |> Http.encodeUri ] , body = Http.emptyBody
test/elm-sources/getBooksByTitleSource.elm view
@@ -4,7 +4,7 @@ getBooksByTitle : String -> Http.Request (Book)-getBooksByTitle title =+getBooksByTitle capture_title = Http.request { method = "GET"@@ -14,7 +14,7 @@ String.join "/" [ "" , "books"- , title |> Http.encodeUri+ , capture_title |> Http.encodeUri ] , body = Http.emptyBody
test/elm-sources/getBooksSource.elm view
@@ -5,22 +5,22 @@ getBooks : Bool -> Maybe (String) -> Maybe (Int) -> List (Maybe (Bool)) -> Http.Request (List (Book))-getBooks published sort year filters =+getBooks query_published query_sort query_year query_filters = let params = List.filter (not << String.isEmpty)- [ if published then- "published="+ [ if query_published then+ "query_published=" else ""- , sort- |> Maybe.map (Http.encodeUri >> (++) "sort=")+ , query_sort+ |> Maybe.map (Http.encodeUri >> (++) "query_sort=") |> Maybe.withDefault ""- , year- |> Maybe.map (toString >> Http.encodeUri >> (++) "year=")+ , query_year+ |> Maybe.map (toString >> Http.encodeUri >> (++) "query_year=") |> Maybe.withDefault ""- , filters- |> List.map (\val -> "filters[]=" ++ (val |> toString |> Http.encodeUri))+ , query_filters+ |> List.map (\val -> "query_filters[]=" ++ (val |> toString |> Http.encodeUri)) |> String.join "&" ] in
test/elm-sources/getWithaheaderSource.elm view
@@ -5,13 +5,13 @@ getWithaheader : String -> Int -> Http.Request (String)-getWithaheader myStringHeader myIntHeader =+getWithaheader header_myStringHeader header_MyIntHeader = Http.request { method = "GET" , headers =- [ Http.header "myStringHeader" myStringHeader- , Http.header "myIntHeader" (toString myIntHeader)+ [ Http.header "myStringHeader" header_myStringHeader+ , Http.header "MyIntHeader" (toString header_MyIntHeader) ] , url = String.join "/"