@@ -84,6 +84,7 @@ module Servant.Utils.Links (
8484 --
8585 -- | Note that 'URI' is from the "Network.URI" module in the @network-uri@ package.
8686 safeLink
87+ , allLinks
8788 , URI(..)
8889 -- * Adding custom types
8990 , HasLink(..)
@@ -108,6 +109,7 @@ import Prelude ()
108109import Prelude.Compat
109110
110111import Web.HttpApiData
112+import Servant.API.Alternative ( (:<|>)((:<|>)) )
111113import Servant.API.BasicAuth ( BasicAuth )
112114import Servant.API.Capture ( Capture, CaptureAll )
113115import Servant.API.ReqBody ( ReqBody )
@@ -220,6 +222,30 @@ safeLink
220222 -> MkLink endpoint
221223safeLink _ endpoint = toLink endpoint (Link mempty mempty)
222224
225+-- | Create all links in an API.
226+--
227+-- Note that the @api@ type must be restricted to the endpoints that have
228+-- valid links to them.
229+--
230+-- >>> type API = "foo" :> Capture "name" Text :> Get '[JSON] Text :<|> "bar" :> Capture "name" Int :> Get '[JSON] Double
231+-- >>> let fooLink :<|> barLink = allLinks (Proxy :: Proxy API)
232+-- >>> :t fooLink
233+-- fooLink :: Text -> Link
234+-- >>> :t barLink
235+-- barLink :: Int -> Link
236+--
237+-- Note: nested APIs don't work well with this approach
238+--
239+-- >>> :kind! MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double))
240+-- MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double)) :: *
241+-- = Char -> (Int -> Link) :<|> (Double -> Link)
242+--
243+allLinks
244+ :: forall api. HasLink api
245+ => Proxy api
246+ -> MkLink api
247+allLinks api = toLink api (Link mempty mempty)
248+
223249-- | Construct a toLink for an endpoint.
224250class HasLink endpoint where
225251 type MkLink endpoint
@@ -266,6 +292,11 @@ instance (KnownSymbol sym, HasLink sub)
266292 where
267293 k = symbolVal (Proxy :: Proxy sym)
268294
295+-- :<|> instance - Generate all links at once
296+instance (HasLink a, HasLink b) => HasLink (a :<|> b) where
297+ type MkLink (a :<|> b) = MkLink a :<|> MkLink b
298+ toLink _ l = toLink (Proxy :: Proxy a) l :<|> toLink (Proxy :: Proxy b) l
299+
269300-- Misc instances
270301instance HasLink sub => HasLink (ReqBody ct a :> sub) where
271302 type MkLink (ReqBody ct a :> sub) = MkLink sub
@@ -313,3 +344,4 @@ instance HasLink sub => HasLink (AuthProtect tag :> sub) where
313344
314345-- $setup
315346-- >>> import Servant.API
347+-- >>> import Data.Text (Text)