Protocol - element-ts/lithium GitHub Wiki
When a client starts a new connection to a server via the LiSocket.init() static async method, it generates a new
socket using the ws package. It then waits to get its id from the server using an
internal command.
Once an id is generated by the server, and the server has processed the new connection, the init() method on
LiSocket sets its id and resolves the promise. This is why the method is async.
When a command is invoked by a socket, it creates an LiMessage object which looks like below:
{
timestamp: Date.now(),
command: "the-command-name",
param: 42,
id: "an-id-created",
peerToPeer: false
}
It sets the timestamp to the current time. The command and param are self-explanatory. For id, the LiMessageManager
instance attached to the LiBaseSocket generates a new non-colliding identifier and adds the new message's handler
to an internal map.
The message object is stringified by @elijahjcobb/better-json. All this
package does is stringify it but correctly handles the conversion for Buffer objects. The string is then converted
into a Buffer and sent through the socket. On the other side, the corresponding LiBaseSocket parses the binary data
and gets it back to an LiMesage.
The socket then checks the types of the message and finds the handler provided by the implement method in the socket's
LiCommandRegistry instance. It runs the handler. If the handler throws an error the socket will catch it. Then it
packages up the response of the handler whether it be a correct response or error and creates a new LiMessage where
the timestamp, is the original message's timestamp, the command, is either "return" or "error". The param is the
return value or error, the id is the original message's id, and peerToPeer is set to false unless it is a peer-to-peer
command.