git.iko.soy/typeable/servant
on master help sign in
Added lang parameter.
69f09f2Maksymilian Owsianny
servant-foreign/src/Servant/Foreign/Internal.hs+73−69
@@ -122,144 +122,148 @@ type family Elem (a :: *) (ls::[*]) :: Constraint where
122 Elem a (a ': list) = ()
122 Elem a (a ': list) = ()
123 Elem a (b ': list) = Elem a list
123 Elem a (b ': list) = Elem a list
124
124
125−class HasForeignType a where
125+class HasForeignType lang a where
126− typeFor :: Proxy a -> ForeignType
126+ typeFor :: Proxy lang -> Proxy a -> ForeignType
127
127
128−class HasForeign (layout :: *) where
128+class HasForeign lang (layout :: *) where
129 type Foreign layout :: *
129 type Foreign layout :: *
130− foreignFor :: Proxy layout -> Req -> Foreign layout
130+ foreignFor :: Proxy lang -> Proxy layout -> Req -> Foreign layout
131
131
132−instance (HasForeign a, HasForeign b)
132+instance (HasForeign lang a, HasForeign lang b)
133− => HasForeign (a :<|> b) where
133+ => HasForeign lang (a :<|> b) where
134 type Foreign (a :<|> b) = Foreign a :<|> Foreign b
134 type Foreign (a :<|> b) = Foreign a :<|> Foreign b
135
135
136− foreignFor Proxy req =
136+ foreignFor lang Proxy req =
137− foreignFor (Proxy :: Proxy a) req
137+ foreignFor lang (Proxy :: Proxy a) req
138− :<|> foreignFor (Proxy :: Proxy b) req
138+ :<|> foreignFor lang (Proxy :: Proxy b) req
139
139
140−instance (KnownSymbol sym, HasForeignType a, HasForeign sublayout)
140+instance (KnownSymbol sym, HasForeignType lang a, HasForeign lang sublayout)
141− => HasForeign (Capture sym a :> sublayout) where
141+ => HasForeign lang (Capture sym a :> sublayout) where
142 type Foreign (Capture sym a :> sublayout) = Foreign sublayout
142 type Foreign (Capture sym a :> sublayout) = Foreign sublayout
143
143
144− foreignFor Proxy req =
144+ foreignFor lang Proxy req =
145− foreignFor (Proxy :: Proxy sublayout) $
145+ foreignFor lang (Proxy :: Proxy sublayout) $
146 req & reqUrl.path <>~ [Segment (Cap arg)]
146 req & reqUrl.path <>~ [Segment (Cap arg)]
147 & funcName %~ (++ ["by", str])
147 & funcName %~ (++ ["by", str])
148
148
149 where
149 where
150 str = pack . symbolVal $ (Proxy :: Proxy sym)
150 str = pack . symbolVal $ (Proxy :: Proxy sym)
151− arg = (str, typeFor (Proxy :: Proxy a))
151+ arg = (str, typeFor lang (Proxy :: Proxy a))
152
152
153−instance (Elem JSON list, HasForeignType a) => HasForeign (Delete list a) where
153+instance (Elem JSON list, HasForeignType lang a)
154+ => HasForeign lang (Delete list a) where
154 type Foreign (Delete list a) = Req
155 type Foreign (Delete list a) = Req
155
156
156− foreignFor Proxy req =
157+ foreignFor lang Proxy req =
157 req & funcName %~ ("delete" :)
158 req & funcName %~ ("delete" :)
158 & reqMethod .~ "DELETE"
159 & reqMethod .~ "DELETE"
159 & reqReturnType .~ retType
160 & reqReturnType .~ retType
160 where
161 where
161− retType = typeFor (Proxy :: Proxy a)
162+ retType = typeFor lang (Proxy :: Proxy a)
162
163
163−instance (Elem JSON list, HasForeignType a) => HasForeign (Get list a) where
164+instance (Elem JSON list, HasForeignType lang a)
165+ => HasForeign lang (Get list a) where
164 type Foreign (Get list a) = Req
166 type Foreign (Get list a) = Req
165
167
166− foreignFor Proxy req =
168+ foreignFor lang Proxy req =
167 req & funcName %~ ("get" :)
169 req & funcName %~ ("get" :)
168 & reqMethod .~ "GET"
170 & reqMethod .~ "GET"
169 & reqReturnType .~ retType
171 & reqReturnType .~ retType
170 where
172 where
171− retType = typeFor (Proxy :: Proxy a)
173+ retType = typeFor lang (Proxy :: Proxy a)
172
174
173−instance (KnownSymbol sym, HasForeignType a, HasForeign sublayout)
175+instance (KnownSymbol sym, HasForeignType lang a, HasForeign lang sublayout)
174− => HasForeign (Header sym a :> sublayout) where
176+ => HasForeign lang (Header sym a :> sublayout) where
175 type Foreign (Header sym a :> sublayout) = Foreign sublayout
177 type Foreign (Header sym a :> sublayout) = Foreign sublayout
176
178
177− foreignFor Proxy req =
179+ foreignFor lang Proxy req =
178− foreignFor subP $ req
180+ foreignFor lang subP $ req
179 & reqHeaders <>~ [HeaderArg arg]
181 & reqHeaders <>~ [HeaderArg arg]
180
182
181 where
183 where
182 hname = pack . symbolVal $ (Proxy :: Proxy sym)
184 hname = pack . symbolVal $ (Proxy :: Proxy sym)
183− arg = (hname, typeFor (Proxy :: Proxy a))
185+ arg = (hname, typeFor lang (Proxy :: Proxy a))
184 subP = Proxy :: Proxy sublayout
186 subP = Proxy :: Proxy sublayout
185
187
186−instance (Elem JSON list, HasForeignType a) => HasForeign (Post list a) where
188+instance (Elem JSON list, HasForeignType lang a)
189+ => HasForeign lang (Post list a) where
187 type Foreign (Post list a) = Req
190 type Foreign (Post list a) = Req
188
191
189− foreignFor Proxy req =
192+ foreignFor lang Proxy req =
190 req & funcName %~ ("post" :)
193 req & funcName %~ ("post" :)
191 & reqMethod .~ "POST"
194 & reqMethod .~ "POST"
192 & reqReturnType .~ retType
195 & reqReturnType .~ retType
193 where
196 where
194− retType = typeFor (Proxy :: Proxy a)
197+ retType = typeFor lang (Proxy :: Proxy a)
195
198
196−instance (Elem JSON list, HasForeignType a) => HasForeign (Put list a) where
199+instance (Elem JSON list, HasForeignType lang a)
200+ => HasForeign lang (Put list a) where
197 type Foreign (Put list a) = Req
201 type Foreign (Put list a) = Req
198
202
199− foreignFor Proxy req =
203+ foreignFor lang Proxy req =
200 req & funcName %~ ("put" :)
204 req & funcName %~ ("put" :)
201 & reqMethod .~ "PUT"
205 & reqMethod .~ "PUT"
202 & reqReturnType .~ retType
206 & reqReturnType .~ retType
203 where
207 where
204− retType = typeFor (Proxy :: Proxy a)
208+ retType = typeFor lang (Proxy :: Proxy a)
205
209
206−instance (KnownSymbol sym, HasForeignType a, HasForeign sublayout)
210+instance (KnownSymbol sym, HasForeignType lang a, HasForeign lang sublayout)
207− => HasForeign (QueryParam sym a :> sublayout) where
211+ => HasForeign lang (QueryParam sym a :> sublayout) where
208 type Foreign (QueryParam sym a :> sublayout) = Foreign sublayout
212 type Foreign (QueryParam sym a :> sublayout) = Foreign sublayout
209
213
210− foreignFor Proxy req =
214+ foreignFor lang Proxy req =
211− foreignFor (Proxy :: Proxy sublayout) $
215+ foreignFor lang (Proxy :: Proxy sublayout) $
212 req & reqUrl.queryStr <>~ [QueryArg arg Normal]
216 req & reqUrl.queryStr <>~ [QueryArg arg Normal]
213
217
214 where
218 where
215 str = pack . symbolVal $ (Proxy :: Proxy sym)
219 str = pack . symbolVal $ (Proxy :: Proxy sym)
216− arg = (str, typeFor (Proxy :: Proxy a))
220+ arg = (str, typeFor lang (Proxy :: Proxy a))
217
221
218−instance (KnownSymbol sym, HasForeignType a, HasForeign sublayout)
222+instance (KnownSymbol sym, HasForeignType lang a, HasForeign lang sublayout)
219− => HasForeign (QueryParams sym a :> sublayout) where
223+ => HasForeign lang (QueryParams sym a :> sublayout) where
220 type Foreign (QueryParams sym a :> sublayout) = Foreign sublayout
224 type Foreign (QueryParams sym a :> sublayout) = Foreign sublayout
221
225
222− foreignFor Proxy req =
226+ foreignFor lang Proxy req =
223− foreignFor (Proxy :: Proxy sublayout) $
227+ foreignFor lang (Proxy :: Proxy sublayout) $
224 req & reqUrl.queryStr <>~ [QueryArg arg List]
228 req & reqUrl.queryStr <>~ [QueryArg arg List]
225
229
226 where
230 where
227 str = pack . symbolVal $ (Proxy :: Proxy sym)
231 str = pack . symbolVal $ (Proxy :: Proxy sym)
228− arg = (str, typeFor (Proxy :: Proxy a))
232+ arg = (str, typeFor lang (Proxy :: Proxy a))
229
233
230−instance (KnownSymbol sym, HasForeignType a, a ~ Bool, HasForeign sublayout)
234+instance (KnownSymbol sym, HasForeignType lang a, a ~ Bool, HasForeign lang sublayout)
231− => HasForeign (QueryFlag sym :> sublayout) where
235+ => HasForeign lang (QueryFlag sym :> sublayout) where
232 type Foreign (QueryFlag sym :> sublayout) = Foreign sublayout
236 type Foreign (QueryFlag sym :> sublayout) = Foreign sublayout
233
237
234− foreignFor Proxy req =
238+ foreignFor lang Proxy req =
235− foreignFor (Proxy :: Proxy sublayout) $
239+ foreignFor lang (Proxy :: Proxy sublayout) $
236 req & reqUrl.queryStr <>~ [QueryArg arg Flag]
240 req & reqUrl.queryStr <>~ [QueryArg arg Flag]
237
241
238 where
242 where
239 str = pack . symbolVal $ (Proxy :: Proxy sym)
243 str = pack . symbolVal $ (Proxy :: Proxy sym)
240− arg = (str, typeFor (Proxy :: Proxy a))
244+ arg = (str, typeFor lang (Proxy :: Proxy a))
241
245
242−instance HasForeign Raw where
246+instance HasForeign lang Raw where
243 type Foreign Raw = Method -> Req
247 type Foreign Raw = Method -> Req
244
248
245− foreignFor Proxy req method =
249+ foreignFor _ Proxy req method =
246 req & funcName %~ ((toLower method) :)
250 req & funcName %~ ((toLower method) :)
247 & reqMethod .~ method
251 & reqMethod .~ method
248
252
249−instance (Elem JSON list, HasForeignType a, HasForeign sublayout)
253+instance (Elem JSON list, HasForeignType lang a, HasForeign lang sublayout)
250− => HasForeign (ReqBody list a :> sublayout) where
254+ => HasForeign lang (ReqBody list a :> sublayout) where
251 type Foreign (ReqBody list a :> sublayout) = Foreign sublayout
255 type Foreign (ReqBody list a :> sublayout) = Foreign sublayout
252
256
253− foreignFor Proxy req =
257+ foreignFor lang Proxy req =
254− foreignFor (Proxy :: Proxy sublayout) $
258+ foreignFor lang (Proxy :: Proxy sublayout) $
255− req & reqBody .~ (Just $ typeFor (Proxy :: Proxy a))
259+ req & reqBody .~ (Just $ typeFor lang (Proxy :: Proxy a))
256
260
257−instance (KnownSymbol path, HasForeign sublayout)
261+instance (KnownSymbol path, HasForeign lang sublayout)
258− => HasForeign (path :> sublayout) where
262+ => HasForeign lang (path :> sublayout) where
259 type Foreign (path :> sublayout) = Foreign sublayout
263 type Foreign (path :> sublayout) = Foreign sublayout
260
264
261− foreignFor Proxy req =
265+ foreignFor lang Proxy req =
262− foreignFor (Proxy :: Proxy sublayout) $
266+ foreignFor lang (Proxy :: Proxy sublayout) $
263 req & reqUrl.path <>~ [Segment (Static str)]
267 req & reqUrl.path <>~ [Segment (Static str)]
264 & funcName %~ (++ [str])
268 & funcName %~ (++ [str])
265
269
@@ -267,26 +271,26 @@ instance (KnownSymbol path, HasForeign sublayout)
267 str = Data.Text.map (\c -> if c == '.' then '_' else c)
271 str = Data.Text.map (\c -> if c == '.' then '_' else c)
268 . pack . symbolVal $ (Proxy :: Proxy path)
272 . pack . symbolVal $ (Proxy :: Proxy path)
269
273
270−instance HasForeign sublayout => HasForeign (RemoteHost :> sublayout) where
274+instance HasForeign lang sublayout => HasForeign lang (RemoteHost :> sublayout) where
271 type Foreign (RemoteHost :> sublayout) = Foreign sublayout
275 type Foreign (RemoteHost :> sublayout) = Foreign sublayout
272
276
273− foreignFor Proxy req =
277+ foreignFor lang Proxy req =
274− foreignFor (Proxy :: Proxy sublayout) req
278+ foreignFor lang (Proxy :: Proxy sublayout) req
275
279
276−instance HasForeign sublayout => HasForeign (IsSecure :> sublayout) where
280+instance HasForeign lang sublayout => HasForeign lang (IsSecure :> sublayout) where
277 type Foreign (IsSecure :> sublayout) = Foreign sublayout
281 type Foreign (IsSecure :> sublayout) = Foreign sublayout
278
282
279− foreignFor Proxy req =
283+ foreignFor lang Proxy req =
280− foreignFor (Proxy :: Proxy sublayout) req
284+ foreignFor lang (Proxy :: Proxy sublayout) req
281
285
282−instance HasForeign sublayout => HasForeign (Vault :> sublayout) where
286+instance HasForeign lang sublayout => HasForeign lang (Vault :> sublayout) where
283 type Foreign (Vault :> sublayout) = Foreign sublayout
287 type Foreign (Vault :> sublayout) = Foreign sublayout
284
288
285− foreignFor Proxy req =
289+ foreignFor lang Proxy req =
286− foreignFor (Proxy :: Proxy sublayout) req
290+ foreignFor lang (Proxy :: Proxy sublayout) req
287
291
288−instance HasForeign sublayout => HasForeign (HttpVersion :> sublayout) where
292+instance HasForeign lang sublayout => HasForeign lang (HttpVersion :> sublayout) where
289 type Foreign (HttpVersion :> sublayout) = Foreign sublayout
293 type Foreign (HttpVersion :> sublayout) = Foreign sublayout
290
294
291− foreignFor Proxy req =
295+ foreignFor lang Proxy req =
292− foreignFor (Proxy :: Proxy sublayout) req
296+ foreignFor lang (Proxy :: Proxy sublayout) req
servant-js/src/Servant/JS.hs+11−7
@@ -2,6 +2,7 @@
2{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE TypeOperators #-}
5+{-# LANGUAGE MultiParamTypeClasses #-}
5-----------------------------------------------------------------------------
6-----------------------------------------------------------------------------
6-- |
7-- |
7-- Module : Servant.JS
8-- Module : Servant.JS
@@ -122,16 +123,19 @@ import Servant.JS.Internal
122import Servant.JS.JQuery
123import Servant.JS.JQuery
123import Servant.JS.Vanilla
124import Servant.JS.Vanilla
124
125
126+-- Dummy type specifying target language
127+data LangJS
128+
125-- | Generate the data necessary to generate javascript code
129-- | Generate the data necessary to generate javascript code
126-- for all the endpoints of an API, as ':<|>'-separated values
130-- for all the endpoints of an API, as ':<|>'-separated values
127-- of type 'AjaxReq'.
131-- of type 'AjaxReq'.
128−javascript :: HasForeign layout => Proxy layout -> Foreign layout
132+javascript :: HasForeign LangJS layout => Proxy layout -> Foreign layout
129−javascript p = foreignFor p defReq
133+javascript p = foreignFor (Proxy :: Proxy LangJS) p defReq
130
134
131-- | Directly generate all the javascript functions for your API
135-- | Directly generate all the javascript functions for your API
132-- from a 'Proxy' for your API type. You can then write it to
136-- from a 'Proxy' for your API type. You can then write it to
133-- a file or integrate it in a page, for example.
137-- a file or integrate it in a page, for example.
134−jsForAPI :: (HasForeign api, GenerateList (Foreign api))
138+jsForAPI :: (HasForeign LangJS api, GenerateList (Foreign api))
135 => Proxy api -- ^ proxy for your API type
139 => Proxy api -- ^ proxy for your API type
136 -> JavaScriptGenerator -- ^ js code generator to use (angular, vanilla js, jquery, others)
140 -> JavaScriptGenerator -- ^ js code generator to use (angular, vanilla js, jquery, others)
137 -> Text -- ^ a text that you can embed in your pages or write to a file
141 -> Text -- ^ a text that you can embed in your pages or write to a file
@@ -140,7 +144,7 @@ jsForAPI p gen = gen (listFromAPI p)
140-- | Directly generate all the javascript functions for your API
144-- | Directly generate all the javascript functions for your API
141-- from a 'Proxy' for your API type using the given generator
145-- from a 'Proxy' for your API type using the given generator
142-- and write the resulting code to a file at the given path.
146-- and write the resulting code to a file at the given path.
143−writeJSForAPI :: (HasForeign api, GenerateList (Foreign api))
147+writeJSForAPI :: (HasForeign LangJS api, GenerateList (Foreign api))
144 => Proxy api -- ^ proxy for your API type
148 => Proxy api -- ^ proxy for your API type
145 -> JavaScriptGenerator -- ^ js code generator to use (angular, vanilla js, jquery, others)
149 -> JavaScriptGenerator -- ^ js code generator to use (angular, vanilla js, jquery, others)
146 -> FilePath -- ^ path to the file you want to write the resulting javascript code into
150 -> FilePath -- ^ path to the file you want to write the resulting javascript code into
@@ -148,8 +152,8 @@ writeJSForAPI :: (HasForeign api, GenerateList (Foreign api))
148writeJSForAPI p gen fp = writeFile fp (jsForAPI p gen)
152writeJSForAPI p gen fp = writeFile fp (jsForAPI p gen)
149
153
150-- A catch all instance since JavaScript has no types.
154-- A catch all instance since JavaScript has no types.
151−instance HasForeignType a where
155+instance HasForeignType LangJS a where
152− typeFor _ = empty
156+ typeFor _ _ = empty
153
157
154-- | Utility class used by 'jsForAPI' which computes
158-- | Utility class used by 'jsForAPI' which computes
155-- the data needed to generate a function for each endpoint
159-- the data needed to generate a function for each endpoint
@@ -165,6 +169,6 @@ instance (GenerateList start, GenerateList rest) => GenerateList (start :<|> res
165
169
166-- | Generate the necessary data for JS codegen as a list, each 'AjaxReq'
170-- | Generate the necessary data for JS codegen as a list, each 'AjaxReq'
167-- describing one endpoint from your API type.
171-- describing one endpoint from your API type.
168−listFromAPI :: (HasForeign api, GenerateList (Foreign api)) => Proxy api -> [AjaxReq]
172+listFromAPI :: (HasForeign LangJS api, GenerateList (Foreign api)) => Proxy api -> [AjaxReq]
169listFromAPI p = generateList (javascript p)
173listFromAPI p = generateList (javascript p)
170
174
servant-js/test/Servant/JSSpec/CustomHeaders.hs+10−9
@@ -6,6 +6,7 @@
6{-# LANGUAGE TypeFamilies #-}
6{-# LANGUAGE TypeFamilies #-}
7{-# LANGUAGE TypeOperators #-}
7{-# LANGUAGE TypeOperators #-}
8{-# LANGUAGE OverloadedStrings #-}
8{-# LANGUAGE OverloadedStrings #-}
9+{-# LANGUAGE MultiParamTypeClasses #-}
9
10
10module Servant.JSSpec.CustomHeaders where
11module Servant.JSSpec.CustomHeaders where
11
12
@@ -21,11 +22,11 @@ import Servant.JS.Internal
21-- using -- Basic, Digest, whatever.
22-- using -- Basic, Digest, whatever.
22data Authorization (sym :: Symbol) a
23data Authorization (sym :: Symbol) a
23
24
24−instance (KnownSymbol sym, HasForeign sublayout)
25+instance (KnownSymbol sym, HasForeign lang sublayout)
25− => HasForeign (Authorization sym a :> sublayout) where
26+ => HasForeign lang (Authorization sym a :> sublayout) where
26 type Foreign (Authorization sym a :> sublayout) = Foreign sublayout
27 type Foreign (Authorization sym a :> sublayout) = Foreign sublayout
27
28
28− foreignFor Proxy req = foreignFor (Proxy :: Proxy sublayout) $
29+ foreignFor lang Proxy req = foreignFor lang (Proxy :: Proxy sublayout) $
29 req & reqHeaders <>~ [ ReplaceHeaderArg ("Authorization", "") $
30 req & reqHeaders <>~ [ ReplaceHeaderArg ("Authorization", "") $
30 tokenType (pack . symbolVal $ (Proxy :: Proxy sym)) ]
31 tokenType (pack . symbolVal $ (Proxy :: Proxy sym)) ]
31 where
32 where
@@ -34,11 +35,11 @@ instance (KnownSymbol sym, HasForeign sublayout)
34-- | This is a combinator that fetches an X-MyLovelyHorse header.
35-- | This is a combinator that fetches an X-MyLovelyHorse header.
35data MyLovelyHorse a
36data MyLovelyHorse a
36
37
37−instance (HasForeign sublayout)
38+instance (HasForeign lang sublayout)
38− => HasForeign (MyLovelyHorse a :> sublayout) where
39+ => HasForeign lang (MyLovelyHorse a :> sublayout) where
39 type Foreign (MyLovelyHorse a :> sublayout) = Foreign sublayout
40 type Foreign (MyLovelyHorse a :> sublayout) = Foreign sublayout
40
41
41− foreignFor Proxy req = foreignFor (Proxy :: Proxy sublayout) $
42+ foreignFor lang Proxy req = foreignFor lang (Proxy :: Proxy sublayout) $
42 req & reqHeaders <>~ [ ReplaceHeaderArg ("X-MyLovelyHorse", "") tpl ]
43 req & reqHeaders <>~ [ ReplaceHeaderArg ("X-MyLovelyHorse", "") tpl ]
43 where
44 where
44 tpl = "I am good friends with {X-MyLovelyHorse}"
45 tpl = "I am good friends with {X-MyLovelyHorse}"
@@ -46,11 +47,11 @@ instance (HasForeign sublayout)
46-- | This is a combinator that fetches an X-WhatsForDinner header.
47-- | This is a combinator that fetches an X-WhatsForDinner header.
47data WhatsForDinner a
48data WhatsForDinner a
48
49
49−instance (HasForeign sublayout)
50+instance (HasForeign lang sublayout)
50− => HasForeign (WhatsForDinner a :> sublayout) where
51+ => HasForeign lang (WhatsForDinner a :> sublayout) where
51 type Foreign (WhatsForDinner a :> sublayout) = Foreign sublayout
52 type Foreign (WhatsForDinner a :> sublayout) = Foreign sublayout
52
53
53− foreignFor Proxy req = foreignFor (Proxy :: Proxy sublayout) $
54+ foreignFor lang Proxy req = foreignFor lang (Proxy :: Proxy sublayout) $
54 req & reqHeaders <>~ [ ReplaceHeaderArg ("X-WhatsForDinner", "") tpl ]
55 req & reqHeaders <>~ [ ReplaceHeaderArg ("X-WhatsForDinner", "") tpl ]
55 where
56 where
56 tpl = "I would like {X-WhatsForDinner} with a cherry on top."
57 tpl = "I would like {X-WhatsForDinner} with a cherry on top."