purescript-rest icon indicating copy to clipboard operation
purescript-rest copied to clipboard

Updates to work PureScript 0.10.5

Open dgendill opened this issue 9 years ago • 2 comments

I went through the codebase and updated the syntax and dependencies to work with the latest version of PureScript. I think everything should work as before, but I did run into a problem rewriting the jsonRequest function for the Endpoint Server instance. I get a type error on the Right case...

Node.onEnd requestStream do
  body <- unsafeRunRef $ readRef bodyRef
  case (runExcept $ readJSON body) of
    Right a -> respond (Right a)
    Left _ -> respond (Left (ServiceError 400 "Bad request"))
src/REST/Server.purs:121:26
Right a -> respond (Right a)
                ^^^^^^^^^^^^^^^^^
Could not match type
  Function
with type
  Eff

I'm not entirely sure how to fix that, but everything else seems to work. When I comment out the code that uses jsonRequest and jsonResponse, I can start the server and hit the home endpoint in the browser.

dgendill avatar Jan 26 '17 03:01 dgendill

I was able to build and test with these modifications:

src/REST/Server.purs

This modification builds but I am not sure how useful it is.

-- ...
  jsonRequest = Server \req res r ->
    let receive _  = do
          let requestStream = Node.requestAsStream req
          Node.setEncoding requestStream Node.UTF8
          bodyRef <- unsafeRunRef $ newRef ""
          Node.onDataString requestStream UTF8 \ s -> do
            unsafeRunRef $ modifyRef bodyRef ((<>) s)
          Node.onError requestStream \ _ -> pure unit
          Node.onEnd requestStream (pure unit)
          pure unit
    in Just (ServerResult r (Right receive))
-- ...

src/REST/Docs.purs

-- ...
  jsonRequest         = requestDocs
  jsonResponse        = responseDocs
-- ...

src/REST/Endpoint.purs

-- ...
import Control.Monad.Eff.Exception (EXCEPTION)
-- ...
type Source eff req = (req -> Eff ( http :: Node.HTTP | eff) Unit) -> Eff (http :: Node.HTTP, err :: EXCEPTION | eff) Unit
-- ...

test/Main.purs

-- ...
import Control.Monad.Eff.Exception (EXCEPTION)
-- ...
import REST.Endpoint (comments, header, post, lit, response, get, Sink, ServiceError(..), class Endpoint, class AsForeign, class HasExample, sendResponse, Source, jsonResponse, jsonRequest)
-- ...
echo :: forall e eff. (Endpoint e) => e (Eff (http :: Node.HTTP, err :: EXCEPTION | eff) Unit)
echo = worker <$> (docs *> post *> lit "echo" *> shoutHeader) <*> jsonRequest <*> jsonResponse <*> response
  where
  worker :: String -> Source eff (Either ServiceError Echo) -> Sink eff Echo -> Node.Response -> Eff (http :: Node.HTTP, err :: EXCEPTION | eff) Unit
  worker shout source sink res = do
    source \e ->
      case e of
        Left (ServiceError code msg) -> sendResponse res code "text/plain" msg
        Right (Echo s) -> sink <<< Echo $
          case shout of
            "yes" -> toUpper s
            _ -> s

Output

~/g/purescript-rest git:master ❯❯❯ pulp build                                                                                                    ✱
* Building project in /purescript-rest
* Build successful.
~/g/purescript-rest git:master ❯❯❯ pulp test                                                                                                     ✱
* Building project in /purescript-rest
Compiling Test.Main

* Build successful.
* Running tests...
The API tester is configured to send requests to localhost:9000/api.
To avoid CORS issues in the browser, you should forward requests from port 9000 to 8080/8081 accordingly.
Listening on port 8080.
Serving docs on port 8081.

:+1:

lettier avatar Jan 26 '17 07:01 lettier

I wish I could figure out what I needed to return from the receive and related functions, but I suppose this is a good start. The onEnd function needs to do something with the accumulated body of the request and the respond callback function (which seems like it should have type (Either ServiceError req) -> Eff (http :: Node.HTTP | eff)). So passing Right a to the callback seems like it should return the Eff that Node.onEnd wants, but that doesn't seem to be the case.

If you're ok with merging a partial solution, at least it will compiles for anyone who's curious. I might come back to this later when I know more.

dgendill avatar Jan 26 '17 22:01 dgendill