-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Helpers for generating clients for servant APIs in any programming language -- -- Helper types and functions for generating client functions for servant -- APIs in any programming language -- -- This package provides types and functions that collect all the data -- needed to generate client functions in the programming language of -- your choice. This effectively means you only have to write the code -- that "pretty-prints" this data as some code in your target language. -- -- See the servant-js package for an example -- -- CHANGELOG @package servant-foreign @version 0.7 -- | Generalizes all the data needed to make code generation work with -- arbitrary programming languages. module Servant.Foreign.Internal newtype FunctionName FunctionName :: [Text] -> FunctionName [unFunctionName] :: FunctionName -> [Text] _FunctionName :: Iso' FunctionName [Text] newtype PathSegment PathSegment :: Text -> PathSegment [unPathSegment] :: PathSegment -> Text _PathSegment :: Iso' PathSegment Text data Arg f Arg :: PathSegment -> f -> Arg f [_argName] :: Arg f -> PathSegment [_argType] :: Arg f -> f argType :: Lens (Arg f_ahe6) (Arg f_ahhu) f_ahe6 f_ahhu argName :: Lens' (Arg f_ahe6) PathSegment argPath :: Getter (Arg f) Text data SegmentType f -- | a static path segment. like "/foo" Static :: PathSegment -> SegmentType f -- | a capture. like "/:userid" Cap :: (Arg f) -> SegmentType f _Cap :: Prism (SegmentType f_ahlF) (SegmentType f_ahhJ) (Arg f_ahlF) (Arg f_ahhJ) _Static :: Prism' (SegmentType f_ahhJ) PathSegment newtype Segment f Segment :: SegmentType f -> Segment f [unSegment] :: Segment f -> SegmentType f _Segment :: Iso (Segment f_ahs3) (Segment f_ahlP) (SegmentType f_ahs3) (SegmentType f_ahlP) isCapture :: Segment f -> Bool captureArg :: Segment f -> Arg f type Path f = [Segment f] data ArgType Normal :: ArgType Flag :: ArgType List :: ArgType _List :: Prism' ArgType () _Flag :: Prism' ArgType () _Normal :: Prism' ArgType () data QueryArg f QueryArg :: Arg f -> ArgType -> QueryArg f [_queryArgName] :: QueryArg f -> Arg f [_queryArgType] :: QueryArg f -> ArgType queryArgType :: Lens' (QueryArg f_ahul) ArgType queryArgName :: Lens (QueryArg f_ahul) (QueryArg f_ahyh) (Arg f_ahul) (Arg f_ahyh) data HeaderArg f HeaderArg :: Arg f -> HeaderArg f [_headerArg] :: HeaderArg f -> Arg f ReplaceHeaderArg :: Arg f -> Text -> HeaderArg f [_headerArg] :: HeaderArg f -> Arg f [_headerPattern] :: HeaderArg f -> Text headerPattern :: Traversal' (HeaderArg f_ahyx) Text headerArg :: Lens (HeaderArg f_ahyx) (HeaderArg f_ahCf) (Arg f_ahyx) (Arg f_ahCf) _ReplaceHeaderArg :: Prism' (HeaderArg f_ahyx) (Arg f_ahyx, Text) _HeaderArg :: Prism' (HeaderArg f_ahyx) (Arg f_ahyx) data Url f Url :: Path f -> [QueryArg f] -> Url f [_path] :: Url f -> Path f [_queryStr] :: Url f -> [QueryArg f] defUrl :: Url f queryStr :: Lens' (Url f_ahE8) [QueryArg f_ahE8] path :: Lens' (Url f_ahE8) (Path f_ahE8) data Req f Req :: Url f -> Method -> [HeaderArg f] -> Maybe f -> Maybe f -> FunctionName -> Req f [_reqUrl] :: Req f -> Url f [_reqMethod] :: Req f -> Method [_reqHeaders] :: Req f -> [HeaderArg f] [_reqBody] :: Req f -> Maybe f [_reqReturnType] :: Req f -> Maybe f [_reqFuncName] :: Req f -> FunctionName reqUrl :: Lens' (Req f_ahId) (Url f_ahId) reqReturnType :: Lens' (Req f_ahId) (Maybe f_ahId) reqMethod :: Lens' (Req f_ahId) Method reqHeaders :: Lens' (Req f_ahId) [HeaderArg f_ahId] reqFuncName :: Lens' (Req f_ahId) FunctionName reqBody :: Lens' (Req f_ahId) (Maybe f_ahId) defReq :: Req ftype -- | To be used exclusively as a "negative" return type/constraint by -- Elem type family. class NotFound -- | HasForeignType maps Haskell types with types in the target -- language of your backend. For example, let's say you're implementing a -- backend to some language X, and you want a Text representation -- of each input/output type mentioned in the API: -- --
-- -- First you need to create a dummy type to parametrize your -- -- instances. -- data LangX -- -- -- Otherwise you define instances for the types you need -- instance HasForeignType LangX Text Int where -- typeFor _ _ _ = "intX" -- -- -- Or for example in case of lists -- instance HasForeignType LangX Text a => HasForeignType LangX Text [a] where -- typeFor lang type _ = "listX of " <> typeFor lang ftype (Proxy :: Proxy a) ---- -- Finally to generate list of information about all the endpoints for an -- API you create a function of a form: -- --
-- getEndpoints :: (HasForeign LangX Text api, GenerateList Text (Foreign Text api)) -- => Proxy api -> [Req Text] -- getEndpoints api = listFromAPI (Proxy :: Proxy LangX) (Proxy :: Proxy Text) api ---- --
-- -- If language __X__ is dynamically typed then you can use -- -- a predefined NoTypes parameter with the () output type: ---- --
-- getEndpoints :: (HasForeign NoTypes () api, GenerateList Text (Foreign () api)) -- => Proxy api -> [Req ()] -- getEndpoints api = listFromAPI (Proxy :: Proxy NoTypes) (Proxy :: Proxy ()) api --class HasForeignType lang ftype a typeFor :: HasForeignType lang ftype a => Proxy lang -> Proxy ftype -> Proxy a -> ftype data NoTypes class HasForeign lang ftype (layout :: *) where type family Foreign ftype layout :: * foreignFor :: HasForeign lang ftype layout => Proxy lang -> Proxy ftype -> Proxy layout -> Req ftype -> Foreign ftype layout -- | Utility class used by listFromAPI which computes the data -- needed to generate a function for each endpoint and hands it all back -- in a list. class GenerateList ftype reqs generateList :: GenerateList ftype reqs => reqs -> [Req ftype] -- | Generate the necessary data for codegen as a list, each Req -- describing one endpoint from your API type. listFromAPI :: (HasForeign lang ftype api, GenerateList ftype (Foreign ftype api)) => Proxy lang -> Proxy ftype -> Proxy api -> [Req ftype] instance forall (k :: BOX) (ftype :: k). Servant.Foreign.Internal.HasForeignType Servant.Foreign.Internal.NoTypes () ftype instance forall (k :: BOX) (lang :: k) ftype a b. (Servant.Foreign.Internal.HasForeign lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype b) => Servant.Foreign.Internal.HasForeign lang ftype (a Servant.API.Alternative.:<|> b) instance forall (k :: BOX) (k1 :: BOX) (lang :: k) ftype (sym :: GHC.TypeLits.Symbol) (t :: k1) sublayout. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype t, Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.Capture.Capture sym t Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (k1 :: BOX) (k2 :: BOX) (lang :: k) ftype (method :: k1) (status :: GHC.TypeLits.Nat) (list :: [*]) (a :: k2). (Servant.Foreign.Internal.Elem Servant.API.ContentTypes.JSON list, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.API.Verbs.ReflectMethod method) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.Verbs.Verb method status list a) instance forall (k :: BOX) (lang :: k) ftype (sym :: GHC.TypeLits.Symbol) a sublayout. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.Header.Header sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (k1 :: BOX) (lang :: k) ftype (sym :: GHC.TypeLits.Symbol) (a :: k1) sublayout. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.QueryParam.QueryParam sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype (sym :: GHC.TypeLits.Symbol) a sublayout. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype [a], Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.QueryParam.QueryParams sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype (sym :: GHC.TypeLits.Symbol) sublayout. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype GHC.Types.Bool, Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.QueryParam.QueryFlag sym Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype. Servant.Foreign.Internal.HasForeign lang ftype Servant.API.Raw.Raw instance forall (k :: BOX) (k1 :: BOX) (lang :: k) ftype (list :: [*]) (a :: k1) sublayout. (Servant.Foreign.Internal.Elem Servant.API.ContentTypes.JSON list, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.ReqBody.ReqBody list a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype (path :: GHC.TypeLits.Symbol) sublayout. (GHC.TypeLits.KnownSymbol path, Servant.Foreign.Internal.HasForeign lang ftype sublayout) => Servant.Foreign.Internal.HasForeign lang ftype (path Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype sublayout. Servant.Foreign.Internal.HasForeign lang ftype sublayout => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.RemoteHost.RemoteHost Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype sublayout. Servant.Foreign.Internal.HasForeign lang ftype sublayout => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.IsSecure.IsSecure Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype sublayout. Servant.Foreign.Internal.HasForeign lang ftype sublayout => Servant.Foreign.Internal.HasForeign lang ftype (Data.Vault.Lazy.Vault Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (lang :: k) ftype (name :: GHC.TypeLits.Symbol) (context :: [*]) sublayout. Servant.Foreign.Internal.HasForeign lang ftype sublayout => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.WithNamedContext.WithNamedContext name context sublayout) instance forall (k :: BOX) (lang :: k) ftype sublayout. Servant.Foreign.Internal.HasForeign lang ftype sublayout => Servant.Foreign.Internal.HasForeign lang ftype (Network.HTTP.Types.Version.HttpVersion Servant.API.Sub.:> sublayout) instance Servant.Foreign.Internal.GenerateList ftype (Servant.Foreign.Internal.Req ftype) instance (Servant.Foreign.Internal.GenerateList ftype start, Servant.Foreign.Internal.GenerateList ftype rest) => Servant.Foreign.Internal.GenerateList ftype (start Servant.API.Alternative.:<|> rest) instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.Req f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.Req f) instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.Url f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.Url f) instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.HeaderArg f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.HeaderArg f) instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.QueryArg f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.QueryArg f) instance GHC.Show.Show Servant.Foreign.Internal.ArgType instance GHC.Classes.Eq Servant.Foreign.Internal.ArgType instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.Segment f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.Segment f) instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.SegmentType f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.SegmentType f) instance GHC.Classes.Eq f => GHC.Classes.Eq (Servant.Foreign.Internal.Arg f) instance GHC.Show.Show f => GHC.Show.Show (Servant.Foreign.Internal.Arg f) instance GHC.Base.Monoid Servant.Foreign.Internal.PathSegment instance Data.String.IsString Servant.Foreign.Internal.PathSegment instance GHC.Classes.Eq Servant.Foreign.Internal.PathSegment instance GHC.Show.Show Servant.Foreign.Internal.PathSegment instance GHC.Base.Monoid Servant.Foreign.Internal.FunctionName instance GHC.Classes.Eq Servant.Foreign.Internal.FunctionName instance GHC.Show.Show Servant.Foreign.Internal.FunctionName module Servant.Foreign.Inflections -- | Function name builder that simply concat each part together concatCase :: FunctionName -> Text -- | Function name builder using the snake_case convention. each part is -- separated by a single underscore character. snakeCase :: FunctionName -> Text -- | Function name builder using the CamelCase convention. each part begins -- with an upper case character. camelCase :: FunctionName -> Text concatCaseL :: Getter FunctionName Text snakeCaseL :: Getter FunctionName Text camelCaseL :: Getter FunctionName Text -- | Generalizes all the data needed to make code generation work with -- arbitrary programming languages. module Servant.Foreign data ArgType Normal :: ArgType Flag :: ArgType List :: ArgType data HeaderArg f HeaderArg :: Arg f -> HeaderArg f [_headerArg] :: HeaderArg f -> Arg f ReplaceHeaderArg :: Arg f -> Text -> HeaderArg f [_headerArg] :: HeaderArg f -> Arg f [_headerPattern] :: HeaderArg f -> Text data QueryArg f QueryArg :: Arg f -> ArgType -> QueryArg f [_queryArgName] :: QueryArg f -> Arg f [_queryArgType] :: QueryArg f -> ArgType data Req f Req :: Url f -> Method -> [HeaderArg f] -> Maybe f -> Maybe f -> FunctionName -> Req f [_reqUrl] :: Req f -> Url f [_reqMethod] :: Req f -> Method [_reqHeaders] :: Req f -> [HeaderArg f] [_reqBody] :: Req f -> Maybe f [_reqReturnType] :: Req f -> Maybe f [_reqFuncName] :: Req f -> FunctionName newtype Segment f Segment :: SegmentType f -> Segment f [unSegment] :: Segment f -> SegmentType f data SegmentType f -- | a static path segment. like "/foo" Static :: PathSegment -> SegmentType f -- | a capture. like "/:userid" Cap :: (Arg f) -> SegmentType f data Url f Url :: Path f -> [QueryArg f] -> Url f [_path] :: Url f -> Path f [_queryStr] :: Url f -> [QueryArg f] type Path f = [Segment f] data Arg f Arg :: PathSegment -> f -> Arg f [_argName] :: Arg f -> PathSegment [_argType] :: Arg f -> f newtype FunctionName FunctionName :: [Text] -> FunctionName [unFunctionName] :: FunctionName -> [Text] newtype PathSegment PathSegment :: Text -> PathSegment [unPathSegment] :: PathSegment -> Text argName :: Lens' (Arg f_ahe6) PathSegment argType :: Lens (Arg f_ahe6) (Arg f_ahhu) f_ahe6 f_ahhu argPath :: Getter (Arg f) Text reqUrl :: Lens' (Req f_ahId) (Url f_ahId) reqMethod :: Lens' (Req f_ahId) Method reqHeaders :: Lens' (Req f_ahId) [HeaderArg f_ahId] reqBody :: Lens' (Req f_ahId) (Maybe f_ahId) reqReturnType :: Lens' (Req f_ahId) (Maybe f_ahId) reqFuncName :: Lens' (Req f_ahId) FunctionName path :: Lens' (Url f_ahE8) (Path f_ahE8) queryStr :: Lens' (Url f_ahE8) [QueryArg f_ahE8] queryArgName :: Lens (QueryArg f_ahul) (QueryArg f_ahyh) (Arg f_ahul) (Arg f_ahyh) queryArgType :: Lens' (QueryArg f_ahul) ArgType headerArg :: Lens (HeaderArg f_ahyx) (HeaderArg f_ahCf) (Arg f_ahyx) (Arg f_ahCf) _PathSegment :: Iso' PathSegment Text _HeaderArg :: Prism' (HeaderArg f_ahyx) (Arg f_ahyx) _ReplaceHeaderArg :: Prism' (HeaderArg f_ahyx) (Arg f_ahyx, Text) _Static :: Prism' (SegmentType f_ahhJ) PathSegment _Cap :: Prism (SegmentType f_ahlF) (SegmentType f_ahhJ) (Arg f_ahlF) (Arg f_ahhJ) _Normal :: Prism' ArgType () _Flag :: Prism' ArgType () _List :: Prism' ArgType () class HasForeign lang ftype (layout :: *) where type family Foreign ftype layout :: * foreignFor :: HasForeign lang ftype layout => Proxy lang -> Proxy ftype -> Proxy layout -> Req ftype -> Foreign ftype layout -- | HasForeignType maps Haskell types with types in the target -- language of your backend. For example, let's say you're implementing a -- backend to some language X, and you want a Text representation -- of each input/output type mentioned in the API: -- --
-- -- First you need to create a dummy type to parametrize your -- -- instances. -- data LangX -- -- -- Otherwise you define instances for the types you need -- instance HasForeignType LangX Text Int where -- typeFor _ _ _ = "intX" -- -- -- Or for example in case of lists -- instance HasForeignType LangX Text a => HasForeignType LangX Text [a] where -- typeFor lang type _ = "listX of " <> typeFor lang ftype (Proxy :: Proxy a) ---- -- Finally to generate list of information about all the endpoints for an -- API you create a function of a form: -- --
-- getEndpoints :: (HasForeign LangX Text api, GenerateList Text (Foreign Text api)) -- => Proxy api -> [Req Text] -- getEndpoints api = listFromAPI (Proxy :: Proxy LangX) (Proxy :: Proxy Text) api ---- --
-- -- If language __X__ is dynamically typed then you can use -- -- a predefined NoTypes parameter with the () output type: ---- --
-- getEndpoints :: (HasForeign NoTypes () api, GenerateList Text (Foreign () api)) -- => Proxy api -> [Req ()] -- getEndpoints api = listFromAPI (Proxy :: Proxy NoTypes) (Proxy :: Proxy ()) api --class HasForeignType lang ftype a typeFor :: HasForeignType lang ftype a => Proxy lang -> Proxy ftype -> Proxy a -> ftype -- | Utility class used by listFromAPI which computes the data -- needed to generate a function for each endpoint and hands it all back -- in a list. class GenerateList ftype reqs generateList :: GenerateList ftype reqs => reqs -> [Req ftype] data NoTypes captureArg :: Segment f -> Arg f isCapture :: Segment f -> Bool defReq :: Req ftype -- | Generate the necessary data for codegen as a list, each Req -- describing one endpoint from your API type. listFromAPI :: (HasForeign lang ftype api, GenerateList ftype (Foreign ftype api)) => Proxy lang -> Proxy ftype -> Proxy api -> [Req ftype]