@@ -45,6 +45,9 @@ verbAlias s n m = TypeDecl noLoc n [] alias
4545 where
4646 alias = foldr' (\l r -> TyInfix l (UnQual (sym ":>")) r) verb (path ++ qry)
4747
48+ -- FIXME: rather than using 'terminal' to get the terminal type,
49+ -- write a custom 'Link' for servant to specify required params.
50+
4851 path :: [Type]
4952 path = map match
5053 . filter (not . Text.null)
@@ -59,7 +62,7 @@ verbAlias s n m = TypeDecl noLoc n [] alias
5962 , _prmLocation k == Path
6063 = TyApp (TyApp (tycon "Capture")
6164 (sing (Text.init t)))
62− (external (_type (_prmSchema k)))
65+ (terminalType (_type (_prmSchema k)))
6366 | otherwise = sing x
6467
6568 -- FIXME: order by _mParameterOrder
@@ -67,11 +70,12 @@ verbAlias s n m = TypeDecl noLoc n [] alias
6770 qry = mapMaybe f (Map.toList params)
6871 where
6972 f (k, x) =
70− -- FIXME: types, many/repeated
71− let t = external (_type (_prmSchema x))
73+ let t = terminalType (_type (_prmSchema x))
7274 n = sing (local k)
7375 in case _prmLocation x of
7476 Query -> Just $ TyApp (TyApp (tycon "QueryParam") n) t
77+ Query | _prmRepeated x
78+ -> Just $ TyApp (TyApp (tycon "QueryParams") n) t
7579 Path -> Nothing
7680
7781 params = _mParameters m
@@ -83,6 +87,35 @@ verbAlias s n m = TypeDecl noLoc n [] alias
8387 typ = tycon "'[JSON]"
8488 res = maybe (tycon "()") (tycon . Free) (_mResponse m)
8589
90+requestDecl :: Id -> Pre -> [Local] -> Maybe Id -> Decl
91+requestDecl n p fs r =
92+ -- FIXME: associated Rs type
93+ InstDecl noLoc Nothing [] [] (unqual "GoogleRequest") [tycon n]
94+ [ response
95+ , request
96+ , requestWithRoute
97+ ]
98+ where
99+ response = InsType noLoc (TyApp (tycon "Rs") (tycon n)) $
100+ maybe unit_tycon tycon r
101+
102+ request = funD "request" $
103+ appFun (var "requestWithRoute") [var "defReq", var "serviceURL"]
104+
105+ requestWithRoute =
106+ InsDecl (FunBind [match "requestWithRoute" e])
107+ where
108+ e = appFun (var "clientWithRoute") $
109+ [ ExpTypeSig noLoc (var "Proxy") (TyApp (tycon "Proxy") (tycon n))
110+ , var "r"
111+ , var "u"
112+ ] ++ map (var . fname p) fs
113+
114+ match f e = Match noLoc (name f) pats Nothing (UnGuardedRhs e) noBinds
115+
116+ pats = [prec, pvar "r", pvar "u"]
117+ prec = PRec (UnQual (dname n)) [PFieldWildcard]
118+
86119jsonDecls :: Id -> Pre -> Map Local Solved -> [Decl]
87120jsonDecls n p (Map.toList -> rs) = [from, to]
88121 where
@@ -170,8 +203,8 @@ conDecl n p rs = QualConDecl noLoc [] [] body
170203 where
171204 body = case Map.toList rs of
172205 [] -> ConDecl n []
173− [x] -> RecDecl n [field internal x]
174− xs -> RecDecl n (map (field (strict . internal)) xs)
206+ [x] -> RecDecl n [field internalType x]
207+ xs -> RecDecl n (map (field (strict . internalType)) xs)
175208
176209 field f (l, v) = ([fname p l], f (_type v))
177210
@@ -206,7 +239,7 @@ fieldUpdate p l s = FieldUpdate (UnQual (fname p l)) rhs
206239lensSig :: Id -> Pre -> Local -> Solved -> Decl
207240lensSig n p l s = TypeSig noLoc [lname p l] $
208241 TyApp (TyApp (tycon "Lens'") (tycon n))
209− (external (_type s))
242+ (externalType (_type s))
210243
211244lensDecl :: Pre -> Local -> Solved -> Decl
212245lensDecl p l s = sfun noLoc (lname p l) [] (UnGuardedRhs rhs) noBinds
@@ -220,7 +253,7 @@ lensDecl p l s = sfun noLoc (lname p l) [] (UnGuardedRhs rhs) noBinds
220253 (RecUpdate (var "s") [FieldUpdate (UnQual f) (var "a")])))
221254
222255parameters :: [Solved] -> [Type]
223−parameters = map (external . _type) . filter (view required)
256+parameters = map (externalType . _type) . filter (view required)
224257
225258def :: Solved -> Maybe Exp
226259def s
@@ -236,20 +269,32 @@ def s
236269
237270 lit = var . name . Text.unpack
238271
239−external, internal :: TType -> Type
240−external = internal . \case
241− TMaybe t@TList {} -> t
242− t -> t
243−
244−internal = \case
272+terminalType :: TType -> Type
273+terminalType = internalType . go
274+ where
275+ go (TMaybe x) = x
276+ go (TList x) = x
277+ go x = x
278+
279+externalType :: TType -> Type
280+externalType = \case
281+ TType r -> tycon r
282+ TMaybe t@TList {} -> externalType t
283+ TMaybe t -> TyApp (tycon "Maybe") (externalType t)
284+ TEither a b -> TyApp (TyApp (tycon "Either") (externalType a)) (externalType b)
285+ TList t -> TyList (externalType t)
286+ TLit l -> externalLit l
287+
288+internalType :: TType -> Type
289+internalType = \case
245290 TType r -> tycon r
246− TMaybe t -> TyApp (tycon "Maybe") (internal t)
247− TEither a b -> TyApp (TyApp (tycon "Either") (internal a)) (internal b)
248− TList t -> TyList (internal t)
249− TLit l -> literal l
291+ TMaybe t -> TyApp (tycon "Maybe") (internalType t)
292+ TEither a b -> TyApp (TyApp (tycon "Either") (internalType a)) (internalType b)
293+ TList t -> TyList (internalType t)
294+ TLit l -> internalLit l
250295
251−literal :: Lit -> Type
252−literal = \case
296+externalLit :: Lit -> Type
297+externalLit = \case
253298 Text -> tycon "Text"
254299 Bool -> tycon "Bool"
255300 Time -> tycon "UTCTime"
@@ -263,6 +308,21 @@ literal = \case
263308 Int32 -> tycon "Int32"
264309 Int64 -> tycon "Int64"
265310
311+internalLit :: Lit -> Type
312+internalLit = \case
313+ Text -> tycon "Text"
314+ Bool -> tycon "Bool"
315+ Time -> tycon "UTCTime"
316+ Date -> tycon "UTCTime"
317+ Nat -> tycon "Nat"
318+ Float -> tycon "Float"
319+ Double -> tycon "Double"
320+ Byte -> tycon "Word8"
321+ UInt32 -> tycon "Word32"
322+ UInt64 -> tycon "Word64"
323+ Int32 -> tycon "Int32"
324+ Int64 -> tycon "Int64"
325+
266326mapping :: TType -> Exp -> Exp
267327mapping t e = infixE e "." (go t)
268328 where
@@ -277,6 +337,7 @@ mapping t e = infixE e "." (go t)
277337iso :: TType -> Maybe Exp
278338iso = \case
279339 TList {} -> Just (var "_Coerce")
340+ TLit Nat -> Just (var "_Nat")
280341 _ -> Nothing
281342
282343strict :: Type -> Type