-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | generate API docs for your servant webservice -- -- Library for generating API docs from a servant API definition. -- -- Runnable example here. -- -- CHANGELOG @package servant-docs @version 0.6 module Servant.Docs.Internal.Pretty -- | PrettyJSON content type. data PrettyJSON -- | Prettify generated JSON documentation. -- --
-- docs (pretty (Proxy :: Proxy MyAPI)) --pretty :: Proxy layout -> Proxy (Pretty layout) -- | Replace all JSON content types with PrettyJSON. Kind-polymorphic so it -- can operate on kinds * and [*]. instance Servant.API.ContentTypes.Accept Servant.Docs.Internal.Pretty.PrettyJSON instance Data.Aeson.Types.Class.ToJSON a => Servant.API.ContentTypes.MimeRender Servant.Docs.Internal.Pretty.PrettyJSON a module Servant.Docs.Internal -- | An Endpoint type that holds the path and the -- method. -- -- Gets used as the key in the API hashmap. Modify -- defEndpoint or any Endpoint value you want using the -- path and method lenses to tweak. -- --
-- λ> defEndpoint -- GET / -- λ> defEndpoint & path <>~ ["foo"] -- GET /foo -- λ> defEndpoint & path <>~ ["foo"] & method .~ methodPost -- POST /foo --data Endpoint Endpoint :: [String] -> Method -> Endpoint [_path] :: Endpoint -> [String] [_method] :: Endpoint -> Method -- | Render a path as a /-delimited string showPath :: [String] -> String -- | An Endpoint whose path is `"/"` and whose method is -- GET -- -- Here's how you can modify it: -- --
-- λ> defEndpoint -- GET / -- λ> defEndpoint & path <>~ ["foo"] -- GET /foo -- λ> defEndpoint & path <>~ ["foo"] & method .~ methodPost -- POST /foo --defEndpoint :: Endpoint -- | Our API documentation type, a product of top-level information and a -- good old hashmap from Endpoint to Action data API API :: [DocIntro] -> HashMap Endpoint Action -> API [_apiIntros] :: API -> [DocIntro] [_apiEndpoints] :: API -> HashMap Endpoint Action -- | An empty API emptyAPI :: API -- | A type to represent captures. Holds the name of the capture and a -- description. -- -- Write a ToCapture instance for your captured types. data DocCapture DocCapture :: String -> String -> DocCapture [_capSymbol] :: DocCapture -> String [_capDesc] :: DocCapture -> String -- | A type to represent a GET parameter from the Query String. -- Holds its name, the possible values (leave empty if there isn't a -- finite number of them), and a description of how it influences the -- output or behavior. -- -- Write a ToParam instance for your GET parameter types data DocQueryParam DocQueryParam :: String -> [String] -> String -> ParamKind -> DocQueryParam [_paramName] :: DocQueryParam -> String [_paramValues] :: DocQueryParam -> [String] [_paramDesc] :: DocQueryParam -> String [_paramKind] :: DocQueryParam -> ParamKind -- | An introductory paragraph for your documentation. You can pass these -- to docsWithIntros. data DocIntro DocIntro :: String -> [String] -> DocIntro -- | Appears above the intro blob [_introTitle] :: DocIntro -> String -- | Each String is a paragraph. [_introBody] :: DocIntro -> [String] -- | A type to represent Authentication information about an endpoint. data DocAuthentication DocAuthentication :: String -> String -> DocAuthentication [_authIntro] :: DocAuthentication -> String [_authDataRequired] :: DocAuthentication -> String -- | A type to represent extra notes that may be attached to an -- Action. -- -- This is intended to be used when writing your own HasDocs instances to -- add extra sections to your endpoint's documentation. data DocNote DocNote :: String -> [String] -> DocNote [_noteTitle] :: DocNote -> String [_noteBody] :: DocNote -> [String] -- | Type of extra information that a user may wish to "union" with their -- documentation. -- -- These are intended to be built using extraInfo. Multiple ExtraInfo may -- be combined with the monoid instance. newtype ExtraInfo layout ExtraInfo :: (HashMap Endpoint Action) -> ExtraInfo layout -- | Documentation options. data DocOptions DocOptions :: Int -> DocOptions -- | Maximum samples allowed. [_maxSamples] :: DocOptions -> Int -- | Default documentation options. defaultDocOptions :: DocOptions -- | Type of GET parameter: -- --
-- λ> defResponse
-- Response {_respStatus = 200, _respTypes = [], _respBody = []}
-- λ> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "{ \"status\": \"ok\" }")]
-- Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well", "{ \"status\": \"ok\" }")]}
--
data Response
Response :: Int -> [MediaType] -> [(Text, MediaType, ByteString)] -> [Header] -> Response
[_respStatus] :: Response -> Int
[_respTypes] :: Response -> [MediaType]
[_respBody] :: Response -> [(Text, MediaType, ByteString)]
[_respHeaders] :: Response -> [Header]
-- | Default response: status code 200, no response body.
--
-- Can be tweaked with two lenses.
--
--
-- λ> defResponse
-- Response {_respStatus = 200, _respBody = Nothing}
-- λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
-- Response {_respStatus = 204, _respBody = Just "[]"}
--
defResponse :: Response
-- | A datatype that represents everything that can happen at an endpoint,
-- with its lenses:
--
-- -- docs == docsWithOptions defaultDocOptions --docs :: HasDocs layout => Proxy layout -> API -- | Generate the docs for a given API that implements HasDocs. docsWithOptions :: HasDocs layout => Proxy layout -> DocOptions -> API -- | Closed type family, check if endpoint is exactly within API. -- | Create an ExtraInfo that is garunteed to be within the given -- API layout. -- -- The safety here is to ensure that you only add custom documentation to -- an endpoint that actually exists within your API. -- --
-- extra :: ExtraInfo TestApi
-- extra =
-- extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
-- defAction & headers <>~ ["unicorns"]
-- & notes <>~ [ DocNote "Title" ["This is some text"]
-- , DocNote "Second secton" ["And some more"]
-- ]
--
extraInfo :: (IsIn endpoint layout, HasLink endpoint, HasDocs endpoint) => Proxy endpoint -> Action -> ExtraInfo layout
-- | Generate documentation given some extra introductions (in the form of
-- DocInfo) and some extra endpoint documentation (in the form
-- of ExtraInfo.
--
-- The extra introductions will be prepended to the top of the
-- documentation, before the specific endpoint documentation. The extra
-- endpoint documentation will be "unioned" with the automatically
-- generated endpoint documentation.
--
-- You are expected to build up the ExtraInfo with the Monoid instance
-- and extraInfo.
--
-- If you only want to add an introduction, use docsWithIntros.
docsWith :: HasDocs layout => DocOptions -> [DocIntro] -> ExtraInfo layout -> Proxy layout -> API
-- | Generate the docs for a given API that implements HasDocs with
-- with any number of introduction(s)
docsWithIntros :: HasDocs layout => [DocIntro] -> Proxy layout -> API
-- | The class that abstracts away the impact of API combinators on
-- documentation generation.
class HasDocs layout
docsFor :: HasDocs layout => Proxy layout -> (Endpoint, Action) -> DocOptions -> API
-- | The class that lets us display a sample input or output in the
-- supported content-types when generating documentation for endpoints
-- that either:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
-- {-# LANGUAGE OverloadedStrings #-}
--
-- import Data.Aeson
-- import Data.Text
-- import GHC.Generics
--
-- data Greet = Greet { _msg :: Text }
-- deriving (Generic, Show)
--
-- instance FromJSON Greet
-- instance ToJSON Greet
--
-- instance ToSample Greet where
-- toSamples _ = singleSample g
--
-- where g = Greet "Hello, haskeller!"
--
--
-- You can also instantiate this class using toSamples instead of
-- toSample: it lets you specify different responses along with
-- some context (as Text) that explains when you're supposed to
-- get the corresponding response.
class ToSample a where toSamples = defaultSamples
toSamples :: ToSample a => Proxy a -> [(Text, a)]
-- | Sample input or output (if there is at least one).
toSample :: ToSample a => Proxy a -> Maybe a
-- | No samples.
noSamples :: [(Text, a)]
-- | Single sample without description.
singleSample :: a -> [(Text, a)]
-- | Samples without documentation.
samples :: [a] -> [(Text, a)]
-- | Default sample Generic-based inputs/outputs.
defaultSamples :: (Generic a, GToSample (Rep a)) => Proxy a -> [(Text, a)]
-- | ToSample for Generics.
--
-- The use of Omega allows for more productive sample
-- generation.
class GToSample t
gtoSamples :: GToSample t => proxy t -> Omega (Text, t x)
class AllHeaderSamples ls
allHeaderToSample :: AllHeaderSamples ls => Proxy ls -> [Header]
-- | Synthesise a sample value of a type, encoded in the specified media
-- types.
sampleByteString :: (ToSample a, AllMimeRender (ct : cts) a) => Proxy (ct : cts) -> Proxy a -> [(MediaType, ByteString)]
-- | Synthesise a list of sample values of a particular type, encoded in
-- the specified media types.
sampleByteStrings :: (ToSample a, AllMimeRender (ct : cts) a) => Proxy (ct : cts) -> Proxy a -> [(Text, MediaType, ByteString)]
-- | The class that helps us automatically get documentation for GET
-- parameters.
--
-- Example of an instance:
--
-- -- instance ToParam (QueryParam "capital" Bool) where -- toParam _ = -- DocQueryParam "capital" -- ["true", "false"] -- "Get the greeting message in uppercase (true) or not (false). Default is false." --class ToParam t toParam :: ToParam t => Proxy t -> DocQueryParam -- | The class that helps us automatically get documentation for URL -- captures. -- -- Example of an instance: -- --
-- instance ToCapture (Capture "name" Text) where -- toCapture _ = DocCapture "name" "name of the person to greet" --class ToCapture c toCapture :: ToCapture c => Proxy c -> DocCapture -- | The class that helps us get documentation for authenticated endpoints class ToAuthInfo a toAuthInfo :: ToAuthInfo a => Proxy a -> DocAuthentication -- | Generate documentation in Markdown format for the given API. markdown :: API -> String -- | The generated docs for a :<|> b just appends the -- docs for a with the docs for b. -- | "books" :> Capture "isbn" Text will appear as -- books:isbn in the docs. instance Servant.Docs.Internal.GToSample GHC.Generics.U1 instance Servant.Docs.Internal.GToSample GHC.Generics.V1 instance (Servant.Docs.Internal.GToSample p, Servant.Docs.Internal.GToSample q) => Servant.Docs.Internal.GToSample (p GHC.Generics.:*: q) instance (Servant.Docs.Internal.GToSample p, Servant.Docs.Internal.GToSample q) => Servant.Docs.Internal.GToSample (p GHC.Generics.:+: q) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.GToSample (GHC.Generics.K1 i a) instance Servant.Docs.Internal.GToSample f => Servant.Docs.Internal.GToSample (GHC.Generics.M1 i a f) instance Servant.Docs.Internal.AllHeaderSamples '[] instance (Data.ByteString.Conversion.To.ToByteString l, Servant.Docs.Internal.AllHeaderSamples ls, Servant.Docs.Internal.ToSample l, GHC.TypeLits.KnownSymbol h) => Servant.Docs.Internal.AllHeaderSamples (Servant.API.Header.Header h l : ls) instance (Servant.Docs.Internal.HasDocs layout1, Servant.Docs.Internal.HasDocs layout2) => Servant.Docs.Internal.HasDocs (layout1 Servant.API.Alternative.:<|> layout2) instance forall (k :: BOX) (k1 :: BOX) (sym :: GHC.TypeLits.Symbol) (a :: k1) (sublayout :: k). (GHC.TypeLits.KnownSymbol sym, Servant.Docs.Internal.ToCapture (Servant.API.Capture.Capture sym a), Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.Capture.Capture sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (method :: k) (status :: GHC.TypeLits.Nat) ct (cts :: [*]) a. (Servant.Docs.Internal.ToSample a, Servant.API.ContentTypes.AllMimeRender (ct : cts) a, GHC.TypeLits.KnownNat status, Servant.API.Verbs.ReflectMethod method) => Servant.Docs.Internal.HasDocs (Servant.API.Verbs.Verb method status (ct : cts) a) instance forall (k :: BOX) (method :: k) (status :: GHC.TypeLits.Nat) ct (cts :: [*]) (ls :: [*]) a. (Servant.Docs.Internal.ToSample a, Servant.API.ContentTypes.AllMimeRender (ct : cts) a, GHC.TypeLits.KnownNat status, Servant.API.Verbs.ReflectMethod method, Servant.Docs.Internal.AllHeaderSamples ls, Servant.API.ResponseHeaders.GetHeaders (Servant.API.ResponseHeaders.HList ls)) => Servant.Docs.Internal.HasDocs (Servant.API.Verbs.Verb method status (ct : cts) (Servant.API.ResponseHeaders.Headers ls a)) instance forall (k :: BOX) (sym :: GHC.TypeLits.Symbol) a (sublayout :: k). (GHC.TypeLits.KnownSymbol sym, Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.Header.Header sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (k1 :: BOX) (sym :: GHC.TypeLits.Symbol) (a :: k1) (sublayout :: k). (GHC.TypeLits.KnownSymbol sym, Servant.Docs.Internal.ToParam (Servant.API.QueryParam.QueryParam sym a), Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.QueryParam.QueryParam sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (k1 :: BOX) (sym :: GHC.TypeLits.Symbol) (a :: k1) (sublayout :: k). (GHC.TypeLits.KnownSymbol sym, Servant.Docs.Internal.ToParam (Servant.API.QueryParam.QueryParams sym a), Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.QueryParam.QueryParams sym a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (sym :: GHC.TypeLits.Symbol) (sublayout :: k). (GHC.TypeLits.KnownSymbol sym, Servant.Docs.Internal.ToParam (Servant.API.QueryParam.QueryFlag sym), Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.QueryParam.QueryFlag sym Servant.API.Sub.:> sublayout) instance Servant.Docs.Internal.HasDocs Servant.API.Raw.Raw instance forall (k :: BOX) ct (cts :: [*]) a (sublayout :: k). (Servant.Docs.Internal.ToSample a, Servant.API.ContentTypes.AllMimeRender (ct : cts) a, Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.ReqBody.ReqBody (ct : cts) a Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (path :: GHC.TypeLits.Symbol) (sublayout :: k). (GHC.TypeLits.KnownSymbol path, Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (path Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (sublayout :: k). Servant.Docs.Internal.HasDocs sublayout => Servant.Docs.Internal.HasDocs (Servant.API.RemoteHost.RemoteHost Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (sublayout :: k). Servant.Docs.Internal.HasDocs sublayout => Servant.Docs.Internal.HasDocs (Servant.API.IsSecure.IsSecure Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (sublayout :: k). Servant.Docs.Internal.HasDocs sublayout => Servant.Docs.Internal.HasDocs (Network.HTTP.Types.Version.HttpVersion Servant.API.Sub.:> sublayout) instance forall (k :: BOX) (sublayout :: k). Servant.Docs.Internal.HasDocs sublayout => Servant.Docs.Internal.HasDocs (Data.Vault.Lazy.Vault Servant.API.Sub.:> sublayout) instance Servant.Docs.Internal.HasDocs sublayout => Servant.Docs.Internal.HasDocs (Servant.API.WithNamedContext.WithNamedContext name context sublayout) instance forall (k :: BOX) (realm :: GHC.TypeLits.Symbol) usr (sublayout :: k). (Servant.Docs.Internal.ToAuthInfo (Servant.API.BasicAuth.BasicAuth realm usr), Servant.Docs.Internal.HasDocs sublayout) => Servant.Docs.Internal.HasDocs (Servant.API.BasicAuth.BasicAuth realm usr Servant.API.Sub.:> sublayout) instance Servant.Docs.Internal.ToSample () instance Servant.Docs.Internal.ToSample GHC.Types.Bool instance Servant.Docs.Internal.ToSample GHC.Types.Ordering instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b) => Servant.Docs.Internal.ToSample (a, b) instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b, Servant.Docs.Internal.ToSample c) => Servant.Docs.Internal.ToSample (a, b, c) instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b, Servant.Docs.Internal.ToSample c, Servant.Docs.Internal.ToSample d) => Servant.Docs.Internal.ToSample (a, b, c, d) instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b, Servant.Docs.Internal.ToSample c, Servant.Docs.Internal.ToSample d, Servant.Docs.Internal.ToSample e) => Servant.Docs.Internal.ToSample (a, b, c, d, e) instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b, Servant.Docs.Internal.ToSample c, Servant.Docs.Internal.ToSample d, Servant.Docs.Internal.ToSample e, Servant.Docs.Internal.ToSample f) => Servant.Docs.Internal.ToSample (a, b, c, d, e, f) instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b, Servant.Docs.Internal.ToSample c, Servant.Docs.Internal.ToSample d, Servant.Docs.Internal.ToSample e, Servant.Docs.Internal.ToSample f, Servant.Docs.Internal.ToSample g) => Servant.Docs.Internal.ToSample (a, b, c, d, e, f, g) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (GHC.Base.Maybe a) instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b) => Servant.Docs.Internal.ToSample (Data.Either.Either a b) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample [a] instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Control.Applicative.Const a b) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Control.Applicative.ZipList a) instance Servant.Docs.Internal.ToSample Data.Monoid.All instance Servant.Docs.Internal.ToSample Data.Monoid.Any instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Data.Monoid.Sum a) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Data.Monoid.Product a) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Data.Monoid.First a) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Data.Monoid.Last a) instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Data.Monoid.Dual a) instance GHC.Generics.Selector Servant.Docs.Internal.S1_0_1Endpoint instance GHC.Generics.Selector Servant.Docs.Internal.S1_0_0Endpoint instance GHC.Generics.Constructor Servant.Docs.Internal.C1_0Endpoint instance GHC.Generics.Datatype Servant.Docs.Internal.D1Endpoint instance GHC.Show.Show Servant.Docs.Internal.API instance GHC.Classes.Eq Servant.Docs.Internal.API instance GHC.Show.Show Servant.Docs.Internal.Action instance GHC.Classes.Ord Servant.Docs.Internal.Action instance GHC.Classes.Eq Servant.Docs.Internal.Action instance GHC.Show.Show Servant.Docs.Internal.Response instance GHC.Classes.Ord Servant.Docs.Internal.Response instance GHC.Classes.Eq Servant.Docs.Internal.Response instance GHC.Show.Show Servant.Docs.Internal.DocQueryParam instance GHC.Classes.Ord Servant.Docs.Internal.DocQueryParam instance GHC.Classes.Eq Servant.Docs.Internal.DocQueryParam instance GHC.Show.Show Servant.Docs.Internal.ParamKind instance GHC.Classes.Ord Servant.Docs.Internal.ParamKind instance GHC.Classes.Eq Servant.Docs.Internal.ParamKind instance GHC.Show.Show Servant.Docs.Internal.DocOptions instance GHC.Show.Show Servant.Docs.Internal.DocNote instance GHC.Classes.Ord Servant.Docs.Internal.DocNote instance GHC.Classes.Eq Servant.Docs.Internal.DocNote instance GHC.Show.Show Servant.Docs.Internal.DocAuthentication instance GHC.Classes.Ord Servant.Docs.Internal.DocAuthentication instance GHC.Classes.Eq Servant.Docs.Internal.DocAuthentication instance GHC.Show.Show Servant.Docs.Internal.DocIntro instance GHC.Classes.Eq Servant.Docs.Internal.DocIntro instance GHC.Show.Show Servant.Docs.Internal.DocCapture instance GHC.Classes.Ord Servant.Docs.Internal.DocCapture instance GHC.Classes.Eq Servant.Docs.Internal.DocCapture instance GHC.Generics.Generic Servant.Docs.Internal.Endpoint instance GHC.Classes.Ord Servant.Docs.Internal.Endpoint instance GHC.Classes.Eq Servant.Docs.Internal.Endpoint instance GHC.Show.Show Servant.Docs.Internal.Endpoint instance Data.Hashable.Class.Hashable Servant.Docs.Internal.Endpoint instance GHC.Base.Monoid Servant.Docs.Internal.API instance GHC.Classes.Ord Servant.Docs.Internal.DocIntro instance forall (k :: BOX) (a :: k). GHC.Base.Monoid (Servant.Docs.Internal.ExtraInfo a) -- | This module lets you get API docs for free. It lets you generate an -- API from the type that represents your API using docs: -- --
-- docs :: HasDocs api => Proxy api -> API ---- -- Alternatively, if you wish to add one or more introductions to your -- documentation, use docsWithIntros: -- --
-- docsWithIntros :: HasDocs api => [DocIntro] -> Proxy api -> API ---- -- You can then call markdown on the API value: -- --
-- markdown :: API -> String ---- -- or define a custom pretty printer: -- --
-- yourPrettyDocs :: API -> String -- or blaze-html's HTML, or ... ---- -- The only thing you'll need to do will be to implement some classes for -- your captures, get parameters and request or response bodies. -- -- See example/greet.hs for an example. module Servant.Docs -- | The class that abstracts away the impact of API combinators on -- documentation generation. class HasDocs layout docsFor :: HasDocs layout => Proxy layout -> (Endpoint, Action) -> DocOptions -> API -- | Generate the docs for a given API that implements HasDocs. This -- is the default way to create documentation. -- --
-- docs == docsWithOptions defaultDocOptions --docs :: HasDocs layout => Proxy layout -> API -- | Prettify generated JSON documentation. -- --
-- docs (pretty (Proxy :: Proxy MyAPI)) --pretty :: Proxy layout -> Proxy (Pretty layout) -- | Generate documentation in Markdown format for the given API. markdown :: API -> String -- | Generate documentation given some extra introductions (in the form of -- DocInfo) and some extra endpoint documentation (in the form -- of ExtraInfo. -- -- The extra introductions will be prepended to the top of the -- documentation, before the specific endpoint documentation. The extra -- endpoint documentation will be "unioned" with the automatically -- generated endpoint documentation. -- -- You are expected to build up the ExtraInfo with the Monoid instance -- and extraInfo. -- -- If you only want to add an introduction, use docsWithIntros. docsWith :: HasDocs layout => DocOptions -> [DocIntro] -> ExtraInfo layout -> Proxy layout -> API -- | Generate the docs for a given API that implements HasDocs with -- with any number of introduction(s) docsWithIntros :: HasDocs layout => [DocIntro] -> Proxy layout -> API -- | Generate the docs for a given API that implements HasDocs. docsWithOptions :: HasDocs layout => Proxy layout -> DocOptions -> API -- | Type of extra information that a user may wish to "union" with their -- documentation. -- -- These are intended to be built using extraInfo. Multiple ExtraInfo may -- be combined with the monoid instance. newtype ExtraInfo layout ExtraInfo :: (HashMap Endpoint Action) -> ExtraInfo layout -- | Create an ExtraInfo that is garunteed to be within the given -- API layout. -- -- The safety here is to ensure that you only add custom documentation to -- an endpoint that actually exists within your API. -- --
-- extra :: ExtraInfo TestApi
-- extra =
-- extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
-- defAction & headers <>~ ["unicorns"]
-- & notes <>~ [ DocNote "Title" ["This is some text"]
-- , DocNote "Second secton" ["And some more"]
-- ]
--
extraInfo :: (IsIn endpoint layout, HasLink endpoint, HasDocs endpoint) => Proxy endpoint -> Action -> ExtraInfo layout
-- | Documentation options.
data DocOptions
DocOptions :: Int -> DocOptions
-- | Maximum samples allowed.
[_maxSamples] :: DocOptions -> Int
-- | Default documentation options.
defaultDocOptions :: DocOptions
maxSamples :: Iso' DocOptions Int
-- | The class that lets us display a sample input or output in the
-- supported content-types when generating documentation for endpoints
-- that either:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
-- {-# LANGUAGE OverloadedStrings #-}
--
-- import Data.Aeson
-- import Data.Text
-- import GHC.Generics
--
-- data Greet = Greet { _msg :: Text }
-- deriving (Generic, Show)
--
-- instance FromJSON Greet
-- instance ToJSON Greet
--
-- instance ToSample Greet where
-- toSamples _ = singleSample g
--
-- where g = Greet "Hello, haskeller!"
--
--
-- You can also instantiate this class using toSamples instead of
-- toSample: it lets you specify different responses along with
-- some context (as Text) that explains when you're supposed to
-- get the corresponding response.
class ToSample a where toSamples = defaultSamples
toSamples :: ToSample a => Proxy a -> [(Text, a)]
-- | Sample input or output (if there is at least one).
toSample :: ToSample a => Proxy a -> Maybe a
-- | No samples.
noSamples :: [(Text, a)]
-- | Single sample without description.
singleSample :: a -> [(Text, a)]
-- | Samples without documentation.
samples :: [a] -> [(Text, a)]
-- | Synthesise a sample value of a type, encoded in the specified media
-- types.
sampleByteString :: (ToSample a, AllMimeRender (ct : cts) a) => Proxy (ct : cts) -> Proxy a -> [(MediaType, ByteString)]
-- | Synthesise a list of sample values of a particular type, encoded in
-- the specified media types.
sampleByteStrings :: (ToSample a, AllMimeRender (ct : cts) a) => Proxy (ct : cts) -> Proxy a -> [(Text, MediaType, ByteString)]
-- | The class that helps us automatically get documentation for GET
-- parameters.
--
-- Example of an instance:
--
-- -- instance ToParam (QueryParam "capital" Bool) where -- toParam _ = -- DocQueryParam "capital" -- ["true", "false"] -- "Get the greeting message in uppercase (true) or not (false). Default is false." --class ToParam t toParam :: ToParam t => Proxy t -> DocQueryParam -- | The class that helps us automatically get documentation for URL -- captures. -- -- Example of an instance: -- --
-- instance ToCapture (Capture "name" Text) where -- toCapture _ = DocCapture "name" "name of the person to greet" --class ToCapture c toCapture :: ToCapture c => Proxy c -> DocCapture -- | An Endpoint type that holds the path and the -- method. -- -- Gets used as the key in the API hashmap. Modify -- defEndpoint or any Endpoint value you want using the -- path and method lenses to tweak. -- --
-- λ> defEndpoint -- GET / -- λ> defEndpoint & path <>~ ["foo"] -- GET /foo -- λ> defEndpoint & path <>~ ["foo"] & method .~ methodPost -- POST /foo --data Endpoint path :: Lens' Endpoint [String] method :: Lens' Endpoint Method -- | An Endpoint whose path is `"/"` and whose method is -- GET -- -- Here's how you can modify it: -- --
-- λ> defEndpoint -- GET / -- λ> defEndpoint & path <>~ ["foo"] -- GET /foo -- λ> defEndpoint & path <>~ ["foo"] & method .~ methodPost -- POST /foo --defEndpoint :: Endpoint -- | Our API documentation type, a product of top-level information and a -- good old hashmap from Endpoint to Action data API apiIntros :: Lens' API [DocIntro] apiEndpoints :: Lens' API (HashMap Endpoint Action) -- | An empty API emptyAPI :: API -- | A type to represent captures. Holds the name of the capture and a -- description. -- -- Write a ToCapture instance for your captured types. data DocCapture DocCapture :: String -> String -> DocCapture [_capSymbol] :: DocCapture -> String [_capDesc] :: DocCapture -> String capSymbol :: Lens' DocCapture String capDesc :: Lens' DocCapture String -- | A type to represent a GET parameter from the Query String. -- Holds its name, the possible values (leave empty if there isn't a -- finite number of them), and a description of how it influences the -- output or behavior. -- -- Write a ToParam instance for your GET parameter types data DocQueryParam DocQueryParam :: String -> [String] -> String -> ParamKind -> DocQueryParam [_paramName] :: DocQueryParam -> String [_paramValues] :: DocQueryParam -> [String] [_paramDesc] :: DocQueryParam -> String [_paramKind] :: DocQueryParam -> ParamKind -- | Type of GET parameter: -- --
-- λ> defResponse
-- Response {_respStatus = 200, _respTypes = [], _respBody = []}
-- λ> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "{ \"status\": \"ok\" }")]
-- Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well", "{ \"status\": \"ok\" }")]}
--
data Response
Response :: Int -> [MediaType] -> [(Text, MediaType, ByteString)] -> [Header] -> Response
[_respStatus] :: Response -> Int
[_respTypes] :: Response -> [MediaType]
[_respBody] :: Response -> [(Text, MediaType, ByteString)]
[_respHeaders] :: Response -> [Header]
respStatus :: Lens' Response Int
respTypes :: Lens' Response [MediaType]
respBody :: Lens' Response [(Text, MediaType, ByteString)]
-- | Default response: status code 200, no response body.
--
-- Can be tweaked with two lenses.
--
--
-- λ> defResponse
-- Response {_respStatus = 200, _respBody = Nothing}
-- λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
-- Response {_respStatus = 204, _respBody = Just "[]"}
--
defResponse :: Response
-- | A datatype that represents everything that can happen at an endpoint,
-- with its lenses:
--
--
--
-- You can tweak an Action (like the default defAction)
-- with these lenses to transform an action and add some information to
-- it.
data Action
captures :: Lens' Action [DocCapture]
headers :: Lens' Action [Text]
notes :: Lens' Action [DocNote]
params :: Lens' Action [DocQueryParam]
rqtypes :: Lens' Action [MediaType]
rqbody :: Lens' Action [(MediaType, ByteString)]
response :: Lens' Action Response
defAction :: Action
-- | Create an API that's comprised of a single endpoint. API is a
-- Monoid, so combine multiple endpoints with mappend or
-- <>.
single :: Endpoint -> Action -> API