figbus / elm-urbit-api / Urbit

Data Types


type Session

A session represents an active connection to an urbit ship.

url : Session -> String

Get a Session's url.

ship : Session -> Encoding.Atom.Atom

Get a Session's ship.

uid : Session -> String

Get a Session's uid.

lastEventId : Session -> Basics.Int

Get a Session's lastEventId.


type alias InMsg =
{ lastEventId : Basics.Int
, data : InMsgData 
}

Represents an incoming message.


type InMsgData
    = Poke Basics.Int (Result String ())
    | Subscribe Basics.Int (Result String ())
    | Diff Basics.Int Json.Encode.Value
    | Quit Basics.Int

An incoming message may be one of the following:

In all cases the first Int value represents the Id of the message it is relevant to.


type OutMsg

Represents an outgoing message.

Connection Setup

These are required in order to maintain an active connection to an urbit ship and to perform poke/subscription requests.

connect : { ship : Encoding.Atom.Atom, url : String, channelId : String, code : String } -> (Result Http.Error Session -> msg) -> Platform.Cmd.Cmd msg

Connect to an urbit ship and return a Session on success. Should be followed by setupEventSource (this must be done as a separate step due to the nature of Elm ports).

You can generate a unique channelId any way you wish, however the provided genChannelId function is recommended.

connectUnauth : { ship : Encoding.Atom.Atom, url : String, channelId : String } -> (Result Http.Error Session -> msg) -> Platform.Cmd.Cmd msg

Alternative to connect that does not require a code.

Note: Ensure the correct cookie is set through some other means beforehand or else this will not work. Hosting from within an urbit using the :file-server app with public set to false should work, for example.

setupEventSource : (String -> Platform.Cmd.Cmd msg) -> Session -> Platform.Cmd.Cmd msg

This will set up the realtime communication channel with urbit. Because Elm does not support the EventSource API required, this must be done using ports. Elm does not allow ports to be published as part of a package, but luckily the setup for this is fairly straightforward.

First, copy/paste the following into your js file and replace any references to app with the variable name of your running Elm app:

app.ports.setupUrbitEventSource.subscribe((url) => {
  const eventSource = new EventSource(url, { withCredentials: true });

  eventSource.onmessage = function (event) {
    app.ports.onUrbitMessage.send({ message: event });
  };

  eventSource.onerror = function (event) {
    app.ports.onUrbitMessage.send({ error: event });
  };
});

Next, declare a port module and the following ports to handle the initial setup and incoming messages:

port setupUrbitEventSource : String -> Cmd msg

port onUrbitMessage : (JE.Value -> msg) -> Sub msg

Now, the newly created setupUrbitEventSource can be passed as the first argument to our setupEventSource function and used to perform the necessary setup. Similarly, the onUrbitMessage function can be passed as the first argument to messages below to set up the subscription to incoming events.

setupCommand =
    Urbit.setupEventSource setupUrbitEventSource session

messagesSubscription =
    Urbit.messages onUrbitMessage GotUrbitMessage

See the Elm guide for further information regarding ports.

messages : ((Json.Encode.Value -> msg) -> Platform.Sub.Sub msg) -> (Result Json.Decode.Error InMsg -> msg) -> Platform.Sub.Sub msg

Subscribe to incoming messages from urbit. See setupEventSource above for instructions on how to use this. Every message received must be acknowledged by using the related ack function, otherwise urbit will stop accepting any further messages.

ack : Basics.Int -> OutMsg

Acknowledge an incoming message by its Id. Must be performed for every incoming message received.

Stateful Requests

poke : { ship : Encoding.Atom.Atom, app : String, mark : String, json : Json.Encode.Value } -> OutMsg

Poke an app on a ship.

subscribe : { ship : Encoding.Atom.Atom, app : String, path : String } -> OutMsg

Subscribe to ship events on some path.

unsubscribe : Basics.Int -> OutMsg

Unsubscribe from an existing subscription by its Id.

disconnect : OutMsg

Safely deletes a channel.

send : Session -> (Result Http.Error () -> msg) -> OutMsg -> ( Session, Platform.Cmd.Cmd msg )

Sends an outgoing message to urbit. Returns a tuple of a new session and the command.

sendBatch : Session -> (Result Http.Error () -> msg) -> List OutMsg -> ( Session, Platform.Cmd.Cmd msg )

Sends multiple outgoing messages to urbit in one request. Returns a tuple of a new session and the command.

sendTask : Session -> OutMsg -> ( Session, Task Http.Error () )

Sends an outgoing message to urbit as a task. Returns a tuple of a new session and the task.

sendBatchTask : Session -> List OutMsg -> ( Session, Task Http.Error () )

Sends multiple outgoing messages to urbit in one request as a task. Returns a tuple of a new session and the task.

Stateless Requests

These do not require an active connection, however they do at least require you to be authenticated.

login : { url : String, code : String } -> (Result Http.Error () -> msg) -> Platform.Cmd.Cmd msg

Login to an urbit without maintaining an active connection. This will allow for stateless scry and spider requests that require authentication, but not others.

Note: This is not required if you have already used connect to authenticate.

scry : { url : String, app : String, path : String, mark : String, decoder : Json.Decode.Decoder a } -> (Result Http.Error a -> msg) -> Platform.Cmd.Cmd msg

Make a scry request.

spider : { url : String, desk : String, inputMark : String, outputMark : String, threadName : String, body : Json.Encode.Value, decoder : Json.Decode.Decoder output } -> (Result Http.Error output -> msg) -> Platform.Cmd.Cmd msg

Start a thread and get the response.

Helpers

genChannelId : Time.Posix -> Random.Generator String

Recommended way to create a unique id for a session's channel. Takes the current time and returns a random generator which can then be used to generate the full ID.

genUid : Random.Generator String

Helper for generating random urbit UIDs.

Based off of https://github.com/urbit/urbit/blob/137e4428f617c13f28ed31e520eff98d251ed3e9/pkg/interface/src/lib/util.js#L3