-- 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.8 -- | 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 :: forall f_ajje f_ajms. Lens (Arg f_ajje) (Arg f_ajms) f_ajje f_ajms argName :: forall f_ajje. Lens' (Arg f_ajje) 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 :: forall f_ajmH f_ajqk. Prism (SegmentType f_ajqk) (SegmentType f_ajmH) (Arg f_ajqk) (Arg f_ajmH) _Static :: forall f_ajmH. Prism' (SegmentType f_ajmH) PathSegment newtype Segment f Segment :: SegmentType f -> Segment f [unSegment] :: Segment f -> SegmentType f _Segment :: forall f_ajqu f_ajx2. Iso (Segment f_ajx2) (Segment f_ajqu) (SegmentType f_ajx2) (SegmentType f_ajqu) 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 :: forall f_ajB3. Lens' (QueryArg f_ajB3) ArgType queryArgName :: forall f_ajB3 f_ajEL. Lens (QueryArg f_ajB3) (QueryArg f_ajEL) (Arg f_ajB3) (Arg f_ajEL) 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 :: forall f_ajF1. Traversal' (HeaderArg f_ajF1) Text headerArg :: forall f_ajF1 f_ajIk. Lens (HeaderArg f_ajF1) (HeaderArg f_ajIk) (Arg f_ajF1) (Arg f_ajIk) _ReplaceHeaderArg :: forall f_ajF1. Prism' (HeaderArg f_ajF1) (Arg f_ajF1, Text) _HeaderArg :: forall f_ajF1. Prism' (HeaderArg f_ajF1) (Arg f_ajF1) data Url f Url :: Path f -> [QueryArg f] -> Url f [_path] :: Url f -> Path f [_queryStr] :: Url f -> [QueryArg f] defUrl :: Url f queryStr :: forall f_ajK1. Lens' (Url f_ajK1) [QueryArg f_ajK1] path :: forall f_ajK1. Lens' (Url f_ajK1) (Path f_ajK1) 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 :: forall f_ajNT. Lens' (Req f_ajNT) (Url f_ajNT) reqReturnType :: forall f_ajNT. Lens' (Req f_ajNT) (Maybe f_ajNT) reqMethod :: forall f_ajNT. Lens' (Req f_ajNT) Method reqHeaders :: forall f_ajNT. Lens' (Req f_ajNT) [HeaderArg f_ajNT] reqFuncName :: forall f_ajNT. Lens' (Req f_ajNT) FunctionName reqBody :: forall f_ajNT. Lens' (Req f_ajNT) (Maybe f_ajNT) 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 NoContent output type: ---- --
-- getEndpoints :: (HasForeign NoTypes NoContent api, GenerateList Text (Foreign NoContent api)) -- => Proxy api -> [Req NoContent] -- getEndpoints api = listFromAPI (Proxy :: Proxy NoTypes) (Proxy :: Proxy NoContent) api --class HasForeignType lang ftype a typeFor :: HasForeignType lang ftype a => Proxy lang -> Proxy ftype -> Proxy a -> ftype data NoTypes class HasForeign lang ftype (api :: *) where type Foreign ftype api :: * where { type family Foreign ftype api :: *; } foreignFor :: HasForeign lang ftype api => Proxy lang -> Proxy ftype -> Proxy api -> Req ftype -> Foreign ftype api -- | 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 (ftype :: k). Servant.Foreign.Internal.HasForeignType Servant.Foreign.Internal.NoTypes Servant.API.ContentTypes.NoContent ftype instance forall k (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 k1 (sym :: GHC.Types.Symbol) (lang :: k1) ftype (t :: k) api. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype t, Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.Capture.Capture sym t Servant.API.Sub.:> api) instance forall k1 k k2 (list :: [GHC.Types.*]) (lang :: k2) ftype (a :: k) (method :: k1) (status :: GHC.Types.Nat). (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 (sym :: GHC.Types.Symbol) (lang :: k) ftype a api. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.Header.Header sym a Servant.API.Sub.:> api) instance forall k k1 (sym :: GHC.Types.Symbol) (lang :: k1) ftype (a :: k) api. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.QueryParam.QueryParam sym a Servant.API.Sub.:> api) instance forall k (sym :: GHC.Types.Symbol) (lang :: k) ftype a api. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype [a], Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.QueryParam.QueryParams sym a Servant.API.Sub.:> api) instance forall k (sym :: GHC.Types.Symbol) (lang :: k) ftype api. (GHC.TypeLits.KnownSymbol sym, Servant.Foreign.Internal.HasForeignType lang ftype GHC.Types.Bool, Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.QueryParam.QueryFlag sym Servant.API.Sub.:> api) instance forall k (lang :: k) ftype. Servant.Foreign.Internal.HasForeign lang ftype Servant.API.Raw.Raw instance forall k k1 (list :: [GHC.Types.*]) (lang :: k1) ftype (a :: k) api. (Servant.Foreign.Internal.Elem Servant.API.ContentTypes.JSON list, Servant.Foreign.Internal.HasForeignType lang ftype a, Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.ReqBody.ReqBody list a Servant.API.Sub.:> api) instance forall k (path :: GHC.Types.Symbol) (lang :: k) ftype api. (GHC.TypeLits.KnownSymbol path, Servant.Foreign.Internal.HasForeign lang ftype api) => Servant.Foreign.Internal.HasForeign lang ftype (path Servant.API.Sub.:> api) instance forall k (lang :: k) ftype api. Servant.Foreign.Internal.HasForeign lang ftype api => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.RemoteHost.RemoteHost Servant.API.Sub.:> api) instance forall k (lang :: k) ftype api. Servant.Foreign.Internal.HasForeign lang ftype api => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.IsSecure.IsSecure Servant.API.Sub.:> api) instance forall k (lang :: k) ftype api. Servant.Foreign.Internal.HasForeign lang ftype api => Servant.Foreign.Internal.HasForeign lang ftype (Data.Vault.Lazy.Vault Servant.API.Sub.:> api) instance forall k (lang :: k) ftype api (name :: GHC.Types.Symbol) (context :: [GHC.Types.*]). Servant.Foreign.Internal.HasForeign lang ftype api => Servant.Foreign.Internal.HasForeign lang ftype (Servant.API.WithNamedContext.WithNamedContext name context api) instance forall k (lang :: k) ftype api. Servant.Foreign.Internal.HasForeign lang ftype api => Servant.Foreign.Internal.HasForeign lang ftype (Network.HTTP.Types.Version.HttpVersion Servant.API.Sub.:> api) 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 :: forall f_ajje. Lens' (Arg f_ajje) PathSegment argType :: forall f_ajje f_ajms. Lens (Arg f_ajje) (Arg f_ajms) f_ajje f_ajms argPath :: Getter (Arg f) Text reqUrl :: forall f_ajNT. Lens' (Req f_ajNT) (Url f_ajNT) reqMethod :: forall f_ajNT. Lens' (Req f_ajNT) Method reqHeaders :: forall f_ajNT. Lens' (Req f_ajNT) [HeaderArg f_ajNT] reqBody :: forall f_ajNT. Lens' (Req f_ajNT) (Maybe f_ajNT) reqReturnType :: forall f_ajNT. Lens' (Req f_ajNT) (Maybe f_ajNT) reqFuncName :: forall f_ajNT. Lens' (Req f_ajNT) FunctionName path :: forall f_ajK1. Lens' (Url f_ajK1) (Path f_ajK1) queryStr :: forall f_ajK1. Lens' (Url f_ajK1) [QueryArg f_ajK1] queryArgName :: forall f_ajB3 f_ajEL. Lens (QueryArg f_ajB3) (QueryArg f_ajEL) (Arg f_ajB3) (Arg f_ajEL) queryArgType :: forall f_ajB3. Lens' (QueryArg f_ajB3) ArgType headerArg :: forall f_ajF1 f_ajIk. Lens (HeaderArg f_ajF1) (HeaderArg f_ajIk) (Arg f_ajF1) (Arg f_ajIk) _PathSegment :: Iso' PathSegment Text _HeaderArg :: forall f_ajF1. Prism' (HeaderArg f_ajF1) (Arg f_ajF1) _ReplaceHeaderArg :: forall f_ajF1. Prism' (HeaderArg f_ajF1) (Arg f_ajF1, Text) _Static :: forall f_ajmH. Prism' (SegmentType f_ajmH) PathSegment _Cap :: forall f_ajmH f_ajqk. Prism (SegmentType f_ajqk) (SegmentType f_ajmH) (Arg f_ajqk) (Arg f_ajmH) _Normal :: Prism' ArgType () _Flag :: Prism' ArgType () _List :: Prism' ArgType () class HasForeign lang ftype (api :: *) where type Foreign ftype api :: * where { type family Foreign ftype api :: *; } foreignFor :: HasForeign lang ftype api => Proxy lang -> Proxy ftype -> Proxy api -> Req ftype -> Foreign ftype api -- | 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 NoContent output type: ---- --
-- getEndpoints :: (HasForeign NoTypes NoContent api, GenerateList Text (Foreign NoContent api)) -- => Proxy api -> [Req NoContent] -- getEndpoints api = listFromAPI (Proxy :: Proxy NoTypes) (Proxy :: Proxy NoContent) 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]