Write CLI scripts in Elm (IO Monad)

My idea for this package is to make it more ergonomic to write simple CLI scripts, for example dev tools and build pipelines. I also want to make it as open as possible to allow others to implement their own I/O in nodejs. Supporting HTTP-servers is however out of scope for now.

I’m currently working on specifying the API for the following I/O modules:

  • Read / write files.
  • File system, (move, copy, delete, list etc).
  • Http client, make http requests.
  • Spawn sub processes and run shell commands.

My plan for callJs is to simplify user specific I/O implementations and allow people to experiment.

CallJs Example

CallJs is just a wrapper for communicating with the “outside” using two ports.
To create your own project specific I/O implementation my current thinking goes along these lines:

Javascript

Create a standard nodejs module that exports an Object with all your I/O functions, e.g

js/my-functions.js

module.exports = {
    addOne: function(num) {
        this.send(num + 1); // this.send is a normal Elm port
    },
}

Elm

Then create an Elm module where you supply the Encoder / Decoder for communicating with Javascript, e.g src/MyModule.elm

addOne : Int -> IO x Int
addOne n =
    IO.callJs
        "addOne"
        [ Encode.int n
        ]
        Decode.int

program : IO.Process -> IO String ()
program _ =
    ...

Put it together

When you run or compile you can add arguments to supply your I/O implementation, something like this:

elm.cli run --extend-io js/my-functions.js src/MyModule.elm
2 Likes