lackey 1.0.16 → 2.0.0.0
raw patch · 7 files changed
+479/−340 lines, 7 filesdep ~basedep ~servantdep ~servant-foreignPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, servant, servant-foreign, text
API changes (from Hackage documentation)
Files
- CHANGELOG.markdown +4/−0
- LICENSE.markdown +1/−1
- lackey.cabal +37/−15
- source/library/Lackey.hs +181/−0
- source/test-suite/Main.hs +256/−0
- src/lib/Lackey.hs +0/−191
- src/test/Main.hs +0/−133
+ CHANGELOG.markdown view
@@ -0,0 +1,4 @@+# Change log++Lackey follows the [Package Versioning Policy](https://pvp.haskell.org).+You can find release notes [on GitHub](https://github.com/tfausak/lackey/releases).
LICENSE.markdown view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Taylor Fausak+Copyright (c) 2022 Taylor Fausak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
lackey.cabal view
@@ -1,7 +1,7 @@-cabal-version: >= 1.10+cabal-version: 2.2 name: lackey-version: 1.0.16+version: 2.0.0.0 synopsis: Generate Ruby clients from Servant APIs. description: Lackey generates Ruby clients from Servant APIs.@@ -9,7 +9,7 @@ bug-reports: https://github.com/tfausak/lackey/issues build-type: Simple category: Web-extra-source-files: README.markdown+extra-source-files: CHANGELOG.markdown README.markdown homepage: https://github.com/tfausak/lackey#readme license-file: LICENSE.markdown license: MIT@@ -19,35 +19,57 @@ location: https://github.com/tfausak/lackey type: git -library+flag pedantic+ default: False+ description: Enables @-Werror@, which turns warnings into errors.+ manual: True++common library build-depends:- base >= 4.13.0 && < 4.16- , servant >= 0.16.2 && < 0.19+ , base >= 4.13.0 && < 4.17 , servant-foreign >= 0.15 && < 0.16 , text >= 1.2.4 && < 1.3 default-language: Haskell2010- exposed-modules: Lackey ghc-options: -Weverything+ -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-exported-signatures -Wno-unsafe- hs-source-dirs: src/lib + if flag(pedantic)+ ghc-options: -Werror+ if impl(ghc >= 8.10) ghc-options: -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module + if impl(ghc >= 9.2)+ ghc-options:+ -Wno-missing-kind-signatures++common executable+ import: library++ build-depends: lackey+ ghc-options:+ -rtsopts+ -threaded+ -Wno-unused-packages++library+ import: library++ exposed-modules: Lackey+ hs-source-dirs: source/library+ test-suite test+ import: executable+ build-depends:- base -any , hspec >= 2.7.6 && < 2.10- , lackey -any- , servant -any- , servant-foreign -any- , text -any- default-language: Haskell2010- hs-source-dirs: src/test+ , servant >= 0.16.2 && < 0.19+ hs-source-dirs: source/test-suite main-is: Main.hs type: exitcode-stdio-1.0
+ source/library/Lackey.hs view
@@ -0,0 +1,181 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}++module Lackey+ ( rubyForAPI+ ) where++import qualified Data.Char as Char+import Data.Function ((&))+import qualified Data.Maybe as Maybe+import qualified Data.Proxy as Proxy+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Servant.Foreign as Servant++type Language = Servant.NoTypes++languageProxy :: Proxy.Proxy Language+languageProxy = Proxy.Proxy++type Request = Servant.NoContent++requestProxy :: Proxy.Proxy Request+requestProxy = Proxy.Proxy++renderRequests :: [Servant.Req Request] -> Text.Text+renderRequests requests = requests & fmap renderRequest & Text.intercalate ";"++functionName :: Servant.Req Request -> Text.Text+functionName request = request & Servant._reqFuncName & Servant.snakeCase++hasBody :: Servant.Req Request -> Bool+hasBody request = case Servant._reqBody request of+ Nothing -> False+ Just _ -> True++bodyArgument :: Text.Text+bodyArgument = "body"++underscore :: Text.Text -> Text.Text+underscore text =+ text & Text.toLower & Text.map (\c -> if Char.isAlphaNum c then c else '_')++getHeaders :: Servant.Req Request -> [Text.Text]+getHeaders request =+ request+ & Servant._reqHeaders+ & Maybe.mapMaybe+ (\h -> case h of+ Servant.HeaderArg x -> Just x+ Servant.ReplaceHeaderArg _ _ -> Nothing+ )+ & fmap (Servant.unPathSegment . Servant._argName)++getURLPieces :: Servant.Req Request -> [Either Text.Text Text.Text]+getURLPieces request =+ let+ url = request & Servant._reqUrl+ path =+ url+ & Servant._path+ & Maybe.mapMaybe+ ((\segment -> case segment of+ Servant.Static _ -> Nothing+ Servant.Cap arg -> Just arg+ )+ . Servant.unSegment+ )+ & fmap (Servant.unPathSegment . Servant._argName)+ query = url & Servant._queryStr & fmap+ (Servant.unPathSegment . Servant._argName . Servant._queryArgName)+ in fmap Left path <> fmap Right query++functionArguments :: Servant.Req Request -> Text.Text+functionArguments request = Text.concat+ [ "("+ , [ [Just "excon"]+ , request & getURLPieces & fmap+ (\piece -> Just $ case piece of+ Left capture -> underscore capture+ Right param -> underscore param <> ": nil"+ )+ , request & getHeaders & fmap (Just . (<> ": nil") . underscore)+ , [if hasBody request then Just bodyArgument else Nothing]+ ]+ & concat+ & Maybe.catMaybes+ & Text.intercalate ","+ , ")"+ ]++requestMethod :: Servant.Req Request -> Text.Text+requestMethod request =+ request & Servant._reqMethod & Text.decodeUtf8 & Text.toLower & Text.cons ':'++requestPath :: Servant.Req Request -> Text.Text+requestPath request =+ let+ path =+ request+ & Servant._reqUrl+ & Servant._path+ & fmap+ ((\x -> case x of+ Servant.Static y -> Servant.unPathSegment y+ Servant.Cap y ->+ let+ z =+ y & Servant._argName & Servant.unPathSegment & underscore+ in "#{" <> z <> "}"+ )+ . Servant.unSegment+ )+ & Text.intercalate "/"+ query =+ request+ & Servant._reqUrl+ & Servant._queryStr+ & fmap+ ((\x -> x <> "=#{" <> underscore x <> "}")+ . Servant.unPathSegment+ . Servant._argName+ . Servant._queryArgName+ )+ & Text.intercalate "&"+ url = "/" <> path <> (if Text.null query then "" else "?" <> query)+ in "\"" <> url <> "\""++requestHeaders :: Servant.Req Request -> Text.Text+requestHeaders request =+ [ ["{"]+ , request & getHeaders & fmap (\x -> "\"" <> x <> "\"=>" <> underscore x)+ , ["}"]+ ]+ & concat+ & Text.concat++requestBody :: Servant.Req Request -> Text.Text+requestBody request = if hasBody request then bodyArgument else "nil"++functionBody :: Servant.Req Request -> Text.Text+functionBody request = Text.concat+ [ "excon.request("+ , ":method=>"+ , requestMethod request+ , ","+ , ":path=>"+ , requestPath request+ , ","+ , ":headers=>"+ , requestHeaders request+ , ","+ , ":body=>"+ , requestBody request+ , ")"+ ]++renderRequest :: Servant.Req Request -> Text.Text+renderRequest request = Text.concat+ [ "def "+ , functionName request+ , functionArguments request+ , functionBody request+ , "end"+ ]++requestsForAPI+ :: ( Servant.HasForeign Language Request api+ , Servant.GenerateList Request (Servant.Foreign Request api)+ )+ => Proxy.Proxy api+ -> [Servant.Req Request]+requestsForAPI api = api & Servant.listFromAPI languageProxy requestProxy++rubyForAPI+ :: ( Servant.HasForeign Language Request api+ , Servant.GenerateList Request (Servant.Foreign Request api)+ )+ => Proxy.Proxy api+ -> Text.Text+rubyForAPI api = api & requestsForAPI & renderRequests
+ source/test-suite/Main.hs view
@@ -0,0 +1,256 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}++import qualified Data.Proxy as Proxy+import qualified Data.Text as Text+import qualified Lackey+import qualified Servant.API as Servant+import qualified Test.Hspec as Hspec++main :: IO ()+main =+ Hspec.hspec+ . Hspec.parallel+ . Hspec.describe "Lackey"+ . Hspec.describe "rubyForAPI"+ $ do++ Hspec.it "supports delete requests" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy (Servant.Delete '[Servant.JSON] ())+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "delete" "" "delete" "" "" False++ Hspec.it "supports get requests" $ do+ let+ api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] ())+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" "" "get" "" "" False++ Hspec.it "supports patch requests" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy (Servant.Patch '[Servant.JSON] ())+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "patch" "" "patch" "" "" False++ Hspec.it "supports post requests" $ do+ let+ api = Proxy.Proxy :: Proxy.Proxy (Servant.Post '[Servant.JSON] ())+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "post" "" "post" "" "" False++ Hspec.it "supports put requests" $ do+ let+ api = Proxy.Proxy :: Proxy.Proxy (Servant.Put '[Servant.JSON] ())+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "put" "" "put" "" "" False++ Hspec.it "supports alternatives" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.Get '[Servant.JSON] () Servant.:<|> Servant.Delete '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api `Hspec.shouldBe` Text.concat+ [ ruby "get" "" "get" "" "" False+ , Text.singleton ';'+ , ruby "delete" "" "delete" "" "" False+ ]++ Hspec.it "supports captures" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.Capture "id" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get_by_id" ",id" "get" "#{id}" "" False++ Hspec.it "supports query flags" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryFlag "flag" Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby+ "get"+ ",flag: nil"+ "get"+ "?flag=#{flag}"+ ""+ False++ Hspec.it "supports query params" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryParam "param" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby+ "get"+ ",param: nil"+ "get"+ "?param=#{param}"+ ""+ False++ Hspec.it "supports multiple query params" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryParams "params" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby+ "get"+ ",params: nil"+ "get"+ "?params=#{params}"+ ""+ False++ Hspec.it "supports request bodies" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" ",body" "get" "" "" True++ Hspec.it "supports request headers" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.Header "cookie" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby+ "get"+ ",cookie: nil"+ "get"+ ""+ "\"cookie\"=>cookie"+ False++ Hspec.it "supports response headers" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ (Servant.Get '[Servant.JSON] (Servant.Headers '[] ()))+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" "" "get" "" "" False++ Hspec.it "puts the body param after captures" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.Capture "segment" () Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby+ "get_by_segment"+ ",segment,body"+ "get"+ "#{segment}"+ ""+ True++ Hspec.it "puts the body param after query params" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryFlag "flag" Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby+ "get"+ ",flag: nil,body"+ "get"+ "?flag=#{flag}"+ ""+ True++ Hspec.it "sanitizes path segments" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ("A!" Servant.:> Servant.Get '[Servant.JSON] ())+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get_A!" "" "get" "A!" "" False++ Hspec.it "sanitizes captures" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.Capture "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get_by_A!" ",a_" "get" "#{a_}" "" False++ Hspec.it "sanitizes query flags" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryFlag "A!" Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False++ Hspec.it "sanitizes query params" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryParam "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False++ Hspec.it "sanitizes multiple query params" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.QueryParams "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False++ Hspec.it "sanitizes headers" $ do+ let+ api =+ Proxy.Proxy :: Proxy.Proxy+ ( Servant.Header "A!" () Servant.:> Servant.Get '[Servant.JSON] ()+ )+ Lackey.rubyForAPI api+ `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "" "\"A!\"=>a_" False++-- Since every generated function has the same structure, it can be abstracted+-- away behind this function.+ruby :: String -> String -> String -> String -> String -> Bool -> Text.Text+ruby name params method path headers body = Text.pack+ (concat+ [ "def "+ , name+ , "(excon"+ , params+ , ")"+ , "excon.request("+ , ":method=>:"+ , method+ , ","+ , ":path=>\"/"+ , path+ , "\","+ , ":headers=>{"+ , headers+ , "},"+ , ":body=>"+ , if body then "body" else "nil"+ , ")"+ , "end"+ ]+ )
− src/lib/Lackey.hs
@@ -1,191 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}--module Lackey- ( rubyForAPI- ) where--import qualified Data.Char as Char-import Data.Function ((&))-import qualified Data.Maybe as Maybe-import qualified Data.Proxy as Proxy-import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import qualified Servant.Foreign as Servant--type Language = Servant.NoTypes--languageProxy :: Proxy.Proxy Language-languageProxy = Proxy.Proxy--type Request = Servant.NoContent--requestProxy :: Proxy.Proxy Request-requestProxy = Proxy.Proxy--renderRequests :: [Servant.Req Request] -> Text.Text-renderRequests requests = requests & map renderRequest & Text.intercalate ";"--functionName :: Servant.Req Request -> Text.Text-functionName request = request & Servant._reqFuncName & Servant.snakeCase--hasBody :: Servant.Req Request -> Bool-hasBody request =- case Servant._reqBody request of- Nothing -> False- Just _ -> True--bodyArgument :: Text.Text-bodyArgument = "body"--underscore :: Text.Text -> Text.Text-underscore text =- text & Text.toLower &- Text.map- (\c ->- if Char.isAlphaNum c- then c- else '_')--getHeaders :: Servant.Req Request -> [Text.Text]-getHeaders request =- request & Servant._reqHeaders &- Maybe.mapMaybe- (\h ->- case h of- Servant.HeaderArg x -> Just x- Servant.ReplaceHeaderArg _ _ -> Nothing) &- map Servant._argName &- map Servant.unPathSegment--getURLPieces :: Servant.Req Request -> [Either Text.Text Text.Text]-getURLPieces request =- let url = request & Servant._reqUrl- path =- url & Servant._path & map Servant.unSegment &- Maybe.mapMaybe- (\segment ->- case segment of- Servant.Static _ -> Nothing- Servant.Cap arg -> Just arg) &- map Servant._argName &- map Servant.unPathSegment- query =- url & Servant._queryStr & map Servant._queryArgName &- map Servant._argName &- map Servant.unPathSegment- in map Left path ++ map Right query--functionArguments :: Servant.Req Request -> Text.Text-functionArguments request =- Text.concat- [ "("- , [ [Just "excon"]- , request & getURLPieces &- map- (\piece ->- case piece of- Left capture -> underscore capture- Right param -> underscore param <> ": nil") &- map Just- , request & getHeaders & map underscore & map (<> ": nil") & map Just- , [ if hasBody request- then Just bodyArgument- else Nothing- ]- ] &- concat &- Maybe.catMaybes &- Text.intercalate ","- , ")"- ]--requestMethod :: Servant.Req Request -> Text.Text-requestMethod request =- request & Servant._reqMethod & Text.decodeUtf8 & Text.toLower & Text.cons ':'--requestPath :: Servant.Req Request -> Text.Text-requestPath request =- let path =- request & Servant._reqUrl & Servant._path & map Servant.unSegment &- map- (\x ->- case x of- Servant.Static y -> Servant.unPathSegment y- Servant.Cap y ->- let z =- y & Servant._argName & Servant.unPathSegment & underscore- in "#{" <> z <> "}") &- Text.intercalate "/"- query =- request & Servant._reqUrl & Servant._queryStr &- map Servant._queryArgName &- map Servant._argName &- map Servant.unPathSegment &- map (\x -> x <> "=#{" <> underscore x <> "}") &- Text.intercalate "&"- url =- "/" <> path <>- (if Text.null query- then ""- else "?" <> query)- in "\"" <> url <> "\""--requestHeaders :: Servant.Req Request -> Text.Text-requestHeaders request =- [ ["{"]- , request & getHeaders & map (\x -> "\"" <> x <> "\"=>" <> underscore x)- , ["}"]- ] &- concat &- Text.concat--requestBody :: Servant.Req Request -> Text.Text-requestBody request =- if hasBody request- then bodyArgument- else "nil"--functionBody :: Servant.Req Request -> Text.Text-functionBody request =- Text.concat- [ "excon.request("- , ":method=>"- , requestMethod request- , ","- , ":path=>"- , requestPath request- , ","- , ":headers=>"- , requestHeaders request- , ","- , ":body=>"- , requestBody request- , ")"- ]--renderRequest :: Servant.Req Request -> Text.Text-renderRequest request =- Text.concat- [ "def "- , functionName request- , functionArguments request- , functionBody request- , "end"- ]--requestsForAPI ::- ( Servant.HasForeign Language Request api- , Servant.GenerateList Request (Servant.Foreign Request api)- )- => Proxy.Proxy api- -> [Servant.Req Request]-requestsForAPI api = api & Servant.listFromAPI languageProxy requestProxy--rubyForAPI ::- ( Servant.HasForeign Language Request api- , Servant.GenerateList Request (Servant.Foreign Request api)- )- => Proxy.Proxy api- -> Text.Text-rubyForAPI api = api & requestsForAPI & renderRequests
− src/test/Main.hs
@@ -1,133 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}--import qualified Data.Proxy as Proxy-import qualified Data.Text as Text-import qualified Lackey-import qualified Servant.API as Servant-import qualified Test.Hspec as Hspec--main :: IO ()-main = Hspec.hspec . Hspec.parallel . Hspec.describe "Lackey" . Hspec.describe "rubyForAPI" $ do-- Hspec.it "supports delete requests" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Delete '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "delete" "" "delete" "" "" False-- Hspec.it "supports get requests" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" "" "get" "" "" False-- Hspec.it "supports patch requests" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Patch '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "patch" "" "patch" "" "" False-- Hspec.it "supports post requests" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Post '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "post" "" "post" "" "" False-- Hspec.it "supports put requests" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Put '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "put" "" "put" "" "" False-- Hspec.it "supports alternatives" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] () Servant.:<|> Servant.Delete '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe` Text.concat- [ ruby "get" "" "get" "" "" False- , Text.singleton ';'- , ruby "delete" "" "delete" "" "" False- ]-- Hspec.it "supports captures" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Capture "id" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get_by_id" ",id" "get" "#{id}" "" False-- Hspec.it "supports query flags" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryFlag "flag" Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",flag: nil" "get" "?flag=#{flag}" "" False-- Hspec.it "supports query params" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParam "param" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",param: nil" "get" "?param=#{param}" "" False-- Hspec.it "supports multiple query params" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParams "params" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",params: nil" "get" "?params=#{params}" "" False-- Hspec.it "supports request bodies" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",body" "get" "" "" True-- Hspec.it "supports request headers" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Header "cookie" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",cookie: nil" "get" "" "\"cookie\"=>cookie" False-- Hspec.it "supports response headers" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Get '[Servant.JSON] (Servant.Headers '[] ()))- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" "" "get" "" "" False-- Hspec.it "puts the body param after captures" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Capture "segment" () Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get_by_segment" ",segment,body" "get" "#{segment}" "" True-- Hspec.it "puts the body param after query params" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryFlag "flag" Servant.:> Servant.ReqBody '[Servant.JSON] () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",flag: nil,body" "get" "?flag=#{flag}" "" True-- Hspec.it "sanitizes path segments" $ do- let api = Proxy.Proxy :: Proxy.Proxy ("A!" Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get_A!" "" "get" "A!" "" False-- Hspec.it "sanitizes captures" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Capture "A!" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get_by_A!" ",a_" "get" "#{a_}" "" False-- Hspec.it "sanitizes query flags" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryFlag "A!" Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False-- Hspec.it "sanitizes query params" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParam "A!" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False-- Hspec.it "sanitizes multiple query params" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.QueryParams "A!" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False-- Hspec.it "sanitizes headers" $ do- let api = Proxy.Proxy :: Proxy.Proxy (Servant.Header "A!" () Servant.:> Servant.Get '[Servant.JSON] ())- Lackey.rubyForAPI api `Hspec.shouldBe`- ruby "get" ",a_: nil" "get" "" "\"A!\"=>a_" False---- Since every generated function has the same structure, it can be abstracted--- away behind this function.-ruby :: String -> String -> String -> String -> String -> Bool -> Text.Text-ruby name params method path headers body = Text.pack (concat- [ "def ", name, "(excon", params, ")"- , "excon.request("- , ":method=>:", method, ","- , ":path=>\"/", path, "\","- , ":headers=>{", headers, "},"- , ":body=>", if body then "body" else "nil"- , ")"- , "end"- ])