cdepillabout / servant-static-th

Embed a directory of static files in your application and serve them from your Servant server
http://hackage.haskell.org/package/servant-static-th
BSD 3-Clause "New" or "Revised" License
14 stars 9 forks source link

Type-safe links? #14

Closed saurabhnanda closed 4 years ago

saurabhnanda commented 4 years ago

Is there a recommended way of generating type-safe links for a directory who's API has been created by createApiAndServerDecs?

cdepillabout commented 4 years ago

Servant has some functionality for generating type-safe links: https://hackage.haskell.org/package/servant-0.17/docs/Servant-Links.html.

I'm going to go ahead and close this, since I don't think that there is anything this library can do in particular about this.

If this doesn't work for you, and you think there would be a nice way to handle it in this library, please feel free to respond here and re-open this issue.

saurabhnanda commented 4 years ago

I'm going to go ahead and close this, since I don't think that there is anything this library can do in particular about this.

This library generates servant routes using the following approach, right:

type Api = 
  "assets" :> 
    ("js" :> 
      ( "main.js :> Get ...) :<|>
      ( "app.js :> Get ...) :<|>
      ( "something.js :> Get ...))

This makes it almost impossible to generate type-safe links, because:

Is there any way around this, that I'm missing?

cdepillabout commented 4 years ago

@saurabhnanda Here's an example of doing this, using the example here:

diff --git a/example/Example.hs b/example/Example.hs
index 13729c2..abd0b7f 100644
--- a/example/Example.hs
+++ b/example/Example.hs
@@ -1,13 +1,15 @@
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeOperators #-}

 module Main where

 import Data.Proxy (Proxy(Proxy))
+import Data.Text (Text)
 import Network.Wai (Application)
 import Network.Wai.Handler.Warp (run)
-import Servant.Server (serve)
-import Servant.Static.TH (createApiAndServerDecs)
+import Servant
+import Servant.Static.TH

 -- 'createApiAndServerDecs' will use the files in the directory @example/example-dir@
 -- to create two things.
@@ -66,3 +68,8 @@ app = serve (Proxy :: Proxy FrontEndApi) frontEndServer

 main :: IO ()
 main = run 8080 app
+
+hello :: Text
+hello =
+  let p = Proxy :: Proxy ("dir" :> "inner-file.html" :> Get '[HTML] Html)
+  in toUrlPiece (safeLink (Proxy :: Proxy FrontEndApi) p :: Link)
diff --git a/servant-static-th.cabal b/servant-static-th.cabal
index 18e9051..63528e5 100644
--- a/servant-static-th.cabal
+++ b/servant-static-th.cabal
@@ -54,6 +54,7 @@ executable servant-static-th-example
   build-depends:       base
                      , servant-server
                      , servant-static-th
+                     , text
                      , wai
                      , warp
   default-language:    Haskell2010

These changes are on the current master (commit 3baf38ab50).

I tested building this with the command stack build --flag servant-static-th:buildexample.

The actual example is here:

hello :: Text
hello =
  let p = Proxy :: Proxy ("dir" :> "inner-file.html" :> Get '[HTML] Html)
  in toUrlPiece (safeLink (Proxy :: Proxy FrontEndApi) p :: Link)

Does this help?


Maybe you're looking for type-safe links like Yesod generates? Maybe something like the following:

dir_inner_file_html_get_html_html :: Proxy ("dir" :> "inner-file.html" :> Get '[HTML] Html)
dir_inner_file_html_get_html_html = Proxy

I don't remember exactly how Yesod generates these type-safe files, but I think it is something like this.

servant-static-th doesn't generate anything like this, but it could if someone is interested in adding it.

If you (or anyone else) is interesting in seeing this, please let me know.