View Source Tamnoon.Methods (Tamnoon v1.0.0-rc.3)

A methods module that provides built-in methods for use in your Tamnoon application.

This module offers utilities for basic state management via tmnn_get/2 and tmnn_update/2, as well as PubSub functionality through tmnn_sub/2, tmnn_unsub/2, tmnn_pub/2 and subbed_channels/0.

Most of these methods are primarily intended either to be used internally by Tamnoon, or to be triggered from Tamnoon HEEx markup.

This module is automatically included as a methods module by Tamnoon.

Note: In the documentation for the built-in methods, the term "returns" may refer to either the function's return value or the value included in the server's response to the client. The context should clarify which is meant.

Summary

Functions

Returns the value of the key under the field "key" in the request as an atom. Note: this is not a method handler - simply a utility function.

Returns a list of the channels the client is currently subscribed to.

Logs the req to the console. This method is primarily intended for debugging purposes.

Returns the field from the state corresponding to the :key specified in the request. If the key is not present in the state, returns an error string.

Invoked every 55 seconds by the client in order to prevent idle timeouts. Intended for internal use by Tamnoon.

Broadcasts a request to all clients subscribed to the channel specified under the "channel" key. The request to be sent is provided under the "action" key, and will be treated as a regular method call on the receiving clients.

Sets the server state to the value provided by the client. This is automatically invoked when the client reconnects, helping to restore the previous state and prevent information loss. Intended for internal use by Tamnoon.

Subscribes the client to the channel specified under the "channel" field in the request. If the channel does not exist, it will be created automatically. If the client is already subscribed to the channel, the call has no effect.

Returns the current state. This method is automatically invoked when a client connection is established. Intended for internal use by Tamnoon.

Unsubscribes the client from the channel specified under the "channel" field in the request. If the client is not already subscribed to the channel or it does not exist, the call has no effect. Will return an error string if trying to unsubscribe from the "clients" channel.

Updates the value of the field specified by the "key" in the request, setting it to the value provided under the "value" key. Returns the updated field value, or an error string if the field does not exist.

Functions

@spec get_key(map(), map()) :: atom() | nil

Returns the value of the key under the field "key" in the request as an atom. Note: this is not a method handler - simply a utility function.

@spec subbed_channels() :: [term()]

Returns a list of the channels the client is currently subscribed to.

@spec tmnn_debug(map(), map()) ::
  {%{tmnn_debug: debug_message :: String.t()}, [], state :: map()}

Logs the req to the console. This method is primarily intended for debugging purposes.

@spec tmnn_get(map(), map()) ::
  {field :: map(), [], state :: map()}
  | {%{tmnn_error: error :: String.t()}, [], state :: map()}

Returns the field from the state corresponding to the :key specified in the request. If the key is not present in the state, returns an error string.

Example

<button onclick=@get-mydata>Refresh</button>
<p>@mydata</p>

In this example, clicking the button triggers the :get method with the key :mydata, updating the contents of the <p> element to reflect the current value of :mydata in the state.

Note: In typical usage, method return values should keep the client state in sync automatically, making manual :get calls unnecessary in most cases.

Link to this function

tmnn_keep_alive(req, state)

View Source
@spec tmnn_keep_alive(map(), map()) :: {nil, [], state :: map()}

Invoked every 55 seconds by the client in order to prevent idle timeouts. Intended for internal use by Tamnoon.

@spec tmnn_pub(map(), map()) :: {%{pub: :ok}, [], state :: map()}

Broadcasts a request to all clients subscribed to the channel specified under the "channel" key. The request to be sent is provided under the "action" key, and will be treated as a regular method call on the receiving clients.

Example

defmethod :send_message do
  %{
    message_content: message_content,
    current_room_id: current_room_id
  } = state

  Tamnoon.Methods.pub(%{
        "channel" => "room_#{current_room_id}",
        "action" => %{
          "method" => "add_message",
          "message" => message_content
        }
      }, state)

  {%{message_content: ""}}
end

In the example above, the :send_message method broadcasts an :add_message method call to all clients in the current room. The broadcasted request includes a "message" field with the content of the message.

Link to this function

tmnn_set_state(req, state)

View Source
@spec tmnn_set_state(map(), map()) :: {%{set_state: :ok}, [], state :: map()}

Sets the server state to the value provided by the client. This is automatically invoked when the client reconnects, helping to restore the previous state and prevent information loss. Intended for internal use by Tamnoon.

@spec tmnn_sub(map(), map()) :: {%{sub: :ok}, [], state :: map()}

Subscribes the client to the channel specified under the "channel" field in the request. If the channel does not exist, it will be created automatically. If the client is already subscribed to the channel, the call has no effect.

defmethod :switch_room do
  target_room_id = req["value"]

  Tamnoon.Methods.unsub(%{"channel" => "room_#{state[:current_room_id]}"}, state)
  Tamnoon.Methods.sub(%{"channel" => "room_#{target_room_id}"}, state)

  {%{current_room_id: target_room_id}}
end

In the example above, the :switch_room method unsubscribes the client from their currently joined room and subscribes them to a new room with the key "room_<id>".

@spec tmnn_sync(map(), map()) :: {state :: map(), [], state :: map()}

Returns the current state. This method is automatically invoked when a client connection is established. Intended for internal use by Tamnoon.

@spec tmnn_unsub(map(), map()) ::
  {%{unsub: :ok}, [], state :: map()}
  | {%{tmnn_error: error :: String.t()}, [], state :: map()}

Unsubscribes the client from the channel specified under the "channel" field in the request. If the client is not already subscribed to the channel or it does not exist, the call has no effect. Will return an error string if trying to unsubscribe from the "clients" channel.

defmethod :switch_room do
  target_room_id = req["value"]

  Tamnoon.Methods.unsub(%{"channel" => "room_#{state[:current_room_id]}"}, state)
  Tamnoon.Methods.sub(%{"channel" => "room_#{target_room_id}"}, state)

  {%{current_room_id: target_room_id}}
end

In the example above, the :switch_room method unsubscribes the client from their currently joined room and subscribes them to a new room with the key "room_<id>".

@spec tmnn_update(map(), map()) ::
  {new_field :: map()}
  | {%{tmnn_error: error :: String.t()}, [], state :: map()}

Updates the value of the field specified by the "key" in the request, setting it to the value provided under the "value" key. Returns the updated field value, or an error string if the field does not exist.

Example

<input onchange=@update-name placeholder="Enter your name..">
<p>Your name is: <span>@name</span></p>

In the example above, each time the <input> changes, the :name field in the state will be updated. The updated value will be automatically reflected in the <p> element.

Usage with other elements

This method can also be used with elements that don’t have an intrinsic value (like <button>) by explicitly providing a value attribute:

<button onclick=@update-theme value="dark">Dark mode</button>

In this example, clicking the button sets the :theme field in the state to "dark".