Packages
caffeine_lang
6.1.1
6.3.1
6.3.0
6.2.2
6.2.1
6.2.0
6.1.2
6.1.1
6.1.0
6.0.0
5.6.0
5.5.0
5.4.4
5.4.3
5.4.2
5.4.1
5.4.0
5.3.0
5.2.0
5.1.1
5.1.0
5.0.12
5.0.11
5.0.10
5.0.8
5.0.7
5.0.6
5.0.5
5.0.4
5.0.1
5.0.0
4.10.0
4.9.0
4.8.3
4.8.2
4.8.1
4.8.0
4.7.9
4.7.8
4.7.7
4.7.6
4.7.5
4.6.7
4.6.6
4.6.5
4.6.4
4.6.3
4.6.2
4.6.0
4.5.1
4.5.0
4.4.4
4.4.3
4.4.1
4.4.0
4.3.7
4.3.6
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.0.2
1.0.1
0.1.0
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.2
0.0.1
A compiler for generating reliability artifacts from service expectation definitions.
Current section
Files
Jump to
Current section
Files
src/caffeine_lang@codegen@relay.erl
-module(caffeine_lang@codegen@relay).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/codegen/relay.gleam").
-export([generate/1]).
-export_type([signal_entry/0, signal_kind/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.
-type signal_entry() :: {signal_entry,
binary(),
signal_kind(),
binary(),
gleam@dict:dict(binary(), caffeine_lang@value:value()),
gleam@option:option(binary())}.
-type signal_kind() :: count | distribution.
-file("src/caffeine_lang/codegen/relay.gleam", 130).
-spec match_value_json(caffeine_lang@value:value()) -> gleam@json:json().
match_value_json(V) ->
case V of
{string_value, S} ->
gleam@json:string(S);
{int_value, I} ->
gleam@json:int(I);
{float_value, F} ->
gleam@json:float(F);
{bool_value, B} ->
gleam@json:bool(B);
_ ->
gleam@json:null()
end.
-file("src/caffeine_lang/codegen/relay.gleam", 122).
?DOC(
" Serialize a `match` dict. Match values are runtime-untyped at the relay,\n"
" so we emit each as its nearest JSON shape. Strings stay strings; numeric\n"
" and boolean values keep their JSON-native form. Other shapes fall back\n"
" to `null` (shouldn't appear post-validate). Entries are sorted by key for\n"
" deterministic output across compile targets — `dict.to_list` doesn't\n"
" guarantee insertion order on JavaScript.\n"
).
-spec match_dict_json(gleam@dict:dict(binary(), caffeine_lang@value:value())) -> gleam@json:json().
match_dict_json(Match) ->
_pipe = Match,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Pair) ->
{erlang:element(1, Pair), match_value_json(erlang:element(2, Pair))}
end
),
gleam@json:object(_pipe@3).
-file("src/caffeine_lang/codegen/relay.gleam", 109).
-spec signal_kind_to_string(signal_kind()) -> binary().
signal_kind_to_string(Kind) ->
case Kind of
count ->
<<"count"/utf8>>;
distribution ->
<<"distribution"/utf8>>
end.
-file("src/caffeine_lang/codegen/relay.gleam", 96).
-spec signal_entry_json(signal_entry()) -> gleam@json:json().
signal_entry_json(Entry) ->
gleam@json:object(
[{<<"metric"/utf8>>, gleam@json:string(erlang:element(2, Entry))},
{<<"kind"/utf8>>,
gleam@json:string(
signal_kind_to_string(erlang:element(3, Entry))
)},
{<<"source"/utf8>>, gleam@json:string(erlang:element(4, Entry))},
{<<"match"/utf8>>, match_dict_json(erlang:element(5, Entry))},
{<<"value_path"/utf8>>, case erlang:element(6, Entry) of
none ->
gleam@json:null();
{some, P} ->
gleam@json:string(P)
end}]
).
-file("src/caffeine_lang/codegen/relay.gleam", 89).
?DOC(
" Wrap a list of entries in the top-level `signals.json` object: a version\n"
" tag plus the routing array.\n"
).
-spec signals_json(list(signal_entry())) -> gleam@json:json().
signals_json(Entries) ->
gleam@json:object(
[{<<"version"/utf8>>, gleam@json:int(1)},
{<<"signals"/utf8>>,
gleam@json:array(Entries, fun signal_entry_json/1)}]
).
-file("src/caffeine_lang/codegen/relay.gleam", 62).
?DOC(
" Build the list of signal entries from a single resolved IR by walking\n"
" `slo.indicators` for `ExternalSignal` variants. Literal-query indicators\n"
" are skipped — they don't need relay routing. Entries are sorted by\n"
" indicator name for deterministic output across compile targets.\n"
).
-spec ir_to_signal_entries(
caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved())
) -> list(signal_entry()).
ir_to_signal_entries(Ir) ->
_pipe = erlang:element(3, erlang:element(5, Ir)),
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun(A, B) ->
gleam@string:compare(erlang:element(1, A), erlang:element(1, B))
end
),
gleam@list:filter_map(
_pipe@2,
fun(Pair) ->
{Name, Src} = Pair,
case Src of
{external_signal, Source, Match, Value_extraction} ->
{ok,
{signal_entry,
<<<<<<"caffeine."/utf8,
(erlang:element(3, Ir))/binary>>/binary,
"."/utf8>>/binary,
Name/binary>>,
case Value_extraction of
none ->
count;
{some, _} ->
distribution
end,
Source,
Match,
gleam@option:map(
Value_extraction,
fun(Ve) -> erlang:element(2, Ve) end
)}};
_ ->
{error, nil}
end
end
).
-file("src/caffeine_lang/codegen/relay.gleam", 48).
?DOC(false).
-spec generate(
list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved()))
) -> gleam@option:option(binary()).
generate(Irs) ->
Entries = gleam@list:flat_map(Irs, fun ir_to_signal_entries/1),
case Entries of
[] ->
none;
_ ->
{some, gleam@json:to_string(signals_json(Entries))}
end.