javascript-bridge: Remote Monad for JavaScript on the browser

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain]

Bridge from Haskell to JavaScript on the browser


[Skip to ReadMe]

Properties

Versions0.2.0, 0.2.0
Change logCHANGELOG.md
Dependenciesaeson (==1.4.*), base (>=4.9 && <4.14), binary (==0.8.*), containers (>=0.5 && <0.7), javascript-bridge, scotty (==0.11.*), stm (>=2.4 && <2.6), text (==1.2.*), time (>=1.6 && <1.10), transformers (>=0.4 && <0.6), wai (==3.2.*), wai-websockets (>=3.0.1 && <3.1), websockets (>=0.10 && <0.13) [details]
LicenseBSD-3-Clause
CopyrightCopyright (c) 2016-2019 The University of Kansas
AuthorAndy Gill
Maintainerandygill@ku.edu
CategoryNetwork
Source repositoryhead: git clone https://github.com/ku-fpg/javascript-bridge
Executablesjavascript-bridge-examples, javascript-bridge-simple
UploadedThu Sep 12 15:49:16 UTC 2019 by AndyGill

Modules

[Index]

Downloads

Maintainers' corner

For package maintainers and hackage trustees


Readme for javascript-bridge-0.2.0

[back to package description]

javascript-bridge Build Status

javascript-bridge is a straightforward way of calling JavaScript from Haskell, using web-sockets as the underlying transport mechanism. Conceptually, javascript-bridge gives Haskell acccess to the JavaScript eval function. However, we also support calling and returning values from JavaScript functions, constructing and using remote objects, and sending events from JavaScript to Haskell, all using a remote monad.

Overview of API

javascript-bridge remotely executes JavaScript fragments. The basic Haskell idiom is.

     send eng $ command "console.log('Hello!')"

where send is an IO function that sends a commands for remote execution, eng is a handle into a specific JavaScript engine, and command is a command builder.

There are also ways synchronously sending a procedure, that is a JavaScript expression that constructs a value, then returns the resulting value.

  do xs :: String <- send eng $ procedure "new Date().toLocaleTimeString()"
     print xs

There are ways of creating remote values, for future use, where Haskell has a handle for this remote value.

data Date = Date -- phantom

  do t :: RemoteValue Date <- send eng $ constructor "new Date()"
     send eng $ procedure $ "console.log(" <> var t <> ".toLocaleTimeString())"

Finally, there is a way of sending events from JavaScript, then listening for the event in Haskell.

  do -- Have JavaScript send an event to Haskell
     send eng $ command $ event ('Hello!'::String)"
     -- Have Haskell wait for the event, which is an Aeson 'Value'.
     e :: Value <- listen eng
     print e

Bootstrapping

Bootstrapping the connection is straightforward. First, use a middleware to setup the (Haskell) server.

import Network.JavaScript

        ...
        scotty 3000 $ do
          middleware $ start app
          ...

app :: Engine -> IO ()
app eng = send eng $ command "console.log('Hello!')"

Next, include the following fragment in your HTML code.

    <script>
        window.jsb = {ws: new WebSocket('ws://' + location.host)};
        jsb.ws.onmessage = (evt) => eval(evt.data);
    </script>

That's it!