@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE ConstraintKinds #-}
23{-# LANGUAGE DataKinds #-}
34{-# LANGUAGE DefaultSignatures #-}
@@ -16,55 +17,41 @@
1617{-# LANGUAGE TypeOperators #-}
1718{-# LANGUAGE UndecidableInstances #-}
1819
20+#include "overlapping-compat.h"
1921module Servant.Docs.Internal where
2022
21−import Prelude ()
23+import Prelude ()
2224import Prelude.Compat
2325
2426import Control.Applicative
25−import Control.Arrow
26− (second)
27−import Control.Lens
28− (makeLenses, mapped, each, over, set, to, toListOf, traversed, view,
29− _1, (%~), (&), (.~), (<>~), (^.), (|>))
27+import Control.Arrow (second)
28+import Control.Lens (makeLenses, mapped, over,
29+ traversed, view, (%~), (&), (.~),
30+ (<>~), (^.), (|>))
31+import qualified Control.Monad.Omega as Omega
3032import qualified Data.ByteString.Char8 as BSC
31−import Data.ByteString.Lazy.Char8
32− (ByteString)
33+import Data.ByteString.Lazy.Char8 (ByteString)
3334import qualified Data.CaseInsensitive as CI
34−import Data.Foldable
35− (fold, toList)
36−import Data.Hashable
37− (Hashable)
38−import Data.HashMap.Strict
39− (HashMap)
40−import Data.List.Compat
41− (intercalate, intersperse, sort)
42−import Data.List.NonEmpty
43− (NonEmpty ((:|)), groupWith)
35+import Data.Foldable (fold)
36+import Data.Hashable (Hashable)
37+import Data.HashMap.Strict (HashMap)
38+import Data.List.Compat (intercalate, intersperse, sort)
39+import Data.List.NonEmpty (NonEmpty ((:|)), groupWith)
4440import qualified Data.List.NonEmpty as NE
4541import Data.Maybe
46−import Data.Monoid
47− (All (..), Any (..), Dual (..), First (..), Last (..),
48− Product (..), Sum (..))
49−import Data.Ord
50− (comparing)
51−import Data.Proxy
52− (Proxy (Proxy))
53−import Data.String.Conversions
54− (cs)
55−import Data.Text
56− (Text, unpack)
42+import Data.Monoid (All (..), Any (..), Dual (..),
43+ First (..), Last (..),
44+ Product (..), Sum (..))
45+import Data.Ord (comparing)
46+import Data.Proxy (Proxy (Proxy))
47+import Data.Semigroup (Semigroup (..))
48+import Data.String.Conversions (cs)
49+import Data.Text (Text, unpack)
5750import GHC.Generics
58− (Generic, Rep, K1(K1), M1(M1), U1(U1), V1,
59− (:*:)((:*:)), (:+:)(L1, R1))
60−import qualified GHC.Generics as G
6151import GHC.TypeLits
6252import Servant.API
6353import Servant.API.ContentTypes
6454import Servant.API.TypeLevel
65−import Servant.API.Generic
66−
67−import qualified Data.Universe.Helpers as U
6855
6956import qualified Data.HashMap.Strict as HM
7057import qualified Data.Text as T
@@ -77,15 +64,14 @@ import qualified Network.HTTP.Types as HTTP
7764-- or any 'Endpoint' value you want using the 'path' and 'method'
7865-- lenses to tweak.
7966--
80−-- >>> defEndpoint
81−-- "GET" /
82−--
83−-- >>> defEndpoint & path <>~ ["foo"]
84−-- "GET" /foo
85−--
86−-- >>> defEndpoint & path <>~ ["foo"] & method .~ HTTP.methodPost
87−-- "POST" /foo
88−--
67+-- @
68+-- λ> 'defEndpoint'
69+-- GET /
70+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"]
71+-- GET /foo
72+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"] & 'method' '.~' 'HTTP.methodPost'
73+-- POST /foo
74+-- @
8975data Endpoint = Endpoint
9076 { _path :: [String] -- type collected
9177 , _method :: HTTP.Method -- type collected
@@ -106,15 +92,14 @@ showPath ps = concatMap ('/' :) ps
10692--
10793-- Here's how you can modify it:
10894--
109−-- >>> defEndpoint
110−-- "GET" /
111−--
112−-- >>> defEndpoint & path <>~ ["foo"]
113−-- "GET" /foo
114−--
115−-- >>> defEndpoint & path <>~ ["foo"] & method .~ HTTP.methodPost
116−-- "POST" /foo
117−--
95+-- @
96+-- λ> 'defEndpoint'
97+-- GET /
98+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"]
99+-- GET /foo
100+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"] & 'method' '.~' 'HTTP.methodPost'
101+-- POST /foo
102+-- @
118103defEndpoint :: Endpoint
119104defEndpoint = Endpoint [] HTTP.methodGet
120105
@@ -131,8 +116,7 @@ instance Semigroup API where
131116 (<>) = mappend
132117
133118instance Monoid API where
134− API a1 b1 `mappend` API a2 b2 = API (a1 `mappend` a2)
135− (HM.unionWith combineAction b1 b2)
119+ API a1 b1 `mappend` API a2 b2 = API (a1 `mappend` a2) (b1 `mappend` b2)
136120 mempty = API mempty mempty
137121
138122-- | An empty 'API'
@@ -161,20 +145,6 @@ data DocQueryParam = DocQueryParam
161145 , _paramKind :: ParamKind
162146 } deriving (Eq, Ord, Show)
163147
164−-- | A type to represent fragment. Holds the name of the fragment and its description.
165−--
166−-- Write a 'ToFragment' instance for your fragment types.
167−data DocFragment = DocFragment
168− { _fragSymbol :: String -- type supplied
169− , _fragDesc :: String -- user supplied
170− } deriving (Eq, Ord, Show)
171−
172−-- | There should be at most one 'Fragment' per API endpoint.
173−-- So here we are keeping the first occurrence.
174−combineFragment :: Maybe DocFragment -> Maybe DocFragment -> Maybe DocFragment
175−Nothing `combineFragment` mdocFragment = mdocFragment
176−Just docFragment `combineFragment` _ = Just docFragment
177−
178148-- | An introductory paragraph for your documentation. You can pass these to
179149-- 'docsWithIntros'.
180150data DocIntro = DocIntro
@@ -240,14 +210,12 @@ data ParamKind = Normal | List | Flag
240210-- want to write a 'ToSample' instance for the type that'll be represented
241211-- as encoded data in the response.
242212--
243−-- Can be tweaked with four lenses.
244−--
245−-- >>> defResponse
246−-- Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}
247−--
248−-- >>> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "application/json", "{ \"status\": \"ok\" }")]
249−-- Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well",application/json,"{ \"status\": \"ok\" }")], _respHeaders = []}
213+-- Can be tweaked with three lenses.
250214--
215+-- > λ> defResponse
216+-- > Response {_respStatus = 200, _respTypes = [], _respBody = []}
217+-- > λ> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "{ \"status\": \"ok\" }")]
218+-- > Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well", "{ \"status\": \"ok\" }")]}
251219data Response = Response
252220 { _respStatus :: Int
253221 , _respTypes :: [M.MediaType]
@@ -255,25 +223,14 @@ data Response = Response
255223 , _respHeaders :: [HTTP.Header]
256224 } deriving (Eq, Ord, Show)
257225
258−-- | Combine two Responses, we can't make a monoid because merging Status breaks
259−-- the laws.
260−--
261−-- As such, we invent a non-commutative, left associative operation
262−-- 'combineResponse' to mush two together taking the status from the very left.
263−combineResponse :: Response -> Response -> Response
264−Response s ts bs hs `combineResponse` Response _ ts' bs' hs'
265− = Response s (ts <> ts') (bs <> bs') (hs <> hs')
266−
267226-- | Default response: status code 200, no response body.
268227--
269−-- Can be tweaked with four lenses.
270−--
271−-- >>> defResponse
272−-- Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}
273−--
274−-- >>> defResponse & respStatus .~ 204
275−-- Response {_respStatus = 204, _respTypes = [], _respBody = [], _respHeaders = []}
228+-- Can be tweaked with two lenses.
276229--
230+-- > λ> defResponse
231+-- > Response {_respStatus = 200, _respBody = Nothing}
232+-- > λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
233+-- > Response {_respStatus = 204, _respBody = Just "[]"}
277234defResponse :: Response
278235defResponse = Response
279236 { _respStatus = 200
@@ -295,9 +252,8 @@ defResponse = Response
295252data Action = Action
296253 { _authInfo :: [DocAuthentication] -- user supplied info
297254 , _captures :: [DocCapture] -- type collected + user supplied info
298− , _headers :: [HTTP.Header] -- type collected
255+ , _headers :: [Text] -- type collected
299256 , _params :: [DocQueryParam] -- type collected + user supplied info
300− , _fragment :: Maybe DocFragment -- type collected + user supplied info
301257 , _notes :: [DocNote] -- user supplied
302258 , _mxParams :: [(String, [DocQueryParam])] -- type collected + user supplied info
303259 , _rqtypes :: [M.MediaType] -- type collected
@@ -309,30 +265,27 @@ data Action = Action
309265-- laws.
310266--
311267-- As such, we invent a non-commutative, left associative operation
312−-- 'combineAction' to mush two together taking the response from the very left.
268+-- 'combineAction' to mush two together taking the response, body and content
269+-- types from the very left.
313270combineAction :: Action -> Action -> Action
314−Action a c h p f n m ts body resp
315− `combineAction` Action a' c' h' p' f' n' m' ts' body' resp' =
316− Action (a <> a') (c <> c') (h <> h') (p <> p') (f `combineFragment` f') (n <> n') (m <> m') (ts <> ts') (body <> body') (resp `combineResponse` resp')
271+Action a c h p n m ts body resp `combineAction` Action a' c' h' p' n' m' _ _ _ =
272+ Action (a <> a') (c <> c') (h <> h') (p <> p') (n <> n') (m <> m') ts body resp
317273
318274-- | Default 'Action'. Has no 'captures', no query 'params', expects
319275-- no request body ('rqbody') and the typical response is 'defResponse'.
320276--
321277-- Tweakable with lenses.
322278--
323−-- >>> defAction
324−-- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _fragment = Nothing, _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}}
325−--
326−-- >>> defAction & response.respStatus .~ 201
327−-- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _fragment = Nothing, _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 201, _respTypes = [], _respBody = [], _respHeaders = []}}
328−--
279+-- > λ> defAction
280+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
281+-- > λ> defAction & response.respStatus .~ 201
282+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
329283defAction :: Action
330284defAction =
331285 Action []
332286 []
333287 []
334288 []
335− Nothing
336289 []
337290 []
338291 []
@@ -356,14 +309,12 @@ data ShowContentTypes = AllContentTypes -- ^ For each example, show each conten
356309--
357310-- @since 0.11.1
358311data RenderingOptions = RenderingOptions
359− { _requestExamples :: !ShowContentTypes
312+ { _requestExamples :: !ShowContentTypes
360313 -- ^ How many content types to display for request body examples?
361− , _responseExamples :: !ShowContentTypes
314+ , _responseExamples :: !ShowContentTypes
362315 -- ^ How many content types to display for response body examples?
363− , _notesHeading :: !(Maybe String)
316+ , _notesHeading :: !(Maybe String)
364317 -- ^ Optionally group all 'notes' together under a common heading.
365− , _renderCurlBasePath :: !(Maybe String)
366− -- ^ Optionally render example curl requests under a common base path (e.g. `http://localhost:80`).
367318 } deriving (Show)
368319
369320-- | Default API generation options.
@@ -375,10 +326,9 @@ data RenderingOptions = RenderingOptions
375326-- @since 0.11.1
376327defRenderingOptions :: RenderingOptions
377328defRenderingOptions = RenderingOptions
378− { _requestExamples = AllContentTypes
379− , _responseExamples = AllContentTypes
380− , _notesHeading = Nothing
381− , _renderCurlBasePath = Nothing
329+ { _requestExamples = AllContentTypes
330+ , _responseExamples = AllContentTypes
331+ , _notesHeading = Nothing
382332 }
383333
384334-- gimme some lenses
@@ -388,7 +338,6 @@ makeLenses ''API
388338makeLenses ''Endpoint
389339makeLenses ''DocCapture
390340makeLenses ''DocQueryParam
391−makeLenses ''DocFragment
392341makeLenses ''DocIntro
393342makeLenses ''DocNote
394343makeLenses ''Response
@@ -398,8 +347,7 @@ makeLenses ''RenderingOptions
398347-- | Generate the docs for a given API that implements 'HasDocs'. This is the
399348-- default way to create documentation.
400349--
401−-- > docs == docsWithOptions defaultDocOptions
402−--
350+-- prop> docs == docsWithOptions defaultDocOptions
403351docs :: HasDocs api => Proxy api -> API
404352docs p = docsWithOptions p defaultDocOptions
405353
@@ -415,9 +363,9 @@ docsWithOptions p = docsFor p (defEndpoint, defAction)
415363-- > extra :: ExtraInfo TestApi
416364-- > extra =
417365-- > extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
418−-- > defAction & headers <>~ [("X-Num-Unicorns", 1)]
366+-- > defAction & headers <>~ ["unicorns"]
419367-- > & notes <>~ [ DocNote "Title" ["This is some text"]
420−-- > , DocNote "Second section" ["And some more"]
368+-- > , DocNote "Second secton" ["And some more"]
421369-- > ]
422370
423371extraInfo :: (IsIn endpoint api, HasLink endpoint, HasDocs endpoint)
@@ -447,7 +395,7 @@ docsWith opts intros (ExtraInfo endpoints) p =
447395 & apiEndpoints %~ HM.unionWith (flip combineAction) endpoints
448396
449397
450−-- | Generate the docs for a given API that implements 'HasDocs' with any
398+-- | Generate the docs for a given API that implements 'HasDocs' with with any
451399-- number of introduction(s)
452400docsWithIntros :: HasDocs api => [DocIntro] -> Proxy api -> API
453401docsWithIntros intros = docsWith defaultDocOptions intros mempty
@@ -510,22 +458,22 @@ samples = map ("",)
510458
511459-- | Default sample Generic-based inputs/outputs.
512460defaultSamples :: forall a. (Generic a, GToSample (Rep a)) => Proxy a -> [(Text, a)]
513−defaultSamples _ = second G.to <$> gtoSamples (Proxy :: Proxy (Rep a))
461+defaultSamples _ = Omega.runOmega $ second to <$> gtoSamples (Proxy :: Proxy (Rep a))
514462
515463-- | @'ToSample'@ for Generics.
516464--
517−-- Note: we use combinators from "Universe.Data.Helpers" for more productive sample generation.
465+-- The use of @'Omega'@ allows for more productive sample generation.
518466class GToSample t where
519− gtoSamples :: proxy t -> [(Text, t x)]
467+ gtoSamples :: proxy t -> Omega.Omega (Text, t x)
520468
521469instance GToSample U1 where
522− gtoSamples _ = singleSample U1
470+ gtoSamples _ = Omega.each (singleSample U1)
523471
524472instance GToSample V1 where
525473 gtoSamples _ = empty
526474
527475instance (GToSample p, GToSample q) => GToSample (p :*: q) where
528− gtoSamples _ = U.cartesianProduct render ps qs
476+ gtoSamples _ = render <$> ps <*> qs
529477 where
530478 ps = gtoSamples (Proxy :: Proxy p)
531479 qs = gtoSamples (Proxy :: Proxy q)
@@ -534,13 +482,13 @@ instance (GToSample p, GToSample q) => GToSample (p :*: q) where
534482 | otherwise = (ta <> ", " <> tb, a :*: b)
535483
536484instance (GToSample p, GToSample q) => GToSample (p :+: q) where
537− gtoSamples _ = lefts U.+++ rights
485+ gtoSamples _ = lefts <|> rights
538486 where
539487 lefts = second L1 <$> gtoSamples (Proxy :: Proxy p)
540488 rights = second R1 <$> gtoSamples (Proxy :: Proxy q)
541489
542490instance ToSample a => GToSample (K1 i a) where
543− gtoSamples _ = second K1 <$> toSamples (Proxy :: Proxy a)
491+ gtoSamples _ = second K1 <$> Omega.each (toSamples (Proxy :: Proxy a))
544492
545493instance (GToSample f) => GToSample (M1 i a f) where
546494 gtoSamples _ = second M1 <$> gtoSamples (Proxy :: Proxy f)
@@ -608,15 +556,6 @@ class ToCapture c where
608556class ToAuthInfo a where
609557 toAuthInfo :: Proxy a -> DocAuthentication
610558
611−-- | The class that helps us get documentation for URL fragments.
612−--
613−-- Example of an instance:
614−--
615−-- > instance ToFragment (Fragment a) where
616−-- > toFragment _ = DocFragment "fragment" "fragment description"
617−class ToFragment t where
618− toFragment :: Proxy t -> DocFragment
619−
620559-- | Generate documentation in Markdown format for
621560-- the given 'API'.
622561--
@@ -646,7 +585,7 @@ markdown = markdownWith defRenderingOptions
646585--
647586-- @since 0.11.1
648587markdownWith :: RenderingOptions -> API -> String
649−markdownWith RenderingOptions{..} api = unlines $
588+markdownWith RenderingOptions{..} api = unlines $
650589 introsStr (api ^. apiIntros)
651590 ++ (concatMap (uncurry printEndpoint) . sort . HM.toList $ api ^. apiEndpoints)
652591
@@ -657,12 +596,10 @@ markdownWith RenderingOptions{..} api = unlines $
657596 notesStr (action ^. notes) ++
658597 authStr (action ^. authInfo) ++
659598 capturesStr (action ^. captures) ++
660− headersStr (toListOf (headers . each . _1 . to (T.pack . BSC.unpack . CI.original)) action) ++
599+ headersStr (action ^. headers) ++
661600 paramsStr meth (action ^. params) ++
662− fragmentStr (action ^. fragment) ++
663601 rqbodyStr (action ^. rqtypes) (action ^. rqbody) ++
664602 responseStr (action ^. response) ++
665− maybe [] (curlStr endpoint (action ^. headers) (action ^. rqbody)) _renderCurlBasePath ++
666603 []
667604
668605 where str = "## " ++ BSC.unpack meth
@@ -762,14 +699,6 @@ markdownWith RenderingOptions{..} api = unlines $
762699
763700 where values = param ^. paramValues
764701
765− fragmentStr :: Maybe DocFragment -> [String]
766− fragmentStr Nothing = []
767− fragmentStr (Just frag) =
768− [ "### Fragment:", ""
769− , "- *" ++ (frag ^. fragSymbol) ++ "*: " ++ (frag ^. fragDesc)
770− , ""
771− ]
772−
773702 rqbodyStr :: [M.MediaType] -> [(Text, M.MediaType, ByteString)]-> [String]
774703 rqbodyStr [] [] = []
775704 rqbodyStr types s =
@@ -818,11 +747,12 @@ markdownWith RenderingOptions{..} api = unlines $
818747 ("text", "css") -> "css"
819748 (_, _) -> ""
820749
750+
821751 contentStr mime_type body =
822752 "" :
823− "```" <> markdownForType mime_type :
753+ " ```" <> markdownForType mime_type :
824754 cs body :
825− "```" :
755+ " ```" :
826756 "" :
827757 []
828758
@@ -842,41 +772,11 @@ markdownWith RenderingOptions{..} api = unlines $
842772 xs ->
843773 formatBodies _responseExamples xs
844774
845− curlStr :: Endpoint -> [HTTP.Header] -> [(Text, M.MediaType, ByteString)] -> String -> [String]
846− curlStr endpoint hdrs reqBodies basePath =
847− [ "### Sample Request:"
848− , ""
849− , "```bash"
850− , "curl -X" ++ BSC.unpack (endpoint ^. method) ++ " \\"
851− ] <>
852− maybe [] pure mbMediaTypeStr <>
853− headersStrs <>
854− maybe [] pure mbReqBodyStr <>
855− [ " " ++ basePath ++ showPath (endpoint ^. path)
856− , "```"
857− , ""
858− ]
859−
860− where escapeQuotes :: String -> String
861− escapeQuotes = concatMap $ \c -> case c of
862− '\"' -> "\\\""
863− _ -> [c]
864− mbReqBody = listToMaybe reqBodies
865− mbMediaTypeStr = mkMediaTypeStr <$> mbReqBody
866− headersStrs = mkHeaderStr <$> hdrs
867− mbReqBodyStr = mkReqBodyStr <$> mbReqBody
868− mkMediaTypeStr (_, media_type, _) =
869− " -H \"Content-Type: " ++ show media_type ++ "\" \\"
870− mkHeaderStr (hdrName, hdrVal) =
871− " -H \"" ++ escapeQuotes (cs (CI.original hdrName)) ++ ": " ++
872− escapeQuotes (cs hdrVal) ++ "\" \\"
873− mkReqBodyStr (_, _, body) = " -d \"" ++ escapeQuotes (cs body) ++ "\" \\"
874−
875775-- * Instances
876776
877777-- | The generated docs for @a ':<|>' b@ just appends the docs
878778-- for @a@ with the docs for @b@.
879−instance {-# OVERLAPPABLE #-}
779+instance OVERLAPPABLE_
880780 (HasDocs a, HasDocs b)
881781 => HasDocs (a :<|> b) where
882782
@@ -895,7 +795,7 @@ instance HasDocs EmptyAPI where
895795-- | @"books" :> 'Capture' "isbn" Text@ will appear as
896796-- @/books/:isbn@ in the docs.
897797instance (KnownSymbol sym, ToCapture (Capture sym a), HasDocs api)
898− => HasDocs (Capture' '[] sym a :> api) where
798+ => HasDocs (Capture' mods sym a :> api) where
899799
900800 docsFor Proxy (endpoint, action) =
901801 docsFor subApiP (endpoint', action')
@@ -907,28 +807,6 @@ instance (KnownSymbol sym, ToCapture (Capture sym a), HasDocs api)
907807 endpoint' = over path (\p -> p ++ [":" ++ symbolVal symP]) endpoint
908808 symP = Proxy :: Proxy sym
909809
910−instance (KnownSymbol descr, KnownSymbol sym, HasDocs api)
911− => HasDocs (Capture' (Description descr ': mods) sym a :> api) where
912−
913− docsFor Proxy (endpoint, action) =
914− docsFor subApiP (endpoint', action')
915−
916− where subApiP = Proxy :: Proxy api
917−
918− docCapture = DocCapture (symbolVal symP) (symbolVal descrP)
919− action' = over captures (|> docCapture) action
920− endpoint' = over path (\p -> p ++ [":" ++ symbolVal symP]) endpoint
921− descrP = Proxy :: Proxy descr
922− symP = Proxy :: Proxy sym
923−
924−instance {-# OVERLAPPABLE #-} HasDocs (Capture' mods sym a :> api)
925− => HasDocs (Capture' (mod ': mods) sym a :> api) where
926−
927− docsFor Proxy =
928− docsFor apiP
929−
930− where apiP = Proxy :: Proxy (Capture' mods sym a :> api)
931−
932810
933811-- | @"books" :> 'CaptureAll' "isbn" Text@ will appear as
934812-- @/books/:isbn@ in the docs.
@@ -946,7 +824,7 @@ instance (KnownSymbol sym, ToCapture (CaptureAll sym a), HasDocs sublayout)
946824 symP = Proxy :: Proxy sym
947825
948826
949−instance {-# OVERLAPPABLE #-}
827+instance OVERLAPPABLE_
950828 (ToSample a, AllMimeRender (ct ': cts) a, KnownNat status
951829 , ReflectMethod method)
952830 => HasDocs (Verb method status (ct ': cts) a) where
@@ -962,37 +840,7 @@ instance {-# OVERLAPPABLE #-}
962840 status = fromInteger $ natVal (Proxy :: Proxy status)
963841 p = Proxy :: Proxy a
964842
965−instance (ReflectMethod method) =>
966− HasDocs (NoContentVerb method) where
967− docsFor Proxy (endpoint, action) DocOptions{..} =
968− single endpoint' action'
969−
970− where endpoint' = endpoint & method .~ method'
971− action' = action & response.respStatus .~ 204
972− & response.respTypes .~ []
973− & response.respBody .~ []
974− & response.respHeaders .~ []
975− method' = reflectMethod (Proxy :: Proxy method)
976−
977−-- | TODO: mention the endpoint is streaming, its framing strategy
978−--
979−-- Also there are no samples.
980−--
981−-- TODO: AcceptFraming for content-type
982−instance {-# OVERLAPPABLE #-}
983− (Accept ct, KnownNat status, ReflectMethod method)
984− => HasDocs (Stream method status framing ct a) where
985− docsFor Proxy (endpoint, action) DocOptions{..} =
986− single endpoint' action'
987−
988− where endpoint' = endpoint & method .~ method'
989− action' = action & response.respTypes .~ allMime t
990− & response.respStatus .~ status
991− t = Proxy :: Proxy '[ct]
992− method' = reflectMethod (Proxy :: Proxy method)
993− status = fromInteger $ natVal (Proxy :: Proxy status)
994−
995−instance {-# OVERLAPPING #-}
843+instance OVERLAPPING_
996844 (ToSample a, AllMimeRender (ct ': cts) a, KnownNat status
997845 , ReflectMethod method, AllHeaderSamples ls, GetHeaders (HList ls))
998846 => HasDocs (Verb method status (ct ': cts) (Headers ls a)) where
@@ -1010,17 +858,14 @@ instance {-# OVERLAPPING #-}
1010858 status = fromInteger $ natVal (Proxy :: Proxy status)
1011859 p = Proxy :: Proxy a
1012860
1013−instance (ToHttpApiData a, ToSample a, KnownSymbol sym, HasDocs api)
861+instance (KnownSymbol sym, HasDocs api)
1014862 => HasDocs (Header' mods sym a :> api) where
1015863 docsFor Proxy (endpoint, action) =
1016864 docsFor subApiP (endpoint, action')
1017865
1018866 where subApiP = Proxy :: Proxy api
1019− action' = over headers (|> (headerName, headerVal)) action
1020− headerName = CI.mk . cs $ symbolVal (Proxy :: Proxy sym)
1021− headerVal = case toSample (Proxy :: Proxy a) of
1022− Just x -> cs $ toHeader x
1023− Nothing -> "<no header sample provided>"
867+ action' = over headers (|> headername) action
868+ headername = T.pack $ symbolVal (Proxy :: Proxy sym)
1024869
1025870instance (KnownSymbol sym, ToParam (QueryParam' mods sym a), HasDocs api)
1026871 => HasDocs (QueryParam' mods sym a :> api) where
@@ -1053,15 +898,6 @@ instance (KnownSymbol sym, ToParam (QueryFlag sym), HasDocs api)
1053898 paramP = Proxy :: Proxy (QueryFlag sym)
1054899 action' = over params (|> toParam paramP) action
1055900
1056−instance (ToFragment (Fragment a), HasDocs api)
1057− => HasDocs (Fragment a :> api) where
1058−
1059− docsFor Proxy (endpoint, action) =
1060− docsFor subApiP (endpoint, action')
1061−
1062− where subApiP = Proxy :: Proxy api
1063− fragmentP = Proxy :: Proxy (Fragment a)
1064− action' = set fragment (Just (toFragment fragmentP)) action
1065901
1066902instance HasDocs Raw where
1067903 docsFor _proxy (endpoint, action) _ =
@@ -1094,6 +930,7 @@ instance (KnownSymbol desc, HasDocs api)
1094930-- both are even defined) for any particular type.
1095931instance (ToSample a, AllMimeRender (ct ': cts) a, HasDocs api)
1096932 => HasDocs (ReqBody' mods (ct ': cts) a :> api) where
933+
1097934 docsFor Proxy (endpoint, action) opts@DocOptions{..} =
1098935 docsFor subApiP (endpoint, action') opts
1099936
@@ -1104,18 +941,6 @@ instance (ToSample a, AllMimeRender (ct ': cts) a, HasDocs api)
1104941 t = Proxy :: Proxy (ct ': cts)
1105942 p = Proxy :: Proxy a
1106943
1107−-- | TODO: this instance is incomplete.
1108−instance (HasDocs api, Accept ctype) => HasDocs (StreamBody' mods framing ctype a :> api) where
1109− docsFor Proxy (endpoint, action) opts =
1110− docsFor subApiP (endpoint, action') opts
1111− where
1112− subApiP = Proxy :: Proxy api
1113−
1114− action' :: Action
1115− action' = action & rqtypes .~ toList (contentTypes t)
1116−
1117− t = Proxy :: Proxy ctype
1118−
1119944instance (KnownSymbol path, HasDocs api) => HasDocs (path :> api) where
1120945
1121946 docsFor Proxy (endpoint, action) =
@@ -1144,9 +969,6 @@ instance HasDocs api => HasDocs (Vault :> api) where
1144969instance HasDocs api => HasDocs (WithNamedContext name context api) where
1145970 docsFor Proxy = docsFor (Proxy :: Proxy api)
1146971
1147−instance HasDocs api => HasDocs (WithResource res :> api) where
1148− docsFor Proxy = docsFor (Proxy :: Proxy api)
1149−
1150972instance (ToAuthInfo (BasicAuth realm usr), HasDocs api) => HasDocs (BasicAuth realm usr :> api) where
1151973 docsFor Proxy (endpoint, action) =
1152974 docsFor (Proxy :: Proxy api) (endpoint, action')
@@ -1154,9 +976,6 @@ instance (ToAuthInfo (BasicAuth realm usr), HasDocs api) => HasDocs (BasicAuth r
1154976 authProxy = Proxy :: Proxy (BasicAuth realm usr)
1155977 action' = over authInfo (|> toAuthInfo authProxy) action
1156978
1157−instance HasDocs (ToServantApi api) => HasDocs (NamedRoutes api) where
1158− docsFor Proxy = docsFor (Proxy :: Proxy (ToServantApi api))
1159−
1160979-- ToSample instances for simple types
1161980instance ToSample NoContent
1162981instance ToSample Bool
@@ -1173,7 +992,6 @@ instance (ToSample a, ToSample b, ToSample c, ToSample d, ToSample e, ToSample f
1173992instance ToSample a => ToSample (Maybe a)
1174993instance (ToSample a, ToSample b) => ToSample (Either a b)
1175994instance ToSample a => ToSample [a]
1176−instance ToSample a => ToSample (NonEmpty a)
1177995
1178996-- ToSample instances for Control.Applicative types
1179997instance ToSample a => ToSample (Const a b)
@@ -1187,6 +1005,3 @@ instance ToSample a => ToSample (Product a)
11871005instance ToSample a => ToSample (First a)
11881006instance ToSample a => ToSample (Last a)
11891007instance ToSample a => ToSample (Dual a)
1190−
1191−-- $setup
1192−-- >>> :set -XOverloadedStrings