Chadtech/mail, and you can see an example project here. Below is the most basic example code:
mailLogin : Model -> Mail Msg mailLogin model = [ ( "username", Encode.string model.username ) , ( "password", Encode.string model.password ) ] |> Encode.object |> Mail.letter "login" |> Mail.expectResponse loginDecoder LoginResult |> Mail.send
This code is saying "Pass along this
"login", and decode its response value with
loginDecoder, which will be handled by the
LoginResult". Thats it. Theres no outgoing port that needs to get called, and you dont need to set up the subscription to listen for the result.
@splodingsocks gave that great talk on ports at Elm conf, where he showed everyone a code technique of having only one incoming and outgoing port. Its a really great idea that excited a whole lot of us. At my job, we ended up implementing it in our Elm apps. @pdamoc made Elm Ports Driver, which are an Elm and Npm package for this technique too.
I ended up talking about it with enough people that I wrote this gist, summarizing how I do it. I ended up talking to James Hopkins, a new member of the Elm slack, about his project using ports to access firebase. Somehow an idea emerged between us in our conversation:
What if ports were like http requests, and you didnt have to wire up any subscriptions at all? Instead you could just pack up an address, a value, and an expected return value and send it off.
So thats what I set out to make, and thats what
Chadtech/mail is. The whole one-incoming-and-outgoing-port thing is still there, but its entirely encapsulated inside this new
addresss, and you can send
Letters to those
addresses just by passing along a
String with a
Json.Encode.Value. The JS function also gets a call back, and if you mailed your
Letter along with a
Decoder a and a
Result String a -> msg,
Chadtech/mail decodes the return value and passes the
Msg right into your update function.
The whole thing ended up being really intensive
I didnt realize this at the onset, but to make this work I had to kind of overhaul everything. You know how theres
Html.program, but separately theres also
Navigation.program? I had to make a
Mail.program. The most fundamental change from
Html.programs is that
Mail.Program update functions return
(Model, Mail Msg) instead of
(Model, Cmd Msg). Its just an extension of
Cmds, regular old
Cmd Msgs can become
Mail Msgs by means of
Mail.cmd : Cmd Msg -> Mail Msg and they work just how they did before. Thats the most fundamental difference.
Thats my project. Im curious for any feedback, or if you think this might be useful. I was really just trying to get a proof of concept together but now I have some hope this could actually be practical. Let me know if you dont think so. Seeing as this was a lot more of a fundamental change in the Elm architecture than I thought it would be, it seems to me that the best implementation of this would be in the language itself, and not as a package. It really would just be making a
Ports.send : String -> Letter msg -> Cmd msg function, along with a callback inside