Updates to work PureScript 0.10.5
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.
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:
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.