servant-docs-0.10.0.1: generate API docs for your servant webservice

Safe HaskellNone
LanguageHaskell2010

Servant.Docs.Internal

Contents

Synopsis

Documentation

data Endpoint #

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

Constructors

Endpoint 

Fields

Instances

Eq Endpoint # 
Ord Endpoint # 
Show Endpoint # 
Generic Endpoint # 

Associated Types

type Rep Endpoint :: * -> * #

Methods

from :: Endpoint -> Rep Endpoint x #

to :: Rep Endpoint x -> Endpoint #

Hashable Endpoint # 

Methods

hashWithSalt :: Int -> Endpoint -> Int #

hash :: Endpoint -> Int #

type Rep Endpoint # 
type Rep Endpoint = D1 (MetaData "Endpoint" "Servant.Docs.Internal" "servant-docs-0.10.0.1-E9L4tHZA4ffLoUNuhOuI6d" False) (C1 (MetaCons "Endpoint" PrefixI True) ((:*:) (S1 (MetaSel (Just Symbol "_path") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [String])) (S1 (MetaSel (Just Symbol "_method") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Method))))

showPath :: [String] -> String #

Render a path as a /-delimited string

defEndpoint :: Endpoint #

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

data API #

Our API documentation type, a product of top-level information and a good old hashmap from Endpoint to Action

Instances

Eq API # 

Methods

(==) :: API -> API -> Bool #

(/=) :: API -> API -> Bool #

Show API # 

Methods

showsPrec :: Int -> API -> ShowS #

show :: API -> String #

showList :: [API] -> ShowS #

Semigroup API # 

Methods

(<>) :: API -> API -> API #

sconcat :: NonEmpty API -> API #

stimes :: Integral b => b -> API -> API #

Monoid API # 

Methods

mempty :: API #

mappend :: API -> API -> API #

mconcat :: [API] -> API #

emptyAPI :: API #

An empty API

data DocCapture #

A type to represent captures. Holds the name of the capture and a description.

Write a ToCapture instance for your captured types.

Constructors

DocCapture 

data DocQueryParam #

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 DocIntro #

An introductory paragraph for your documentation. You can pass these to docsWithIntros.

Constructors

DocIntro 

Fields

data DocNote #

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.

Constructors

DocNote 

newtype ExtraInfo 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.

Instances

Semigroup (ExtraInfo k a) # 

Methods

(<>) :: ExtraInfo k a -> ExtraInfo k a -> ExtraInfo k a #

sconcat :: NonEmpty (ExtraInfo k a) -> ExtraInfo k a #

stimes :: Integral b => b -> ExtraInfo k a -> ExtraInfo k a #

Monoid (ExtraInfo k a) # 

Methods

mempty :: ExtraInfo k a #

mappend :: ExtraInfo k a -> ExtraInfo k a -> ExtraInfo k a #

mconcat :: [ExtraInfo k a] -> ExtraInfo k a #

data DocOptions #

Documentation options.

Constructors

DocOptions 

Fields

defaultDocOptions :: DocOptions #

Default documentation options.

data ParamKind #

Type of GET parameter:

  • Normal corresponds to QueryParam, i.e your usual GET parameter
  • List corresponds to QueryParams, i.e GET parameters with multiple values
  • Flag corresponds to QueryFlag, i.e a value-less GET parameter

Constructors

Normal 
List 
Flag 

data Response #

A type to represent an HTTP response. Has an Int status, a list of possible MediaTypes, and a list of example ByteString response bodies. Tweak defResponse using the respStatus, respTypes and respBody lenses if you want.

If you want to respond with a non-empty response body, you'll most likely want to write a ToSample instance for the type that'll be represented as encoded data in the response.

Can be tweaked with three lenses.

λ> 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\" }")]}

defResponse :: Response #

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 "[]"}

data Action #

A datatype that represents everything that can happen at an endpoint, with its lenses:

  • List of captures (captures)
  • List of GET parameters (params)
  • What the request body should look like, if any is requested (rqbody)
  • What the response should be if everything goes well (response)

You can tweak an Action (like the default defAction) with these lenses to transform an action and add some information to it.

Instances

combineAction :: Action -> Action -> Action #

Combine two Actions, we can't make a monoid as merging Response breaks the laws.

As such, we invent a non-commutative, left associative operation combineAction to mush two together taking the response, body and content types from the very left.

single :: Endpoint -> Action -> API #

Create an API that's comprised of a single endpoint. API is a Monoid, so combine multiple endpoints with mappend or <>.

docs :: HasDocs api => Proxy api -> API #

Generate the docs for a given API that implements HasDocs. This is the default way to create documentation.

docs == docsWithOptions defaultDocOptions

docsWithOptions :: HasDocs api => Proxy api -> DocOptions -> API #

Generate the docs for a given API that implements HasDocs.

extraInfo :: (IsIn endpoint api, HasLink endpoint, HasDocs endpoint) => Proxy endpoint -> Action -> ExtraInfo api #

Create an ExtraInfo that is guaranteed 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"]
                                     ]

docsWith :: HasDocs api => DocOptions -> [DocIntro] -> ExtraInfo api -> Proxy api -> API #

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.

docsWithIntros :: HasDocs api => [DocIntro] -> Proxy api -> API #

Generate the docs for a given API that implements HasDocs with with any number of introduction(s)

class HasDocs api where #

The class that abstracts away the impact of API combinators on documentation generation.

Minimal complete definition

docsFor

Methods

docsFor :: Proxy api -> (Endpoint, Action) -> DocOptions -> API #

Instances

HasDocs * EmptyAPI #

The generated docs for EmptyAPI are empty.

Methods

docsFor :: Proxy EmptyAPI api -> (Endpoint, Action) -> DocOptions -> API #

HasDocs * Raw # 

Methods

docsFor :: Proxy Raw api -> (Endpoint, Action) -> DocOptions -> API #

(HasDocs * a, HasDocs * b) => HasDocs * ((:<|>) a b) #

The generated docs for a :<|> b just appends the docs for a with the docs for b.

Methods

docsFor :: Proxy (a :<|> b) api -> (Endpoint, Action) -> DocOptions -> API #

HasDocs * api => HasDocs * (WithNamedContext name context api) # 

Methods

docsFor :: Proxy (WithNamedContext name context api) api -> (Endpoint, Action) -> DocOptions -> API #

(ToAuthInfo * (BasicAuth realm usr), HasDocs k api) => HasDocs * ((:>) k * (BasicAuth realm usr) api) # 

Methods

docsFor :: Proxy ((k :> *) (BasicAuth realm usr) api) api -> (Endpoint, Action) -> DocOptions -> API #

HasDocs k api => HasDocs * ((:>) k * Vault api) # 

Methods

docsFor :: Proxy ((k :> *) Vault api) api -> (Endpoint, Action) -> DocOptions -> API #

HasDocs k api => HasDocs * ((:>) k * HttpVersion api) # 

Methods

docsFor :: Proxy ((k :> *) HttpVersion api) api -> (Endpoint, Action) -> DocOptions -> API #

HasDocs k api => HasDocs * ((:>) k * IsSecure api) # 

Methods

docsFor :: Proxy ((k :> *) IsSecure api) api -> (Endpoint, Action) -> DocOptions -> API #

HasDocs k api => HasDocs * ((:>) k * RemoteHost api) # 

Methods

docsFor :: Proxy ((k :> *) RemoteHost api) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol path, HasDocs k api) => HasDocs * ((:>) k Symbol path api) # 

Methods

docsFor :: Proxy ((k :> Symbol) path api) api -> (Endpoint, Action) -> DocOptions -> API #

(ToSample a, AllMimeRender ((:) * ct cts) a, HasDocs k api) => HasDocs * ((:>) k * (ReqBody * ((:) * ct cts) a) api) # 

Methods

docsFor :: Proxy ((k :> *) (ReqBody * ((* ': ct) cts) a) api) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol sym, ToParam * (QueryFlag sym), HasDocs k api) => HasDocs * ((:>) k * (QueryFlag sym) api) # 

Methods

docsFor :: Proxy ((k :> *) (QueryFlag sym) api) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol sym, ToParam * (QueryParams k1 sym a), HasDocs k api) => HasDocs * ((:>) k * (QueryParams k1 sym a) api) # 

Methods

docsFor :: Proxy ((k :> *) (QueryParams k1 sym a) api) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol sym, ToParam * (QueryParam k1 sym a), HasDocs k api) => HasDocs * ((:>) k * (QueryParam k1 sym a) api) # 

Methods

docsFor :: Proxy ((k :> *) (QueryParam k1 sym a) api) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol sym, HasDocs k api) => HasDocs * ((:>) k * (Header sym a) api) # 

Methods

docsFor :: Proxy ((k :> *) (Header sym a) api) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol sym, ToCapture * (CaptureAll k1 sym a), HasDocs k sublayout) => HasDocs * ((:>) k * (CaptureAll k1 sym a) sublayout) #

"books" :> CaptureAll "isbn" Text will appear as books:isbn in the docs.

Methods

docsFor :: Proxy ((k :> *) (CaptureAll k1 sym a) sublayout) api -> (Endpoint, Action) -> DocOptions -> API #

(KnownSymbol sym, ToCapture * (Capture k1 sym a), HasDocs k api) => HasDocs * ((:>) k * (Capture k1 sym a) api) #

"books" :> Capture "isbn" Text will appear as books:isbn in the docs.

Methods

docsFor :: Proxy ((k :> *) (Capture k1 sym a) api) api -> (Endpoint, Action) -> DocOptions -> API #

(ToSample a, AllMimeRender ((:) * ct cts) a, KnownNat status, ReflectMethod k1 method, AllHeaderSamples [*] ls, GetHeaders (HList ls)) => HasDocs * (Verb * k1 method status ((:) * ct cts) (Headers ls a)) # 

Methods

docsFor :: Proxy (Verb * k1 method status ((* ': ct) cts) (Headers ls a)) api -> (Endpoint, Action) -> DocOptions -> API #

(ToSample a, AllMimeRender ((:) * ct cts) a, KnownNat status, ReflectMethod k1 method) => HasDocs * (Verb * k1 method status ((:) * ct cts) a) # 

Methods

docsFor :: Proxy (Verb * k1 method status ((* ': ct) cts) a) api -> (Endpoint, Action) -> DocOptions -> API #

class ToSample a where #

The class that lets us display a sample input or output in the supported content-types when generating documentation for endpoints that either:

  • expect a request body, or
  • return a non empty response body

Example of an instance:

{-# 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.

Methods

toSamples :: Proxy a -> [(Text, a)] #

toSamples :: (Generic a, GToSample (Rep a)) => Proxy a -> [(Text, a)] #

Instances

ToSample Bool # 

Methods

toSamples :: Proxy * Bool -> [(Text, Bool)] #

ToSample Ordering # 

Methods

toSamples :: Proxy * Ordering -> [(Text, Ordering)] #

ToSample All # 

Methods

toSamples :: Proxy * All -> [(Text, All)] #

ToSample Any # 

Methods

toSamples :: Proxy * Any -> [(Text, Any)] #

ToSample NoContent # 
ToSample a => ToSample [a] # 

Methods

toSamples :: Proxy * [a] -> [(Text, [a])] #

ToSample a => ToSample (Maybe a) # 

Methods

toSamples :: Proxy * (Maybe a) -> [(Text, Maybe a)] #

ToSample a => ToSample (ZipList a) # 

Methods

toSamples :: Proxy * (ZipList a) -> [(Text, ZipList a)] #

ToSample a => ToSample (Dual a) # 

Methods

toSamples :: Proxy * (Dual a) -> [(Text, Dual a)] #

ToSample a => ToSample (Sum a) # 

Methods

toSamples :: Proxy * (Sum a) -> [(Text, Sum a)] #

ToSample a => ToSample (Product a) # 

Methods

toSamples :: Proxy * (Product a) -> [(Text, Product a)] #

ToSample a => ToSample (First a) # 

Methods

toSamples :: Proxy * (First a) -> [(Text, First a)] #

ToSample a => ToSample (Last a) # 

Methods

toSamples :: Proxy * (Last a) -> [(Text, Last a)] #

(ToSample a, ToSample b) => ToSample (Either a b) # 

Methods

toSamples :: Proxy * (Either a b) -> [(Text, Either a b)] #

(ToSample a, ToSample b) => ToSample (a, b) # 

Methods

toSamples :: Proxy * (a, b) -> [(Text, (a, b))] #

(ToSample a, ToSample b, ToSample c) => ToSample (a, b, c) # 

Methods

toSamples :: Proxy * (a, b, c) -> [(Text, (a, b, c))] #

ToSample a => ToSample (Const k a b) # 

Methods

toSamples :: Proxy * (Const k a b) -> [(Text, Const k a b)] #

(ToSample a, ToSample b, ToSample c, ToSample d) => ToSample (a, b, c, d) # 

Methods

toSamples :: Proxy * (a, b, c, d) -> [(Text, (a, b, c, d))] #

(ToSample a, ToSample b, ToSample c, ToSample d, ToSample e) => ToSample (a, b, c, d, e) # 

Methods

toSamples :: Proxy * (a, b, c, d, e) -> [(Text, (a, b, c, d, e))] #

(ToSample a, ToSample b, ToSample c, ToSample d, ToSample e, ToSample f) => ToSample (a, b, c, d, e, f) # 

Methods

toSamples :: Proxy * (a, b, c, d, e, f) -> [(Text, (a, b, c, d, e, f))] #

(ToSample a, ToSample b, ToSample c, ToSample d, ToSample e, ToSample f, ToSample g) => ToSample (a, b, c, d, e, f, g) # 

Methods

toSamples :: Proxy * (a, b, c, d, e, f, g) -> [(Text, (a, b, c, d, e, f, g))] #

toSample :: forall a. ToSample a => Proxy a -> Maybe a #

Sample input or output (if there is at least one).

noSamples :: [(Text, a)] #

No samples.

singleSample :: a -> [(Text, a)] #

Single sample without description.

samples :: [a] -> [(Text, a)] #

Samples without documentation.

defaultSamples :: forall a. (Generic a, GToSample (Rep a)) => Proxy a -> [(Text, a)] #

Default sample Generic-based inputs/outputs.

class GToSample t where #

ToSample for Generics.

The use of Omega allows for more productive sample generation.

Minimal complete definition

gtoSamples

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

Instances

GToSample * V1 # 

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

GToSample * U1 # 

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

ToSample a => GToSample * (K1 i a) # 

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

(GToSample * p, GToSample * q) => GToSample * ((:+:) p q) # 

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

(GToSample * p, GToSample * q) => GToSample * ((:*:) p q) # 

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

GToSample * f => GToSample * (M1 i a f) # 

Methods

gtoSamples :: proxy t -> Omega (Text, t x) #

class AllHeaderSamples ls where #

Minimal complete definition

allHeaderToSample

Methods

allHeaderToSample :: Proxy ls -> [Header] #

Instances

AllHeaderSamples [k] ([] k) # 

Methods

allHeaderToSample :: Proxy [k] ls -> [Header] #

(ToHttpApiData l, AllHeaderSamples [*] ls, ToSample l, KnownSymbol h) => AllHeaderSamples [*] ((:) * (Header h l) ls) # 

Methods

allHeaderToSample :: Proxy ((* ': Header h l) ls) ls -> [Header] #

sampleByteString :: forall ct cts a. (ToSample a, AllMimeRender (ct ': cts) a) => Proxy (ct ': cts) -> Proxy a -> [(MediaType, ByteString)] #

Synthesise a sample value of a type, encoded in the specified media types.

sampleByteStrings :: forall ct cts a. (ToSample a, AllMimeRender (ct ': cts) a) => Proxy (ct ': cts) -> Proxy a -> [(Text, MediaType, ByteString)] #

Synthesise a list of sample values of a particular type, encoded in the specified media types.

class ToParam t where #

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."

Minimal complete definition

toParam

Methods

toParam :: Proxy t -> DocQueryParam #

class ToCapture c where #

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"

Minimal complete definition

toCapture

Methods

toCapture :: Proxy c -> DocCapture #

class ToAuthInfo a where #

The class that helps us get documentation for authenticated endpoints

Minimal complete definition

toAuthInfo

markdown :: API -> String #

Generate documentation in Markdown format for the given API.

Instances