Skip to content

Commit 96ab0ee

Browse files
Add OperationId (#1844)
* Add `OperationId` * Update servant/src/Servant/API/Description.hs Co-authored-by: Clément Delafargue <[email protected]> --------- Co-authored-by: Clément Delafargue <[email protected]>
1 parent 10b5aea commit 96ab0ee

File tree

11 files changed

+90
-2
lines changed

11 files changed

+90
-2
lines changed

changelog.d/pr-1844

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
synopsis: Add support for `OperationId`
2+
packages: servant, servant-client, servant-docs, servant-server, servant-swagger
3+
prs: #1844
4+
issues: N/A
5+
description: {
6+
Add `OperationId`, which can direct code and docs generation.
7+
}

servant-client-core/src/Servant/Client/Core/HasClient.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import Servant.API
6666
, NamedRoutes
6767
, NoContent (NoContent)
6868
, NoContentVerb
69+
, OperationId
6970
, QueryFlag
7071
, QueryParam'
7172
, QueryParams
@@ -723,6 +724,14 @@ instance HasClient m api => HasClient m (Summary desc :> api) where
723724

724725
hoistClientMonad pm _ = hoistClientMonad pm (Proxy :: Proxy api)
725726

727+
-- | Ignore @'OperationId'@ in client functions.
728+
instance HasClient m api => HasClient m (OperationId operationId :> api) where
729+
type Client m (OperationId operationId :> api) = Client m api
730+
731+
clientWithRoute pm _ = clientWithRoute pm (Proxy :: Proxy api)
732+
733+
hoistClientMonad pm _ = hoistClientMonad pm (Proxy :: Proxy api)
734+
726735
-- | Ignore @'Description'@ in client functions.
727736
instance HasClient m api => HasClient m (Description desc :> api) where
728737
type Client m (Description desc :> api) = Client m api

servant-docs/golden/comprehensive.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,27 @@
304304

305305
## GET /named-context
306306

307+
### Response:
308+
309+
- Status code 200
310+
- Headers: []
311+
312+
- Supported content types are:
313+
314+
- `application/json;charset=utf-8`
315+
- `application/json`
316+
317+
- Example (`application/json;charset=utf-8`, `application/json`):
318+
319+
```json
320+
321+
```
322+
323+
## GET /operation-id
324+
325+
### OperationId: foo
326+
327+
307328
### Response:
308329

309330
- Status code 200

servant-docs/src/Servant/Docs/Internal.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,17 @@ instance
11811181
action' = over notes (|> note) action
11821182
note = DocNote (symbolVal (Proxy :: Proxy desc)) []
11831183

1184+
instance
1185+
(HasDocs api, KnownSymbol operationId)
1186+
=> HasDocs (OperationId operationId :> api)
1187+
where
1188+
docsFor Proxy (endpoint, action) =
1189+
docsFor subApiP (endpoint, action')
1190+
where
1191+
subApiP = Proxy :: Proxy api
1192+
action' = over notes (|> note) action
1193+
note = DocNote ("OperationId: " <> symbolVal (Proxy :: Proxy operationId)) []
1194+
11841195
-- TODO: We use 'AllMimeRender' here because we need to be able to show the
11851196
-- example data. However, there's no reason to believe that the instances of
11861197
-- 'AllMimeUnrender' and 'AllMimeRender' actually agree (or to suppose that

servant-foreign/src/Servant/Foreign/Internal.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,19 @@ instance
558558

559559
foreignFor lang ftype Proxy = foreignFor lang ftype (Proxy :: Proxy api)
560560

561+
instance
562+
(HasForeign lang ftype api, KnownSymbol operationId)
563+
=> HasForeign lang ftype (OperationId operationId :> api)
564+
where
565+
type Foreign ftype (OperationId operationId :> api) = Foreign ftype api
566+
567+
foreignFor lang ftype Proxy req =
568+
foreignFor lang ftype (Proxy :: Proxy api) $
569+
req
570+
& reqFuncName . _FunctionName .~ [str]
571+
where
572+
str = pack . symbolVal $ (Proxy :: Proxy operationId)
573+
561574
instance
562575
HasForeign lang ftype api
563576
=> HasForeign lang ftype (Description desc :> api)

servant-server/src/Servant/Server/Internal.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import Servant.API
8282
, IsSecure (..)
8383
, NamedRoutes
8484
, NoContentVerb
85+
, OperationId
8586
, QueryFlag
8687
, QueryParam'
8788
, QueryParams
@@ -1131,6 +1132,13 @@ instance HasServer api ctx => HasServer (Summary desc :> api) ctx where
11311132
route _ = route (Proxy :: Proxy api)
11321133
hoistServerWithContext _ = hoistServerWithContext (Proxy :: Proxy api)
11331134

1135+
-- | Ignore @'OperationId'@ in server handlers.
1136+
instance HasServer api ctx => HasServer (OperationId operationId :> api) ctx where
1137+
type ServerT (OperationId operationId :> api) m = ServerT api m
1138+
1139+
route _ = route (Proxy :: Proxy api)
1140+
hoistServerWithContext _ = hoistServerWithContext (Proxy :: Proxy api)
1141+
11341142
-- | Ignore @'Description'@ in server handlers.
11351143
instance HasServer api ctx => HasServer (Description desc :> api) ctx where
11361144
type ServerT (Description desc :> api) m = ServerT api m

servant-swagger/src/Servant/Swagger/Internal.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,11 @@ instance (HasSwagger api, KnownSymbol desc) => HasSwagger (Summary desc :> api)
389389
toSwagger (Proxy :: Proxy api)
390390
& allOperations . summary %~ (Just (Text.pack (symbolVal (Proxy :: Proxy desc))) <>)
391391

392+
instance (HasSwagger api, KnownSymbol operationId) => HasSwagger (OperationId operationId :> api) where
393+
toSwagger _ =
394+
toSwagger (Proxy :: Proxy api)
395+
& allOperations . operationId %~ (Just (Text.pack (symbolVal (Proxy :: Proxy operationId))) <>)
396+
392397
instance (HasSwagger sub, KnownSymbol (FoldDescription mods), KnownSymbol sym, SBoolI (FoldRequired mods), ToParamSchema a) => HasSwagger (QueryParam' mods sym a :> sub) where
393398
toSwagger _ =
394399
toSwagger (Proxy :: Proxy sub)

servant/src/Servant/API.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ import Servant.API.ContentTypes
105105
, OctetStream
106106
, PlainText
107107
)
108-
import Servant.API.Description (Description, Summary)
108+
import Servant.API.Description (Description, OperationId, Summary)
109109
import Servant.API.Empty (EmptyAPI (..))
110110
import Servant.API.Experimental.Auth (AuthProtect)
111111
import Servant.API.Fragment (Fragment)

servant/src/Servant/API/Description.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module Servant.API.Description
1111
( -- * Combinators
1212
Description
1313
, Summary
14+
, OperationId
1415

1516
-- * Used as modifiers
1617
, FoldDescription
@@ -47,6 +48,14 @@ data Summary (sym :: Symbol)
4748
data Description (sym :: Symbol)
4849
deriving (Typeable)
4950

51+
-- | Add an (unchecked) operation id for (part of) API, useful when generating bindings and OpenAPI docs.
52+
--
53+
-- Example:
54+
--
55+
-- >>> type MyApi = OperationId "getBookByISBN" :> "books" :> Capture "isbn" Text :> Get '[JSON] Book
56+
data OperationId (sym :: Symbol)
57+
deriving (Typeable)
58+
5059
-- | Fold list of modifiers to extract description as a type-level String.
5160
--
5261
-- >>> :kind! FoldDescription '[]

servant/src/Servant/Links.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ import Web.HttpApiData
139139
import Servant.API.Alternative ((:<|>) ((:<|>)))
140140
import Servant.API.BasicAuth (BasicAuth)
141141
import Servant.API.Capture (Capture', CaptureAll)
142-
import Servant.API.Description (Description, Summary)
142+
import Servant.API.Description (Description, OperationId, Summary)
143143
import Servant.API.Empty (EmptyAPI (..))
144144
import Servant.API.Experimental.Auth (AuthProtect)
145145
import Servant.API.Fragment (Fragment)
@@ -550,6 +550,10 @@ instance HasLink sub => HasLink (Summary s :> sub) where
550550
type MkLink (Summary s :> sub) a = MkLink sub a
551551
toLink = simpleToLink (Proxy :: Proxy sub)
552552

553+
instance HasLink sub => HasLink (OperationId s :> sub) where
554+
type MkLink (OperationId s :> sub) a = MkLink sub a
555+
toLink = simpleToLink (Proxy :: Proxy sub)
556+
553557
instance HasLink sub => HasLink (HttpVersion :> sub) where
554558
type MkLink (HttpVersion :> sub) a = MkLink sub a
555559
toLink = simpleToLink (Proxy :: Proxy sub)

0 commit comments

Comments
 (0)