@@ -1,3 +1,4 @@
1{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
@@ -19,8 +20,11 @@ import Elm.Json (jsonParserForType, jsonSerForType)
19import qualified Elm.Module as Elm
20import qualified Elm.Module as Elm
20import Elm.TyRep (ETCon(..), EType(..), ETypeDef(..), toElmType)
21import Elm.TyRep (ETCon(..), EType(..), ETypeDef(..), toElmType)
21import Elm.TyRender (renderElm)
22import Elm.TyRender (renderElm)
23+#if MIN_VERSION_elm_bridge(0,6,0)
24+import Elm.Versions (ElmVersion(Elm0p19))
22import Elm.Versions (ElmVersion(Elm0p18))
26import Elm.Versions (ElmVersion(Elm0p18))
24import Servant.Elm.Internal.Foreign (LangElm, getEndpoints)
28import Servant.Elm.Internal.Foreign (LangElm, getEndpoints)
25import qualified Servant.Foreign as F
29import qualified Servant.Foreign as F
26import System.Directory (createDirectoryIfMissing)
30import System.Directory (createDirectoryIfMissing)
@@ -49,16 +53,22 @@ data ElmOptions = ElmOptions
51 urlPrefix :: UrlPrefix
55 urlPrefix :: UrlPrefix
52− , elmTypeAlterations :: (EType -> EType)
56+ , elmTypeAlterations :: (EType -> EType)
53 -- ^ Alterations to perform on ETypes before code generation.
57 -- ^ Alterations to perform on ETypes before code generation.
54 , elmAlterations :: (ETypeDef -> ETypeDef)
58 , elmAlterations :: (ETypeDef -> ETypeDef)
55 -- ^ Alterations to perform on ETypeDefs before code generation.
59 -- ^ Alterations to perform on ETypeDefs before code generation.
56− , elmToString :: (EType -> Text)
60+ , elmToString :: (EType -> Text)
57 -- ^ Elm functions creating a string from a given type.
61 -- ^ Elm functions creating a string from a given type.
58 , emptyResponseElmTypes :: [EType]
62 , emptyResponseElmTypes :: [EType]
59 -- ^ Types that represent an empty Http response.
63 -- ^ Types that represent an empty Http response.
60 , stringElmTypes :: [EType]
64 , stringElmTypes :: [EType]
61 -- ^ Types that represent a String.
65 -- ^ Types that represent a String.
66+ , expectJsonMethod :: Text
67+ -- ^ The function to use for JSON responses.
68+ , expectStringMethod :: Text
69+ -- ^ The function to use for string responses.
70+ , httpErrorType :: Text
71+ -- ^ The type to use for Http errors.
@@ -82,6 +92,9 @@ The default options are:
82> , stringElmTypes =
92> , stringElmTypes =
83> [ getType (Proxy :: Proxy String)
93> [ getType (Proxy :: Proxy String)
84> , getType (Proxy :: Proxy T.Text) ]
94> , getType (Proxy :: Proxy T.Text) ]
95+> , expectJsonMethod = "Http.expectJson"
96+> , expectStringMethod = "Http.expectString"
97+> , httpErrorType = "Http.Error"
87defElmOptions :: ElmOptions
100defElmOptions :: ElmOptions
@@ -97,6 +110,9 @@ defElmOptions = ElmOptions
97 [ toElmType (Proxy :: Proxy String)
110 [ toElmType (Proxy :: Proxy String)
98 , toElmType (Proxy :: Proxy T.Text)
111 , toElmType (Proxy :: Proxy T.Text)
113+ , expectJsonMethod = "Http.expectJson"
114+ , expectStringMethod = "Http.expectString"
115+ , httpErrorType = "Http.Error"
@@ -115,6 +131,7 @@ The default required imports are:
115> import Set
131> import Set
116> import Http
132> import Http
117> import String
133> import String
118> import Url.Builder
135> import Url.Builder
120defElmImports :: Text
137defElmImports :: Text
@@ -128,6 +145,7 @@ defElmImports =
128 , "import Set"
145 , "import Set"
129 , "import Http"
146 , "import Http"
130 , "import String"
147 , "import String"
131 , "import Url.Builder"
149 , "import Url.Builder"
@@ -149,7 +167,12 @@ generateElmModuleWith ::
149generateElmModuleWith options namespace imports rootDir typeDefs api = do
167generateElmModuleWith options namespace imports rootDir typeDefs api = do
150 let out =
168 let out =
151 T.unlines $
169 T.unlines $
171+#if MIN_VERSION_elm_bridge(0,6,0)
172+ T.pack $ Elm.moduleHeader Elm0p19 moduleName
152− [ T.pack $ Elm.moduleHeader Elm0p18 moduleName
174+ T.pack $ Elm.moduleHeader Elm0p18 moduleName
154 , imports
177 , imports
155 , T.pack $ Elm.makeModuleContentWithAlterations (elmAlterations options) typeDefs
178 , T.pack $ Elm.makeModuleContentWithAlterations (elmAlterations options) typeDefs
@@ -236,7 +259,7 @@ generateElmForRequest opts request =
237 request ^. F.reqFuncName . to (replace . F.camelCase) . to stext
260 request ^. F.reqFuncName . to (replace . F.camelCase) . to stext
239− replace = T.replace "-" "" . T.replace "." ""
262+ replace = T.replace "-" "" . T.replace "." "" . T.replace " " ""
241 typeSignature =
264 typeSignature =
242 mkTypeSignature opts request
265 mkTypeSignature opts request
@@ -298,7 +321,7 @@ mkTypeSignature opts request =
298 toMsgType :: Maybe Doc
321 toMsgType :: Maybe Doc
299 toMsgType = do
322 toMsgType = do
300 result <- fmap elmTypeRef $ request ^. F.reqReturnType
323 result <- fmap elmTypeRef $ request ^. F.reqReturnType
301− Just ("(Result Http.Error " <+> parens result <+> " -> msg)")
324+ Just ("(Result" <+> stext (httpErrorType opts) <+> parens result <+> "-> msg)")
303 returnType :: Maybe Doc
326 returnType :: Maybe Doc
304 returnType = do
327 returnType = do
@@ -316,7 +339,7 @@ elmCaptureArg segment =
316 "capture_" <>
339 "capture_" <>
317 F.captureArg segment ^. F.argName . to (stext . replace . F.unPathSegment)
340 F.captureArg segment ^. F.argName . to (stext . replace . F.unPathSegment)
319− replace = T.replace "-" "_"
342+ replace = T.replace "-" "_" . T.replace " " "_"
322elmQueryArg :: F.QueryArg EType -> Doc
345elmQueryArg :: F.QueryArg EType -> Doc
@@ -487,14 +510,14 @@ mkRequest opts request =
488 case request ^. F.reqReturnType of
511 case request ^. F.reqReturnType of
489 Just elmTypeExpr
512 Just elmTypeExpr
490− | isEmptyType opts elmTypeExpr
513+ | isEmptyType opts $ (elmTypeAlterations opts) elmTypeExpr
491 -- let elmConstructor = T.pack (renderElm elmTypeExpr)
514 -- let elmConstructor = T.pack (renderElm elmTypeExpr)
493− "Http.expectString " <> line <+> indent i "(\\x -> case x of" <> line <+>
516+ stext (expectStringMethod opts) <> line <+> indent i "(\\x -> case x of" <> line <+>
494 indent i "Err e -> toMsg (Err e)" <> line <+>
517 indent i "Err e -> toMsg (Err e)" <> line <+>
495 indent i "Ok _ -> toMsg (Ok ()))"
518 indent i "Ok _ -> toMsg (Ok ()))"
496 Just elmTypeExpr ->
519 Just elmTypeExpr ->
497− "Http.expectJson toMsg" <+> renderDecoderName elmTypeExpr
520+ stext (expectJsonMethod opts) <+> "toMsg" <+> renderDecoderName ((elmTypeAlterations opts) elmTypeExpr)
498 Nothing -> error "mkHttpRequest: no reqReturnType?"
521 Nothing -> error "mkHttpRequest: no reqReturnType?"
499 -- case request ^. F.reqReturnType of
522 -- case request ^. F.reqReturnType of
500 -- Just elmTypeExpr | isEmptyType opts elmTypeExpr ->
523 -- Just elmTypeExpr | isEmptyType opts elmTypeExpr ->
@@ -552,9 +575,9 @@ mkUrl opts segments =
552 F.Cap arg ->
575 F.Cap arg ->
554 toStringSrc =
577 toStringSrc =
555− toString opts (maybeOf (arg ^. F.argType))
578+ toString opts (elmTypeAlterations opts (maybeOf (arg ^. F.argType)))
557− pipeRight [elmCaptureArg s, toStringSrc]
580+ "Url.percentEncode " <> pipeRight [elmCaptureArg s, toStringSrc]
560mkQueryParams
583mkQueryParams
@@ -572,7 +595,7 @@ response body.
573isEmptyType :: ElmOptions -> EType -> Bool
596isEmptyType :: ElmOptions -> EType -> Bool
574isEmptyType opts elmTypeExpr =
597isEmptyType opts elmTypeExpr =
575− elmTypeExpr `elem` emptyResponseElmTypes opts
598+ (elmTypeAlterations opts elmTypeExpr) `elem` emptyResponseElmTypes opts
578{- | Determines whether we call `toString` on URL captures and query params of
601{- | Determines whether we call `toString` on URL captures and query params of
@@ -580,7 +603,7 @@ this type in Elm.
581isElmStringType :: ElmOptions -> EType -> Bool
604isElmStringType :: ElmOptions -> EType -> Bool
582isElmStringType opts elmTypeExpr =
605isElmStringType opts elmTypeExpr =
583− elmTypeExpr `elem` stringElmTypes opts
606+ (elmTypeAlterations opts elmTypeExpr) `elem` stringElmTypes opts
585{- | Determines whether a type is 'Maybe a' where 'a' is something akin to a 'String'.
608{- | Determines whether a type is 'Maybe a' where 'a' is something akin to a 'String'.