packages feed

lackey 2.0.0.3 → 2.0.0.4

raw patch · 5 files changed

+296/−297 lines, 5 filesdep ~basedep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, text

API changes (from Hackage documentation)

Files

LICENSE.markdown view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Taylor Fausak+Copyright (c) 2023 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
README.markdown view
@@ -1,6 +1,6 @@ # [Lackey][] -[![CI](https://github.com/tfausak/lackey/workflows/CI/badge.svg)](https://github.com/tfausak/lackey/actions/new)+[![Workflow](https://github.com/tfausak/lackey/actions/workflows/workflow.yaml/badge.svg)](https://github.com/tfausak/lackey/actions/workflows/workflow.yaml) [![Hackage](https://img.shields.io/hackage/v/lackey)](https://hackage.haskell.org/package/lackey) [![Stackage](https://www.stackage.org/package/lackey/badge/nightly?label=stackage)](https://www.stackage.org/package/lackey) 
lackey.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2  name: lackey-version: 2.0.0.3+version: 2.0.0.4  synopsis: Generate Ruby clients from Servant APIs. description: Lackey generates Ruby clients from Servant APIs.@@ -26,29 +26,26 @@  common library   build-depends:-    , base >= 4.13.0 && < 4.18+    , base >= 4.15.0 && < 4.18     , servant-foreign >= 0.15 && < 0.16-    , text >= 1.2.4 && < 1.3 || >= 2.0 && < 2.1+    , text >= 1.2.5 && < 1.3 || >= 2.0 && < 2.1   default-language: Haskell2010   ghc-options:     -Weverything     -Wno-all-missed-specialisations     -Wno-implicit-prelude     -Wno-missing-exported-signatures+    -Wno-missing-safe-haskell-mode+    -Wno-prepositive-qualified-module     -Wno-unsafe -  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 +  if flag(pedantic)+    ghc-options: -Werror+ common executable   import: library @@ -64,7 +61,7 @@   exposed-modules: Lackey   hs-source-dirs: source/library -test-suite test+test-suite lackey-test-suite   import: executable    build-depends:
source/library/Lackey.hs view
@@ -2,8 +2,9 @@ {-# LANGUAGE OverloadedStrings #-}  module Lackey-  ( rubyForAPI-  ) where+  ( rubyForAPI,+  )+where  import qualified Data.Char as Char import Data.Function ((&))@@ -46,48 +47,53 @@   request     & Servant._reqHeaders     & Maybe.mapMaybe-        (\h -> case h of+      ( \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+  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+          & 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]+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 ",",+      ")"     ]-  & concat-  & Maybe.catMaybes-  & Text.intercalate ","-  , ")"-  ]  requestMethod :: Servant.Req Request -> Text.Text requestMethod request =@@ -95,43 +101,41 @@  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+  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 "/"+      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 <> "\""+          & 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)-    , ["}"]-    ]+  [ ["{"],+    request & getHeaders & fmap (\x -> "\"" <> x <> "\"=>" <> underscore x),+    ["}"]+  ]     & concat     & Text.concat @@ -139,43 +143,45 @@ 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-  , ")"-  ]+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"-  ]+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 ::+  ( 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 ::+  ( 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
@@ -14,243 +14,239 @@     . Hspec.describe "Lackey"     . Hspec.describe "rubyForAPI"     $ do--        Hspec.it "supports delete requests" $ do-          let-            api =+      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+        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 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 =+      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+        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 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 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+      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+        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+      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+        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+      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+        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+      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+        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+      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+        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+      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+        Lackey.rubyForAPI api+          `Hspec.shouldBe` ruby "get" ",body" "get" "" "" True -        Hspec.it "supports request headers" $ do-          let-            api =-              Proxy.Proxy :: Proxy.Proxy+      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+        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+      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+        Lackey.rubyForAPI api+          `Hspec.shouldBe` ruby "get" "" "get" "" "" False -        Hspec.it "puts the body param after captures" $ do-          let-            api =-              Proxy.Proxy :: Proxy.Proxy+      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+        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+      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+        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+      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+        Lackey.rubyForAPI api+          `Hspec.shouldBe` ruby "get_A!" "" "get" "A!" "" False -        Hspec.it "sanitizes captures" $ do-          let-            api =-              Proxy.Proxy :: Proxy.Proxy+      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+        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+      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+        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+      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+        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+      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+        Lackey.rubyForAPI api+          `Hspec.shouldBe` ruby "get" ",a_: nil" "get" "?A!=#{a_}" "" False -        Hspec.it "sanitizes headers" $ do-          let-            api =-              Proxy.Proxy :: Proxy.Proxy+      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+        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"-    ]-  )+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"+        ]+    )