-module(langfuse_client@client).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/langfuse_client/client.gleam").
-export([new/3, send_get/4]).
-export_type([client/0, error/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" HTTP client for a Langfuse project. Holds the base URL and API key pair\n"
" used to authenticate against `/api/public/*` endpoints. Domain-specific\n"
" modules (e.g. `langfuse_client/score`) drive the actual requests via `send_get`.\n"
"\n"
" The pure pieces (types, `new`) compile on both the Erlang and JavaScript\n"
" targets; the HTTP-issuing pieces are Erlang-only because they depend on\n"
" `gleam_httpc`.\n"
).
-type client() :: {client, binary(), binary(), binary()}.
-type error() :: {http_error, binary()} |
{bad_status, integer(), binary()} |
{bad_url, binary()} |
{decode_error, gleam@json:decode_error()}.
-file("src/langfuse_client/client.gleam", 50).
?DOC(
" Build a client. Trailing slashes on `base_url` are stripped so callers\n"
" can pass either form.\n"
).
-spec new(binary(), binary(), binary()) -> client().
new(Base_url, Public_key, Secret_key) ->
gleam@bool:guard(
not gleam_stdlib:string_ends_with(Base_url, <<"/"/utf8>>),
({client, Base_url, Public_key, Secret_key}),
fun() ->
{client, gleam@string:drop_end(Base_url, 1), Public_key, Secret_key}
end
).
-file("src/langfuse_client/client.gleam", 114).
-spec decode_body(
gleam@http@response:response(binary()),
gleam@dynamic@decode:decoder(FFC)
) -> {ok, FFC} | {error, error()}.
decode_body(Resp, Decoder) ->
gleam@bool:guard(
(erlang:element(2, Resp) < 200) orelse (erlang:element(2, Resp) >= 300),
{error, {bad_status, erlang:element(2, Resp), erlang:element(4, Resp)}},
fun() -> _pipe = gleam@json:parse(erlang:element(4, Resp), Decoder),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {decode_error, Field@0} end
) end
).
-file("src/langfuse_client/client.gleam", 108).
-spec send_raw(gleam@http@request:request(binary())) -> {ok,
gleam@http@response:response(binary())} |
{error, error()}.
send_raw(Req) ->
_pipe = gleam@httpc:send(Req),
gleam@result:map_error(
_pipe,
fun(E) -> {http_error, gleam@string:inspect(E)} end
).
-file("src/langfuse_client/client.gleam", 102).
-spec auth_header(client()) -> binary().
auth_header(Client) ->
Creds = <<<<(erlang:element(3, Client))/binary, ":"/utf8>>/binary,
(erlang:element(4, Client))/binary>>,
<<"Basic "/utf8,
(gleam_stdlib:base64_encode(gleam_stdlib:identity(Creds), true))/binary>>.
-file("src/langfuse_client/client.gleam", 85).
-spec build_request(client(), binary()) -> {ok,
gleam@http@request:request(binary())} |
{error, error()}.
build_request(Client, Path) ->
Url = <<(erlang:element(2, Client))/binary, Path/binary>>,
gleam@result:'try'(
begin
_pipe = gleam_stdlib:uri_parse(Url),
gleam@result:replace_error(_pipe, {bad_url, Url})
end,
fun(Parsed) ->
gleam@result:'try'(
begin
_pipe@1 = gleam@http@request:from_uri(Parsed),
gleam@result:replace_error(_pipe@1, {bad_url, Url})
end,
fun(Req) -> _pipe@2 = Req,
_pipe@3 = gleam@http@request:set_method(_pipe@2, get),
_pipe@4 = gleam@http@request:prepend_header(
_pipe@3,
<<"authorization"/utf8>>,
auth_header(Client)
),
_pipe@5 = gleam@http@request:prepend_header(
_pipe@4,
<<"accept"/utf8>>,
<<"application/json"/utf8>>
),
{ok, _pipe@5} end
)
end
).
-file("src/langfuse_client/client.gleam", 70).
?DOC(false).
-spec send_get(
client(),
binary(),
list({binary(), binary()}),
gleam@dynamic@decode:decoder(FEQ)
) -> {ok, FEQ} | {error, error()}.
send_get(Client, Path, Query, Decoder) ->
gleam@result:'try'(
build_request(Client, Path),
fun(Req) ->
Req@1 = gleam@http@request:set_query(Req, Query),
gleam@result:'try'(
send_raw(Req@1),
fun(Resp) -> decode_body(Resp, Decoder) end
)
end
).