Skip to content

Commit 2a4efaa

Browse files
committed
Add TypeRep of api end-point to Foreign.Req.
1 parent d8a4cce commit 2a4efaa

File tree

3 files changed

+43
-21
lines changed

3 files changed

+43
-21
lines changed

servant-foreign/src/Servant/Foreign.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Servant.Foreign
2323
, reqBody
2424
, reqReturnType
2525
, reqFuncName
26+
, reqApiType
2627
, path
2728
, queryStr
2829
, queryArgName

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

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Control.Lens (makePrisms, makeLenses, Getter, (&), (<>~), (%~),
1313
import Data.Monoid
1414
#endif
1515
import Data.Proxy
16+
import Data.Typeable (Typeable, TypeRep, typeOf)
1617
import Data.String
1718
import Data.Text
1819
import Data.Text.Encoding (decodeUtf8)
@@ -125,6 +126,7 @@ data Req f = Req
125126
, _reqBody :: Maybe f
126127
, _reqReturnType :: Maybe f
127128
, _reqFuncName :: FunctionName
129+
, _reqApiType :: TypeRep
128130
}
129131

130132
deriving instance Eq f => Eq (Req f)
@@ -133,7 +135,7 @@ deriving instance Show f => Show (Req f)
133135
makeLenses ''Req
134136

135137
defReq :: Req ftype
136-
defReq = Req defUrl "GET" [] Nothing Nothing (FunctionName [])
138+
defReq = Req defUrl "GET" [] Nothing Nothing (FunctionName []) (typeOf ())
137139

138140
-- | To be used exclusively as a "negative" return type/constraint
139141
-- by @'Elem`@ type family.
@@ -196,81 +198,87 @@ instance (HasForeign lang ftype a, HasForeign lang ftype b)
196198
foreignFor lang ftype (Proxy :: Proxy a) req
197199
:<|> foreignFor lang ftype (Proxy :: Proxy b) req
198200

199-
instance (KnownSymbol sym, HasForeignType lang ftype t, HasForeign lang ftype sublayout)
201+
instance (KnownSymbol sym, HasForeignType lang ftype t, HasForeign lang ftype sublayout, Typeable (Capture sym t :> sublayout))
200202
=> HasForeign lang ftype (Capture sym t :> sublayout) where
201203
type Foreign ftype (Capture sym a :> sublayout) = Foreign ftype sublayout
202204

203205
foreignFor lang Proxy Proxy req =
204206
foreignFor lang Proxy (Proxy :: Proxy sublayout) $
205207
req & reqUrl . path <>~ [Segment (Cap arg)]
206208
& reqFuncName . _FunctionName %~ (++ ["by", str])
209+
& reqApiType .~ typeOf (undefined :: Capture sym t :> sublayout)
207210
where
208211
str = pack . symbolVal $ (Proxy :: Proxy sym)
209212
ftype = typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy t)
210213
arg = Arg
211214
{ _argName = PathSegment str
212215
, _argType = ftype }
213216

214-
instance (Elem JSON list, HasForeignType lang ftype a, ReflectMethod method)
217+
instance (Elem JSON list, HasForeignType lang ftype a, ReflectMethod method, Typeable (Verb method status list a))
215218
=> HasForeign lang ftype (Verb method status list a) where
216219
type Foreign ftype (Verb method status list a) = Req ftype
217220

218221
foreignFor lang Proxy Proxy req =
219222
req & reqFuncName . _FunctionName %~ (methodLC :)
220223
& reqMethod .~ method
221224
& reqReturnType .~ Just retType
225+
& reqApiType .~ typeOf (undefined :: Verb method status list a)
222226
where
223227
retType = typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy a)
224228
method = reflectMethod (Proxy :: Proxy method)
225229
methodLC = toLower $ decodeUtf8 method
226230

227-
instance (KnownSymbol sym, HasForeignType lang ftype a, HasForeign lang ftype sublayout)
231+
instance (KnownSymbol sym, HasForeignType lang ftype a, HasForeign lang ftype sublayout, Typeable (Header sym a :> sublayout))
228232
=> HasForeign lang ftype (Header sym a :> sublayout) where
229233
type Foreign ftype (Header sym a :> sublayout) = Foreign ftype sublayout
230234

231235
foreignFor lang Proxy Proxy req =
232236
foreignFor lang Proxy subP $ req & reqHeaders <>~ [HeaderArg arg]
237+
& reqApiType .~ typeOf (undefined :: Header sym a :> sublayout)
233238
where
234239
hname = pack . symbolVal $ (Proxy :: Proxy sym)
235240
arg = Arg
236241
{ _argName = PathSegment hname
237242
, _argType = typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy a) }
238243
subP = Proxy :: Proxy sublayout
239244

240-
instance (KnownSymbol sym, HasForeignType lang ftype a, HasForeign lang ftype sublayout)
245+
instance (KnownSymbol sym, HasForeignType lang ftype a, HasForeign lang ftype sublayout, Typeable (QueryParam sym a :> sublayout))
241246
=> HasForeign lang ftype (QueryParam sym a :> sublayout) where
242247
type Foreign ftype (QueryParam sym a :> sublayout) = Foreign ftype sublayout
243248

244249
foreignFor lang Proxy Proxy req =
245250
foreignFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy sublayout) $
246251
req & reqUrl.queryStr <>~ [QueryArg arg Normal]
252+
& reqApiType .~ typeOf (undefined :: QueryParam sym a :> sublayout)
247253
where
248254
str = pack . symbolVal $ (Proxy :: Proxy sym)
249255
arg = Arg
250256
{ _argName = PathSegment str
251257
, _argType = typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy a) }
252258

253259
instance
254-
(KnownSymbol sym, HasForeignType lang ftype [a], HasForeign lang ftype sublayout)
260+
(KnownSymbol sym, HasForeignType lang ftype [a], HasForeign lang ftype sublayout, Typeable (QueryParams sym a :> sublayout))
255261
=> HasForeign lang ftype (QueryParams sym a :> sublayout) where
256262
type Foreign ftype (QueryParams sym a :> sublayout) = Foreign ftype sublayout
257263
foreignFor lang Proxy Proxy req =
258264
foreignFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy sublayout) $
259265
req & reqUrl.queryStr <>~ [QueryArg arg List]
266+
& reqApiType .~ typeOf (undefined :: QueryParams sym a :> sublayout)
260267
where
261268
str = pack . symbolVal $ (Proxy :: Proxy sym)
262269
arg = Arg
263270
{ _argName = PathSegment str
264271
, _argType = typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy [a]) }
265272

266273
instance
267-
(KnownSymbol sym, HasForeignType lang ftype Bool, HasForeign lang ftype sublayout)
274+
(KnownSymbol sym, HasForeignType lang ftype Bool, HasForeign lang ftype sublayout, Typeable (QueryFlag sym :> sublayout))
268275
=> HasForeign lang ftype (QueryFlag sym :> sublayout) where
269276
type Foreign ftype (QueryFlag sym :> sublayout) = Foreign ftype sublayout
270277

271278
foreignFor lang ftype Proxy req =
272279
foreignFor lang ftype (Proxy :: Proxy sublayout) $
273280
req & reqUrl.queryStr <>~ [QueryArg arg Flag]
281+
& reqApiType .~ typeOf (undefined :: QueryFlag sym :> sublayout)
274282
where
275283
str = pack . symbolVal $ (Proxy :: Proxy sym)
276284
arg = Arg
@@ -283,61 +291,70 @@ instance HasForeign lang ftype Raw where
283291
foreignFor _ Proxy Proxy req method =
284292
req & reqFuncName . _FunctionName %~ ((toLower $ decodeUtf8 method) :)
285293
& reqMethod .~ method
294+
& reqApiType .~ typeOf (undefined :: Raw)
286295

287-
instance (Elem JSON list, HasForeignType lang ftype a, HasForeign lang ftype sublayout)
296+
instance (Elem JSON list, HasForeignType lang ftype a, HasForeign lang ftype sublayout, Typeable (ReqBody list a :> sublayout))
288297
=> HasForeign lang ftype (ReqBody list a :> sublayout) where
289298
type Foreign ftype (ReqBody list a :> sublayout) = Foreign ftype sublayout
290299

291300
foreignFor lang ftype Proxy req =
292301
foreignFor lang ftype (Proxy :: Proxy sublayout) $
293302
req & reqBody .~ (Just $ typeFor lang ftype (Proxy :: Proxy a))
303+
& reqApiType .~ typeOf (undefined :: ReqBody list a :> sublayout)
294304

295-
instance (KnownSymbol path, HasForeign lang ftype sublayout)
305+
instance (KnownSymbol path, HasForeign lang ftype sublayout, Typeable (path :> sublayout))
296306
=> HasForeign lang ftype (path :> sublayout) where
297307
type Foreign ftype (path :> sublayout) = Foreign ftype sublayout
298308

299309
foreignFor lang ftype Proxy req =
300310
foreignFor lang ftype (Proxy :: Proxy sublayout) $
301311
req & reqUrl . path <>~ [Segment (Static (PathSegment str))]
302312
& reqFuncName . _FunctionName %~ (++ [str])
313+
& reqApiType .~ typeOf (undefined :: path :> sublayout)
303314
where
304315
str =
305316
Data.Text.map (\c -> if c == '.' then '_' else c)
306317
. pack . symbolVal $ (Proxy :: Proxy path)
307318

308-
instance HasForeign lang ftype sublayout
319+
instance (HasForeign lang ftype sublayout, Typeable (RemoteHost :> sublayout))
309320
=> HasForeign lang ftype (RemoteHost :> sublayout) where
310321
type Foreign ftype (RemoteHost :> sublayout) = Foreign ftype sublayout
311322

312323
foreignFor lang ftype Proxy req =
313-
foreignFor lang ftype (Proxy :: Proxy sublayout) req
324+
foreignFor lang ftype (Proxy :: Proxy sublayout) $
325+
req & reqApiType .~ typeOf (undefined :: (RemoteHost :> sublayout))
314326

315-
instance HasForeign lang ftype sublayout
327+
instance (HasForeign lang ftype sublayout, Typeable (IsSecure :> sublayout))
316328
=> HasForeign lang ftype (IsSecure :> sublayout) where
317329
type Foreign ftype (IsSecure :> sublayout) = Foreign ftype sublayout
318330

319331
foreignFor lang ftype Proxy req =
320-
foreignFor lang ftype (Proxy :: Proxy sublayout) req
332+
foreignFor lang ftype (Proxy :: Proxy sublayout) $
333+
req & reqApiType .~ typeOf (undefined :: IsSecure :> sublayout)
321334

322-
instance HasForeign lang ftype sublayout => HasForeign lang ftype (Vault :> sublayout) where
335+
instance (HasForeign lang ftype sublayout, Typeable (Vault :> sublayout))
336+
=> HasForeign lang ftype (Vault :> sublayout) where
323337
type Foreign ftype (Vault :> sublayout) = Foreign ftype sublayout
324338

325339
foreignFor lang ftype Proxy req =
326-
foreignFor lang ftype (Proxy :: Proxy sublayout) req
340+
foreignFor lang ftype (Proxy :: Proxy sublayout) $
341+
req & reqApiType .~ typeOf (undefined :: Vault :> sublayout)
327342

328-
instance HasForeign lang ftype sublayout =>
329-
HasForeign lang ftype (WithNamedContext name context sublayout) where
343+
instance (HasForeign lang ftype sublayout, Typeable (WithNamedContext name context sublayout))
344+
=> HasForeign lang ftype (WithNamedContext name context sublayout) where
330345

331346
type Foreign ftype (WithNamedContext name context sublayout) = Foreign ftype sublayout
332347

333-
foreignFor lang ftype Proxy = foreignFor lang ftype (Proxy :: Proxy sublayout)
348+
foreignFor lang ftype Proxy req = foreignFor lang ftype (Proxy :: Proxy sublayout) $
349+
req & reqApiType .~ typeOf (undefined :: WithNamedContext name context sublayout)
334350

335-
instance HasForeign lang ftype sublayout
351+
instance (HasForeign lang ftype sublayout, Typeable (HttpVersion :> sublayout))
336352
=> HasForeign lang ftype (HttpVersion :> sublayout) where
337353
type Foreign ftype (HttpVersion :> sublayout) = Foreign ftype sublayout
338354

339355
foreignFor lang ftype Proxy req =
340-
foreignFor lang ftype (Proxy :: Proxy sublayout) req
356+
foreignFor lang ftype (Proxy :: Proxy sublayout) $
357+
req & reqApiType .~ typeOf (undefined :: HttpVersion :> sublayout)
341358

342359
-- | Utility class used by 'listFromAPI' which computes
343360
-- the data needed to generate a function for each endpoint

servant-js/src/Servant/JS/JQuery.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ generateJQueryJS = generateJQueryJSWith defCommonGeneratorOptions
2929
-- | js codegen using JQuery
3030
generateJQueryJSWith :: CommonGeneratorOptions -> AjaxReq -> Text
3131
generateJQueryJSWith opts req = "\n" <>
32-
fname <> " = function(" <> argsStr <> ")\n"
32+
jsdocs
33+
<> fname <> " = function(" <> argsStr <> ")\n"
3334
<> "{\n"
3435
<> " $.ajax(\n"
3536
<> " { url: " <> url <> "\n"
@@ -101,3 +102,6 @@ generateJQueryJSWith opts req = "\n" <>
101102
queryArgs = if null queryparams
102103
then ""
103104
else " + '?" <> jsParams queryparams
105+
106+
jsdocs :: Text
107+
jsdocs = "// " <> (T.pack .show $ req ^. reqApiType) <> "\n"

0 commit comments

Comments
 (0)