Created
June 13, 2025 06:29
-
-
Save nileshtrivedi/367d640f5ae9f6c75bd502e4605b0596 to your computer and use it in GitHub Desktop.
tamnoon single-file demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Run this as `elixir app.exs` | |
Mix.install([ | |
{:tamnoon, "~> 0.1.0"} | |
]) | |
defmodule TamnoonSample do | |
end | |
defmodule TamnoonSample.Router do | |
use Plug.Router | |
plug :match | |
plug :dispatch | |
get "/" do | |
homepage_html = """ | |
<!DOCTYPE html> | |
<html lang="en" data-theme="cupcake"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Tamnoon Sample App</title> | |
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" /> | |
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script> | |
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" /> | |
</head> | |
<body> | |
<script> | |
const wsUrl = "ws://localhost:4000/ws/"; | |
const socket = new WebSocket(wsUrl); | |
socket.onopen = function(event) { | |
socket.send(JSON.stringify({method: "get", key: "val"})); | |
document.getElementById("inc").onclick = () => socket.send(JSON.stringify({ | |
"method": "pub", | |
"channel": "clients", | |
"action": { | |
"method": "nudge", | |
"key": "val", | |
"direction": "up" | |
} | |
})) | |
document.getElementById("dec").onclick = () => socket.send(JSON.stringify({ | |
"method": "pub", | |
"channel": "clients", | |
"action": { | |
"method": "nudge", | |
"key": "val", | |
"direction": "down" | |
} | |
})) | |
}; | |
socket.onmessage = function(event) { | |
const field = JSON.parse(event.data); | |
if ("pub" in field) return; | |
if ("val" in field) { | |
document.getElementById("val").innerText = field.val; | |
} | |
}; | |
socket.onclose = function(event) { | |
console.log("WebSocket is closed now."); | |
}; | |
socket.onerror = function(error) { | |
console.log("WebSocket error:", error); | |
}; | |
</script> | |
<div class="hero bg-base-200 min-h-screen"> | |
<div class="hero-content text-center"> | |
<div class="max-w-md"> | |
<h1 id="val" class="text-5xl font-bold mb-4">0</h1> | |
<button class="btn btn-primary px-8 mr-4" id="inc">+</button> | |
<button class="btn btn-primary px-8" id="dec">-</button> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
""" | |
send_resp(conn, 200, homepage_html) | |
end | |
match _ do | |
send_resp(conn, 404, "404") | |
end | |
end | |
defmodule TamnoonSample.Methods do | |
use Tamnoon.Methods | |
defmethod :nudge do | |
key = Tamnoon.Methods.get_key(req, state) | |
val = Map.get(state, key) | |
new_val = if (req["direction"] == "up"), do: val + 1, else: val - 1 | |
new_state = Map.put(state, key, new_val) | |
{%{key => new_val}, new_state} | |
end | |
end | |
defmodule TamnoonSample.Application do | |
# See https://hexdocs.pm/elixir/Application.html | |
# for more information on OTP Applications | |
@moduledoc false | |
use Application | |
@impl true | |
def start(_type, _args) do | |
children = [ | |
{Tamnoon, [[initial_state: %{val: 0}, router: TamnoonSample.Router, methods_module: TamnoonSample.Methods]]} | |
] | |
# See https://hexdocs.pm/elixir/Supervisor.html | |
# for other strategies and supported options | |
opts = [strategy: :one_for_one, name: TamnoonSample.Supervisor] | |
Supervisor.start_link(children, opts) | |
end | |
end | |
Application.ensure_all_started(:logger) | |
{:ok, _pid} = TamnoonSample.Application.start(:normal, []) | |
# This will block the main process and keep the script running | |
Process.sleep(:infinity) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment