Exploring Kino
Mix.install([
{:kino, "~> 0.10.0"},
{:req, "~> 0.3.10"},
{:absinthe_client, "~> 0.1.0"}
])
Helpers
defmodule Github do
def query(query_string) do
Req.new(
base_url: "https://api.github.com",
headers: [
{"Authorization", "bearer " <> System.get_env("LB_GITHUB_TOKEN")},
{"Content-Type", "application/json"}
]
)
|> AbsintheClient.attach()
|> Req.post!(graphql: query_string)
end
end
Github Star Fetcher
defmodule StarFetcher do
use GenServer
def init(:ok) do
state = %{frame: nil}
{:ok, state, {:continue, :setup_form}}
end
def handle_continue(:setup_form, state) do
form =
[
username: Kino.Input.text("Username"),
repo: Kino.Input.text("Repository")
]
|> Kino.Control.form(submit: "Fetch Stars")
|> Kino.render()
frame = Kino.Frame.new() |> Kino.render()
Kino.Control.subscribe(form, :star_fetcher_form)
{:noreply, %{state | frame: frame}}
end
def handle_info({:star_fetcher_form, %{data: %{username: username, repo: repo}}}, state) do
response =
Github.query("""
query {
repository(owner: \"#{username}\", name: \"#{repo}\") {
stargazerCount
}
}
""")
msg = handle_response(response, username, repo)
Kino.Frame.append(state.frame, msg)
{:noreply, state}
end
defp handle_response(%{status: 200, body: %{"errors" => errors}}, _username, _repo) do
first_error = Enum.at(errors, 0)
"Failed to fetch star count: #{Map.get(first_error, "message")}"
end
defp handle_response(%{status: 200, body: %{"data" => data}}, username, repo) do
number_of_stars = data |> Map.get("repository") |> Map.get("stargazerCount")
"https://github.com/#{username}/#{repo} has #{number_of_stars} stars"
end
defp handle_response(%{status: status}, _username, _repo) do
"Search failed with status: #{status}"
end
end
{:ok, star_fetcher} = GenServer.start(StarFetcher, :ok)