haskell-servant / servant-elm

Automatically derive Elm functions to query servant webservices
BSD 3-Clause "New" or "Revised" License
164 stars 48 forks source link

Support for named routes in servant #71

Closed guaraqe closed 8 months ago

guaraqe commented 1 year ago

Are there plans to add support for named routes in servant?

It would be really nice, since the name of the generated functions could be defined by the developers, and functions corresponding to the same route would have the same name in both Haskell and Elm.

ilyakooo0 commented 1 year ago

An obvious issue is that records fields can have duplicate names accross different modules. This would mean that we would still need to speciy the path (possibly of other names) in the names of the generated functions.

ilyakooo0 commented 1 year ago

This is also blocked by servant-foreign not supporting this, so you should probably create an issue there.

guaraqe commented 1 year ago

I see, thanks, I created an issue there: https://github.com/haskell-servant/servant/issues/1673

TheOddler commented 1 year ago

Looks like in the latest version of servant.foreign (0.16 as of writing) there is now support for this, though it still just uses the generated names (which tbh I'm fine with).

Version 0.16 isn't part of any stack lts yet though, so what I did was copy this into my code:

-- Taken from https://hackage.haskell.org/package/servant-foreign-0.16/docs/src/Servant.Foreign.Internal.html#line-518
-- But that is only available on servant-foreign 0.16, which is not in any stackage lts yet
instance HasForeign lang ftype (ToServantApi r) => HasForeign lang ftype (NamedRoutes r) where
  type Foreign ftype (NamedRoutes r) = Foreign ftype (ToServantApi r)

  foreignFor lang ftype Proxy req =
    foreignFor lang ftype (Proxy :: Proxy (ToServantApi r)) req

And then updated my generateElmModuleWith ... to:

  generateElmModuleWith
    ...
    (Proxy :: Proxy (ToServantApi Web.ApiRoutes))

(Added the ToServantApi there too essentially).

blackheaven commented 1 year ago

I'm not sure I get it, I have this error:

    • Expected kind ‘Type -> Type’, but ‘API’ has kind ‘Type’
    • In the first argument of ‘ToServantApi’, namely ‘API’
      In the first argument of ‘Proxy’, namely ‘(ToServantApi API)’
      In an expression type signature: Proxy (ToServantApi API)
   |
42 |     (Proxy :: Proxy (ToServantApi API))
   |                                   ^^^

Any idea what's going on?

TheOddler commented 1 year ago

My guess is that you're missing the mode parameter on you API? My ApiRoutes looks like this:

data ApiRoutes mode = ApiRoutes
  { ping :: mode :- "ping" :> Get '[JSON] String,
    ...
  }
  deriving (Generic)

I also have type Api = NamedRoutes ApiRoutes but that's not the one I used ToServantApi on.

blackheaven commented 1 year ago

Sorry for that, thanks a lot!

domenkozar commented 8 months ago

This is fixed