@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE ConstraintKinds #-}
23{-# LANGUAGE DataKinds #-}
34{-# LANGUAGE DefaultSignatures #-}
@@ -16,6 +17,7 @@
1617{-# LANGUAGE TypeOperators #-}
1718{-# LANGUAGE UndecidableInstances #-}
1819
20+#include "overlapping-compat.h"
1921module Servant.Docs.Internal where
2022
2123import Prelude ()
@@ -25,14 +27,15 @@ import Control.Applicative
2527import Control.Arrow
2628 (second)
2729import Control.Lens
28− (makeLenses, mapped, each, over, set, to, toListOf, traversed, view,
29− _1, (%~), (&), (.~), (<>~), (^.), (|>))
30+ (makeLenses, mapped, over, traversed, view, (%~), (&), (.~),
31+ (<>~), (^.), (|>))
32+import qualified Control.Monad.Omega as Omega
3033import qualified Data.ByteString.Char8 as BSC
3134import Data.ByteString.Lazy.Char8
3235 (ByteString)
3336import qualified Data.CaseInsensitive as CI
3437import Data.Foldable
35− (fold, toList)
38+ (fold)
3639import Data.Hashable
3740 (Hashable)
3841import Data.HashMap.Strict
@@ -50,21 +53,17 @@ import Data.Ord
5053 (comparing)
5154import Data.Proxy
5255 (Proxy (Proxy))
56+import Data.Semigroup
57+ (Semigroup (..))
5358import Data.String.Conversions
5459 (cs)
5560import Data.Text
5661 (Text, unpack)
5762import GHC.Generics
58− (Generic, Rep, K1(K1), M1(M1), U1(U1), V1,
59− (:*:)((:*:)), (:+:)(L1, R1))
60−import qualified GHC.Generics as G
6163import GHC.TypeLits
6264import Servant.API
6365import Servant.API.ContentTypes
6466import Servant.API.TypeLevel
65−import Servant.API.Generic
66−
67−import qualified Data.Universe.Helpers as U
6867
6968import qualified Data.HashMap.Strict as HM
7069import qualified Data.Text as T
@@ -77,15 +76,14 @@ import qualified Network.HTTP.Types as HTTP
7776-- or any 'Endpoint' value you want using the 'path' and 'method'
7877-- lenses to tweak.
7978--
80−-- >>> defEndpoint
81−-- "GET" /
82−--
83−-- >>> defEndpoint & path <>~ ["foo"]
84−-- "GET" /foo
85−--
86−-- >>> defEndpoint & path <>~ ["foo"] & method .~ HTTP.methodPost
87−-- "POST" /foo
88−--
79+-- @
80+-- λ> 'defEndpoint'
81+-- GET /
82+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"]
83+-- GET /foo
84+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"] & 'method' '.~' 'HTTP.methodPost'
85+-- POST /foo
86+-- @
8987data Endpoint = Endpoint
9088 { _path :: [String] -- type collected
9189 , _method :: HTTP.Method -- type collected
@@ -106,15 +104,14 @@ showPath ps = concatMap ('/' :) ps
106104--
107105-- Here's how you can modify it:
108106--
109−-- >>> defEndpoint
110−-- "GET" /
111−--
112−-- >>> defEndpoint & path <>~ ["foo"]
113−-- "GET" /foo
114−--
115−-- >>> defEndpoint & path <>~ ["foo"] & method .~ HTTP.methodPost
116−-- "POST" /foo
117−--
107+-- @
108+-- λ> 'defEndpoint'
109+-- GET /
110+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"]
111+-- GET /foo
112+-- λ> 'defEndpoint' & 'path' '<>~' ["foo"] & 'method' '.~' 'HTTP.methodPost'
113+-- POST /foo
114+-- @
118115defEndpoint :: Endpoint
119116defEndpoint = Endpoint [] HTTP.methodGet
120117
@@ -131,8 +128,7 @@ instance Semigroup API where
131128 (<>) = mappend
132129
133130instance Monoid API where
134− API a1 b1 `mappend` API a2 b2 = API (a1 `mappend` a2)
135− (HM.unionWith combineAction b1 b2)
131+ API a1 b1 `mappend` API a2 b2 = API (a1 `mappend` a2) (b1 `mappend` b2)
136132 mempty = API mempty mempty
137133
138134-- | An empty 'API'
@@ -161,20 +157,6 @@ data DocQueryParam = DocQueryParam
161157 , _paramKind :: ParamKind
162158 } deriving (Eq, Ord, Show)
163159
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−
178160-- | An introductory paragraph for your documentation. You can pass these to
179161-- 'docsWithIntros'.
180162data DocIntro = DocIntro
@@ -240,14 +222,12 @@ data ParamKind = Normal | List | Flag
240222-- want to write a 'ToSample' instance for the type that'll be represented
241223-- as encoded data in the response.
242224--
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 = []}
225+-- Can be tweaked with three lenses.
250226--
227+-- > λ> defResponse
228+-- > Response {_respStatus = 200, _respTypes = [], _respBody = []}
229+-- > λ> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "{ \"status\": \"ok\" }")]
230+-- > Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well", "{ \"status\": \"ok\" }")]}
251231data Response = Response
252232 { _respStatus :: Int
253233 , _respTypes :: [M.MediaType]
@@ -255,25 +235,14 @@ data Response = Response
255235 , _respHeaders :: [HTTP.Header]
256236 } deriving (Eq, Ord, Show)
257237
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−
267238-- | Default response: status code 200, no response body.
268239--
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 = []}
240+-- Can be tweaked with two lenses.
276241--
242+-- > λ> defResponse
243+-- > Response {_respStatus = 200, _respBody = Nothing}
244+-- > λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
245+-- > Response {_respStatus = 204, _respBody = Just "[]"}
277246defResponse :: Response
278247defResponse = Response
279248 { _respStatus = 200
@@ -295,9 +264,8 @@ defResponse = Response
295264data Action = Action
296265 { _authInfo :: [DocAuthentication] -- user supplied info
297266 , _captures :: [DocCapture] -- type collected + user supplied info
298− , _headers :: [HTTP.Header] -- type collected
267+ , _headers :: [Text] -- type collected
299268 , _params :: [DocQueryParam] -- type collected + user supplied info
300− , _fragment :: Maybe DocFragment -- type collected + user supplied info
301269 , _notes :: [DocNote] -- user supplied
302270 , _mxParams :: [(String, [DocQueryParam])] -- type collected + user supplied info
303271 , _rqtypes :: [M.MediaType] -- type collected
@@ -309,30 +277,27 @@ data Action = Action
309277-- laws.
310278--
311279-- As such, we invent a non-commutative, left associative operation
312−-- 'combineAction' to mush two together taking the response from the very left.
280+-- 'combineAction' to mush two together taking the response, body and content
281+-- types from the very left.
313282combineAction :: 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')
283+Action a c h p n m ts body resp `combineAction` Action a' c' h' p' n' m' _ _ _ =
284+ Action (a <> a') (c <> c') (h <> h') (p <> p') (n <> n') (m <> m') ts body resp
317285
318286-- | Default 'Action'. Has no 'captures', no query 'params', expects
319287-- no request body ('rqbody') and the typical response is 'defResponse'.
320288--
321289-- Tweakable with lenses.
322290--
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−--
291+-- > λ> defAction
292+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
293+-- > λ> defAction & response.respStatus .~ 201
294+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
329295defAction :: Action
330296defAction =
331297 Action []
332298 []
333299 []
334300 []
335− Nothing
336301 []
337302 []
338303 []
@@ -356,14 +321,12 @@ data ShowContentTypes = AllContentTypes -- ^ For each example, show each conten
356321--
357322-- @since 0.11.1
358323data RenderingOptions = RenderingOptions
359− { _requestExamples :: !ShowContentTypes
324+ { _requestExamples :: !ShowContentTypes
360325 -- ^ How many content types to display for request body examples?
361− , _responseExamples :: !ShowContentTypes
326+ , _responseExamples :: !ShowContentTypes
362327 -- ^ How many content types to display for response body examples?
363− , _notesHeading :: !(Maybe String)
328+ , _notesHeading :: !(Maybe String)
364329 -- ^ 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`).
367330 } deriving (Show)
368331
369332-- | Default API generation options.
@@ -375,10 +338,9 @@ data RenderingOptions = RenderingOptions
375338-- @since 0.11.1
376339defRenderingOptions :: RenderingOptions
377340defRenderingOptions = RenderingOptions
378− { _requestExamples = AllContentTypes
379− , _responseExamples = AllContentTypes
380− , _notesHeading = Nothing
381− , _renderCurlBasePath = Nothing
341+ { _requestExamples = AllContentTypes
342+ , _responseExamples = AllContentTypes
343+ , _notesHeading = Nothing
382344 }
383345
384346-- gimme some lenses
@@ -388,7 +350,6 @@ makeLenses ''API
388350makeLenses ''Endpoint
389351makeLenses ''DocCapture
390352makeLenses ''DocQueryParam
391−makeLenses ''DocFragment
392353makeLenses ''DocIntro
393354makeLenses ''DocNote
394355makeLenses ''Response
@@ -398,8 +359,7 @@ makeLenses ''RenderingOptions
398359-- | Generate the docs for a given API that implements 'HasDocs'. This is the
399360-- default way to create documentation.
400361--
401−-- > docs == docsWithOptions defaultDocOptions
402−--
362+-- prop> docs == docsWithOptions defaultDocOptions
403363docs :: HasDocs api => Proxy api -> API
404364docs p = docsWithOptions p defaultDocOptions
405365
@@ -415,9 +375,9 @@ docsWithOptions p = docsFor p (defEndpoint, defAction)
415375-- > extra :: ExtraInfo TestApi
416376-- > extra =
417377-- > extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
418−-- > defAction & headers <>~ [("X-Num-Unicorns", 1)]
378+-- > defAction & headers <>~ ["unicorns"]
419379-- > & notes <>~ [ DocNote "Title" ["This is some text"]
420−-- > , DocNote "Second section" ["And some more"]
380+-- > , DocNote "Second secton" ["And some more"]
421381-- > ]
422382
423383extraInfo :: (IsIn endpoint api, HasLink endpoint, HasDocs endpoint)
@@ -510,22 +470,22 @@ samples = map ("",)
510470
511471-- | Default sample Generic-based inputs/outputs.
512472defaultSamples :: forall a. (Generic a, GToSample (Rep a)) => Proxy a -> [(Text, a)]
513−defaultSamples _ = second G.to <$> gtoSamples (Proxy :: Proxy (Rep a))
473+defaultSamples _ = Omega.runOmega $ second to <$> gtoSamples (Proxy :: Proxy (Rep a))
514474
515475-- | @'ToSample'@ for Generics.
516476--
517−-- Note: we use combinators from "Universe.Data.Helpers" for more productive sample generation.
477+-- The use of @'Omega'@ allows for more productive sample generation.
518478class GToSample t where
519− gtoSamples :: proxy t -> [(Text, t x)]
479+ gtoSamples :: proxy t -> Omega.Omega (Text, t x)
520480
521481instance GToSample U1 where
522− gtoSamples _ = singleSample U1
482+ gtoSamples _ = Omega.each (singleSample U1)
523483
524484instance GToSample V1 where
525485 gtoSamples _ = empty
526486
527487instance (GToSample p, GToSample q) => GToSample (p :*: q) where
528− gtoSamples _ = U.cartesianProduct render ps qs
488+ gtoSamples _ = render <$> ps <*> qs
529489 where
530490 ps = gtoSamples (Proxy :: Proxy p)
531491 qs = gtoSamples (Proxy :: Proxy q)
@@ -534,13 +494,13 @@ instance (GToSample p, GToSample q) => GToSample (p :*: q) where
534494 | otherwise = (ta <> ", " <> tb, a :*: b)
535495
536496instance (GToSample p, GToSample q) => GToSample (p :+: q) where
537− gtoSamples _ = lefts U.+++ rights
497+ gtoSamples _ = lefts <|> rights
538498 where
539499 lefts = second L1 <$> gtoSamples (Proxy :: Proxy p)
540500 rights = second R1 <$> gtoSamples (Proxy :: Proxy q)
541501
542502instance ToSample a => GToSample (K1 i a) where
543− gtoSamples _ = second K1 <$> toSamples (Proxy :: Proxy a)
503+ gtoSamples _ = second K1 <$> Omega.each (toSamples (Proxy :: Proxy a))
544504
545505instance (GToSample f) => GToSample (M1 i a f) where
546506 gtoSamples _ = second M1 <$> gtoSamples (Proxy :: Proxy f)
@@ -608,15 +568,6 @@ class ToCapture c where
608568class ToAuthInfo a where
609569 toAuthInfo :: Proxy a -> DocAuthentication
610570
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−
620571-- | Generate documentation in Markdown format for
621572-- the given 'API'.
622573--
@@ -646,7 +597,7 @@ markdown = markdownWith defRenderingOptions
646597--
647598-- @since 0.11.1
648599markdownWith :: RenderingOptions -> API -> String
649−markdownWith RenderingOptions{..} api = unlines $
600+markdownWith RenderingOptions{..} api = unlines $
650601 introsStr (api ^. apiIntros)
651602 ++ (concatMap (uncurry printEndpoint) . sort . HM.toList $ api ^. apiEndpoints)
652603
@@ -657,12 +608,10 @@ markdownWith RenderingOptions{..} api = unlines $
657608 notesStr (action ^. notes) ++
658609 authStr (action ^. authInfo) ++
659610 capturesStr (action ^. captures) ++
660− headersStr (toListOf (headers . each . _1 . to (T.pack . BSC.unpack . CI.original)) action) ++
611+ headersStr (action ^. headers) ++
661612 paramsStr meth (action ^. params) ++
662− fragmentStr (action ^. fragment) ++
663613 rqbodyStr (action ^. rqtypes) (action ^. rqbody) ++
664614 responseStr (action ^. response) ++
665− maybe [] (curlStr endpoint (action ^. headers) (action ^. rqbody)) _renderCurlBasePath ++
666615 []
667616
668617 where str = "## " ++ BSC.unpack meth
@@ -762,14 +711,6 @@ markdownWith RenderingOptions{..} api = unlines $
762711
763712 where values = param ^. paramValues
764713
765− fragmentStr :: Maybe DocFragment -> [String]
766− fragmentStr Nothing = []
767− fragmentStr (Just frag) =
768− [ "### Fragment:", ""
769− , "- *" ++ (frag ^. fragSymbol) ++ "*: " ++ (frag ^. fragDesc)
770− , ""
771− ]
772−
773714 rqbodyStr :: [M.MediaType] -> [(Text, M.MediaType, ByteString)]-> [String]
774715 rqbodyStr [] [] = []
775716 rqbodyStr types s =
@@ -818,11 +759,12 @@ markdownWith RenderingOptions{..} api = unlines $
818759 ("text", "css") -> "css"
819760 (_, _) -> ""
820761
762+
821763 contentStr mime_type body =
822764 "" :
823− "```" <> markdownForType mime_type :
765+ " ```" <> markdownForType mime_type :
824766 cs body :
825− "```" :
767+ " ```" :
826768 "" :
827769 []
828770
@@ -842,41 +784,11 @@ markdownWith RenderingOptions{..} api = unlines $
842784 xs ->
843785 formatBodies _responseExamples xs
844786
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−
875787-- * Instances
876788
877789-- | The generated docs for @a ':<|>' b@ just appends the docs
878790-- for @a@ with the docs for @b@.
879−instance {-# OVERLAPPABLE #-}
791+instance OVERLAPPABLE_
880792 (HasDocs a, HasDocs b)
881793 => HasDocs (a :<|> b) where
882794
@@ -895,7 +807,7 @@ instance HasDocs EmptyAPI where
895807-- | @"books" :> 'Capture' "isbn" Text@ will appear as
896808-- @/books/:isbn@ in the docs.
897809instance (KnownSymbol sym, ToCapture (Capture sym a), HasDocs api)
898− => HasDocs (Capture' '[] sym a :> api) where
810+ => HasDocs (Capture' mods sym a :> api) where
899811
900812 docsFor Proxy (endpoint, action) =
901813 docsFor subApiP (endpoint', action')
@@ -907,28 +819,6 @@ instance (KnownSymbol sym, ToCapture (Capture sym a), HasDocs api)
907819 endpoint' = over path (\p -> p ++ [":" ++ symbolVal symP]) endpoint
908820 symP = Proxy :: Proxy sym
909821
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−
932822
933823-- | @"books" :> 'CaptureAll' "isbn" Text@ will appear as
934824-- @/books/:isbn@ in the docs.
@@ -946,7 +836,7 @@ instance (KnownSymbol sym, ToCapture (CaptureAll sym a), HasDocs sublayout)
946836 symP = Proxy :: Proxy sym
947837
948838
949−instance {-# OVERLAPPABLE #-}
839+instance OVERLAPPABLE_
950840 (ToSample a, AllMimeRender (ct ': cts) a, KnownNat status
951841 , ReflectMethod method)
952842 => HasDocs (Verb method status (ct ': cts) a) where
@@ -962,25 +852,12 @@ instance {-# OVERLAPPABLE #-}
962852 status = fromInteger $ natVal (Proxy :: Proxy status)
963853 p = Proxy :: Proxy a
964854
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−
977855-- | TODO: mention the endpoint is streaming, its framing strategy
978856--
979857-- Also there are no samples.
980−--
981−-- TODO: AcceptFraming for content-type
982−instance {-# OVERLAPPABLE #-}
983− (Accept ct, KnownNat status, ReflectMethod method)
858+instance OVERLAPPABLE_
859+ (MimeRender ct a, KnownNat status
860+ , ReflectMethod method)
984861 => HasDocs (Stream method status framing ct a) where
985862 docsFor Proxy (endpoint, action) DocOptions{..} =
986863 single endpoint' action'
@@ -991,8 +868,9 @@ instance {-# OVERLAPPABLE #-}
991868 t = Proxy :: Proxy '[ct]
992869 method' = reflectMethod (Proxy :: Proxy method)
993870 status = fromInteger $ natVal (Proxy :: Proxy status)
871+ p = Proxy :: Proxy a
994872
995−instance {-# OVERLAPPING #-}
873+instance OVERLAPPING_
996874 (ToSample a, AllMimeRender (ct ': cts) a, KnownNat status
997875 , ReflectMethod method, AllHeaderSamples ls, GetHeaders (HList ls))
998876 => HasDocs (Verb method status (ct ': cts) (Headers ls a)) where
@@ -1010,17 +888,14 @@ instance {-# OVERLAPPING #-}
1010888 status = fromInteger $ natVal (Proxy :: Proxy status)
1011889 p = Proxy :: Proxy a
1012890
1013−instance (ToHttpApiData a, ToSample a, KnownSymbol sym, HasDocs api)
891+instance (KnownSymbol sym, HasDocs api)
1014892 => HasDocs (Header' mods sym a :> api) where
1015893 docsFor Proxy (endpoint, action) =
1016894 docsFor subApiP (endpoint, action')
1017895
1018896 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>"
897+ action' = over headers (|> headername) action
898+ headername = T.pack $ symbolVal (Proxy :: Proxy sym)
1024899
1025900instance (KnownSymbol sym, ToParam (QueryParam' mods sym a), HasDocs api)
1026901 => HasDocs (QueryParam' mods sym a :> api) where
@@ -1053,15 +928,6 @@ instance (KnownSymbol sym, ToParam (QueryFlag sym), HasDocs api)
1053928 paramP = Proxy :: Proxy (QueryFlag sym)
1054929 action' = over params (|> toParam paramP) action
1055930
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
1065931
1066932instance HasDocs Raw where
1067933 docsFor _proxy (endpoint, action) _ =
@@ -1094,6 +960,7 @@ instance (KnownSymbol desc, HasDocs api)
1094960-- both are even defined) for any particular type.
1095961instance (ToSample a, AllMimeRender (ct ': cts) a, HasDocs api)
1096962 => HasDocs (ReqBody' mods (ct ': cts) a :> api) where
963+
1097964 docsFor Proxy (endpoint, action) opts@DocOptions{..} =
1098965 docsFor subApiP (endpoint, action') opts
1099966
@@ -1104,18 +971,6 @@ instance (ToSample a, AllMimeRender (ct ': cts) a, HasDocs api)
1104971 t = Proxy :: Proxy (ct ': cts)
1105972 p = Proxy :: Proxy a
1106973
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−
1119974instance (KnownSymbol path, HasDocs api) => HasDocs (path :> api) where
1120975
1121976 docsFor Proxy (endpoint, action) =
@@ -1151,9 +1006,6 @@ instance (ToAuthInfo (BasicAuth realm usr), HasDocs api) => HasDocs (BasicAuth r
11511006 authProxy = Proxy :: Proxy (BasicAuth realm usr)
11521007 action' = over authInfo (|> toAuthInfo authProxy) action
11531008
1154−instance HasDocs (ToServantApi api) => HasDocs (NamedRoutes api) where
1155− docsFor Proxy = docsFor (Proxy :: Proxy (ToServantApi api))
1156−
11571009-- ToSample instances for simple types
11581010instance ToSample NoContent
11591011instance ToSample Bool
@@ -1170,7 +1022,6 @@ instance (ToSample a, ToSample b, ToSample c, ToSample d, ToSample e, ToSample f
11701022instance ToSample a => ToSample (Maybe a)
11711023instance (ToSample a, ToSample b) => ToSample (Either a b)
11721024instance ToSample a => ToSample [a]
1173−instance ToSample a => ToSample (NonEmpty a)
11741025
11751026-- ToSample instances for Control.Applicative types
11761027instance ToSample a => ToSample (Const a b)
@@ -1184,6 +1035,3 @@ instance ToSample a => ToSample (Product a)
11841035instance ToSample a => ToSample (First a)
11851036instance ToSample a => ToSample (Last a)
11861037instance ToSample a => ToSample (Dual a)
1187−
1188−-- $setup
1189−-- >>> :set -XOverloadedStrings