-module(lightspeed@framework@verified_routes).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/framework/verified_routes.gleam").
-export([route0/1, route1/2, route2/3, path/2, path_with_query/3, pattern/1, param_names/1, new_index/0, index_get0/3, index_get1/4, index_get2/5, index_post0/3, index_post1/4, as_verified_route/1, indexed_name/1, indexed_method/1, static_path/1, path_from_indexed/2, path_with_query_from_indexed/3, reference0/2, reference1/3, reference2/4, compile_reference/2, method_label/1, diagnostic_label/1, index_signature/1]).
-export_type([verified_route/1, route_method/0, get_tag/0, post_tag/0, put_tag/0, patch_tag/0, delete_tag/0, indexed_route/2, router_index/0, route_reference/0, route_diagnostic/0, indexed_meta/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(" Verified-route-style compile-time path helpers and router-index verification.\n").
-opaque verified_route(KNR) :: {verified_route,
binary(),
list(binary()),
fun((KNR) -> binary())}.
-type route_method() :: method_get |
method_post |
method_put |
method_patch |
method_delete.
-type get_tag() :: get_tag.
-type post_tag() :: post_tag.
-type put_tag() :: put_tag.
-type patch_tag() :: patch_tag.
-type delete_tag() :: delete_tag.
-opaque indexed_route(KNS, KNT) :: {indexed_route,
binary(),
route_method(),
verified_route(KNS)} |
{gleam_phantom, KNT}.
-opaque router_index() :: {router_index, list(indexed_meta())}.
-type route_reference() :: {route_reference,
binary(),
route_method(),
list(binary())}.
-type route_diagnostic() :: {unknown_route, binary()} |
{method_mismatch, binary(), route_method(), route_method()} |
{param_mismatch, binary(), list(binary()), list(binary())}.
-type indexed_meta() :: {indexed_meta,
binary(),
route_method(),
binary(),
list(binary())}.
-file("src/lightspeed/framework/verified_routes.gleam", 81).
?DOC(" Build a zero-parameter route helper.\n").
-spec route0(binary()) -> verified_route(nil).
route0(Pattern) ->
{verified_route, Pattern, [], fun(_) -> Pattern end}.
-file("src/lightspeed/framework/verified_routes.gleam", 89).
?DOC(
" Build a one-parameter route helper.\n"
"\n"
" Example:\n"
" `route1(\"/posts/:id\", \"id\")`\n"
).
-spec route1(binary(), binary()) -> verified_route(binary()).
route1(Pattern, Param) ->
Token = <<":"/utf8, Param/binary>>,
{verified_route,
Pattern,
[Param],
fun(Value) -> gleam@string:replace(Pattern, Token, Value) end}.
-file("src/lightspeed/framework/verified_routes.gleam", 100).
?DOC(
" Build a two-parameter route helper.\n"
"\n"
" Example:\n"
" `route2(\"/teams/:team_id/members/:id\", \"team_id\", \"id\")`\n"
).
-spec route2(binary(), binary(), binary()) -> verified_route({binary(),
binary()}).
route2(Pattern, First_param, Second_param) ->
First_token = <<":"/utf8, First_param/binary>>,
Second_token = <<":"/utf8, Second_param/binary>>,
{verified_route,
Pattern,
[First_param, Second_param],
fun(Values) ->
{First_value, Second_value} = Values,
First = gleam@string:replace(Pattern, First_token, First_value),
gleam@string:replace(First, Second_token, Second_value)
end}.
-file("src/lightspeed/framework/verified_routes.gleam", 120).
?DOC(" Render path for one verified route.\n").
-spec path(verified_route(KNX), KNX) -> binary().
path(Route, Params) ->
(erlang:element(4, Route))(Params).
-file("src/lightspeed/framework/verified_routes.gleam", 425).
-spec join_with(binary(), list(binary())) -> binary().
join_with(Separator, Values) ->
case Values of
[] ->
<<""/utf8>>;
[Value] ->
Value;
[Value@1 | Rest] ->
<<<<Value@1/binary, Separator/binary>>/binary,
(join_with(Separator, Rest))/binary>>
end.
-file("src/lightspeed/framework/verified_routes.gleam", 414).
-spec escape_query_piece(binary()) -> binary().
escape_query_piece(Value) ->
Escaped_percent = gleam@string:replace(Value, <<"%"/utf8>>, <<"%25"/utf8>>),
Escaped_space = gleam@string:replace(
Escaped_percent,
<<" "/utf8>>,
<<"%20"/utf8>>
),
Escaped_plus = gleam@string:replace(
Escaped_space,
<<"+"/utf8>>,
<<"%2B"/utf8>>
),
Escaped_ampersand = gleam@string:replace(
Escaped_plus,
<<"&"/utf8>>,
<<"%26"/utf8>>
),
Escaped_equals = gleam@string:replace(
Escaped_ampersand,
<<"="/utf8>>,
<<"%3D"/utf8>>
),
Escaped_question = gleam@string:replace(
Escaped_equals,
<<"?"/utf8>>,
<<"%3F"/utf8>>
),
Escaped_hash = gleam@string:replace(
Escaped_question,
<<"#"/utf8>>,
<<"%23"/utf8>>
),
gleam@string:replace(Escaped_hash, <<"/"/utf8>>, <<"%2F"/utf8>>).
-file("src/lightspeed/framework/verified_routes.gleam", 399).
-spec query_string(list({binary(), binary()})) -> binary().
query_string(Query) ->
case Query of
[] ->
<<""/utf8>>;
Pairs ->
Rendered = gleam@list:map(
Pairs,
fun(Pair) ->
{Key, Value} = Pair,
<<<<(escape_query_piece(Key))/binary, "="/utf8>>/binary,
(escape_query_piece(Value))/binary>>
end
),
join_with(<<"&"/utf8>>, Rendered)
end.
-file("src/lightspeed/framework/verified_routes.gleam", 125).
?DOC(" Render path with query pairs. Empty query emits no `?`.\n").
-spec path_with_query(verified_route(KNZ), KNZ, list({binary(), binary()})) -> binary().
path_with_query(Route, Params, Query) ->
Base = path(Route, Params),
Rendered_query = query_string(Query),
case Rendered_query of
<<""/utf8>> ->
Base;
_ ->
<<<<Base/binary, "?"/utf8>>/binary, Rendered_query/binary>>
end.
-file("src/lightspeed/framework/verified_routes.gleam", 140).
?DOC(" Route pattern string.\n").
-spec pattern(verified_route(any())) -> binary().
pattern(Route) ->
erlang:element(2, Route).
-file("src/lightspeed/framework/verified_routes.gleam", 145).
?DOC(" Route param-name contract for deterministic verification checks.\n").
-spec param_names(verified_route(any())) -> list(binary()).
param_names(Route) ->
erlang:element(3, Route).
-file("src/lightspeed/framework/verified_routes.gleam", 150).
?DOC(" Create an empty router index.\n").
-spec new_index() -> router_index().
new_index() ->
{router_index, []}.
-file("src/lightspeed/framework/verified_routes.gleam", 370).
-spec add_index_entry(router_index(), indexed_route(any(), any())) -> router_index().
add_index_entry(Index, Route) ->
Meta = {indexed_meta,
erlang:element(2, Route),
erlang:element(3, Route),
erlang:element(2, erlang:element(4, Route)),
erlang:element(3, erlang:element(4, Route))},
{router_index, [Meta | erlang:element(2, Index)]}.
-file("src/lightspeed/framework/verified_routes.gleam", 155).
?DOC(" Register a named GET zero-param route in the router index.\n").
-spec index_get0(router_index(), binary(), binary()) -> {router_index(),
indexed_route(nil, get_tag())}.
index_get0(Index, Name, Pattern) ->
Route = route0(Pattern),
Indexed = {indexed_route, Name, method_get, Route},
Updated = add_index_entry(Index, Indexed),
{Updated, Indexed}.
-file("src/lightspeed/framework/verified_routes.gleam", 167).
?DOC(" Register a named GET one-param route in the router index.\n").
-spec index_get1(router_index(), binary(), binary(), binary()) -> {router_index(),
indexed_route(binary(), get_tag())}.
index_get1(Index, Name, Pattern, Param) ->
Route = route1(Pattern, Param),
Indexed = {indexed_route, Name, method_get, Route},
Updated = add_index_entry(Index, Indexed),
{Updated, Indexed}.
-file("src/lightspeed/framework/verified_routes.gleam", 180).
?DOC(" Register a named GET two-param route in the router index.\n").
-spec index_get2(router_index(), binary(), binary(), binary(), binary()) -> {router_index(),
indexed_route({binary(), binary()}, get_tag())}.
index_get2(Index, Name, Pattern, First_param, Second_param) ->
Route = route2(Pattern, First_param, Second_param),
Indexed = {indexed_route, Name, method_get, Route},
Updated = add_index_entry(Index, Indexed),
{Updated, Indexed}.
-file("src/lightspeed/framework/verified_routes.gleam", 194).
?DOC(" Register a named POST zero-param route in the router index.\n").
-spec index_post0(router_index(), binary(), binary()) -> {router_index(),
indexed_route(nil, post_tag())}.
index_post0(Index, Name, Pattern) ->
Route = route0(Pattern),
Indexed = {indexed_route, Name, method_post, Route},
Updated = add_index_entry(Index, Indexed),
{Updated, Indexed}.
-file("src/lightspeed/framework/verified_routes.gleam", 206).
?DOC(" Register a named POST one-param route in the router index.\n").
-spec index_post1(router_index(), binary(), binary(), binary()) -> {router_index(),
indexed_route(binary(), post_tag())}.
index_post1(Index, Name, Pattern, Param) ->
Route = route1(Pattern, Param),
Indexed = {indexed_route, Name, method_post, Route},
Updated = add_index_entry(Index, Indexed),
{Updated, Indexed}.
-file("src/lightspeed/framework/verified_routes.gleam", 219).
?DOC(" Access one indexed route as a legacy verified route.\n").
-spec as_verified_route(indexed_route(KOR, any())) -> verified_route(KOR).
as_verified_route(Route) ->
erlang:element(4, Route).
-file("src/lightspeed/framework/verified_routes.gleam", 226).
?DOC(" Indexed route label.\n").
-spec indexed_name(indexed_route(any(), any())) -> binary().
indexed_name(Route) ->
erlang:element(2, Route).
-file("src/lightspeed/framework/verified_routes.gleam", 231).
?DOC(" Indexed route method.\n").
-spec indexed_method(indexed_route(any(), any())) -> route_method().
indexed_method(Route) ->
erlang:element(3, Route).
-file("src/lightspeed/framework/verified_routes.gleam", 236).
?DOC(" Indexed route static pattern path.\n").
-spec static_path(indexed_route(any(), any())) -> binary().
static_path(Route) ->
erlang:element(2, erlang:element(4, Route)).
-file("src/lightspeed/framework/verified_routes.gleam", 241).
?DOC(" Render path for one indexed route.\n").
-spec path_from_indexed(indexed_route(KPI, any()), KPI) -> binary().
path_from_indexed(Route, Params) ->
path(erlang:element(4, Route), Params).
-file("src/lightspeed/framework/verified_routes.gleam", 249).
?DOC(" Render path with query for one indexed route.\n").
-spec path_with_query_from_indexed(
indexed_route(KPM, any()),
KPM,
list({binary(), binary()})
) -> binary().
path_with_query_from_indexed(Route, Params, Query) ->
path_with_query(erlang:element(4, Route), Params, Query).
-file("src/lightspeed/framework/verified_routes.gleam", 258).
?DOC(" Build a zero-parameter unchecked reference.\n").
-spec reference0(binary(), route_method()) -> route_reference().
reference0(Name, Method) ->
{route_reference, Name, Method, []}.
-file("src/lightspeed/framework/verified_routes.gleam", 263).
?DOC(" Build a one-parameter unchecked reference.\n").
-spec reference1(binary(), route_method(), binary()) -> route_reference().
reference1(Name, Method, Param) ->
{route_reference, Name, Method, [Param]}.
-file("src/lightspeed/framework/verified_routes.gleam", 272).
?DOC(" Build a two-parameter unchecked reference.\n").
-spec reference2(binary(), route_method(), binary(), binary()) -> route_reference().
reference2(Name, Method, First_param, Second_param) ->
{route_reference, Name, Method, [First_param, Second_param]}.
-file("src/lightspeed/framework/verified_routes.gleam", 385).
-spec find_route(list(indexed_meta()), binary()) -> {ok, indexed_meta()} |
{error, nil}.
find_route(Routes, Name) ->
case Routes of
[] ->
{error, nil};
[Route | Rest] ->
case erlang:element(2, Route) =:= Name of
true ->
{ok, Route};
false ->
find_route(Rest, Name)
end
end.
-file("src/lightspeed/framework/verified_routes.gleam", 288).
?DOC(
" Verify one unchecked reference against the indexed route table.\n"
"\n"
" This models compile-time route verification fixtures with deterministic\n"
" diagnostics.\n"
).
-spec compile_reference(router_index(), route_reference()) -> {ok, nil} |
{error, route_diagnostic()}.
compile_reference(Index, Reference) ->
case find_route(erlang:element(2, Index), erlang:element(2, Reference)) of
{error, _} ->
{error, {unknown_route, erlang:element(2, Reference)}};
{ok, Meta} ->
case erlang:element(3, Meta) =:= erlang:element(3, Reference) of
false ->
{error,
{method_mismatch,
erlang:element(2, Reference),
erlang:element(3, Meta),
erlang:element(3, Reference)}};
true ->
case erlang:element(5, Meta) =:= erlang:element(
4,
Reference
) of
true ->
{ok, nil};
false ->
{error,
{param_mismatch,
erlang:element(2, Reference),
erlang:element(5, Meta),
erlang:element(4, Reference)}}
end
end
end.
-file("src/lightspeed/framework/verified_routes.gleam", 342).
?DOC(" Stable method label.\n").
-spec method_label(route_method()) -> binary().
method_label(Method) ->
case Method of
method_get ->
<<"GET"/utf8>>;
method_post ->
<<"POST"/utf8>>;
method_put ->
<<"PUT"/utf8>>;
method_patch ->
<<"PATCH"/utf8>>;
method_delete ->
<<"DELETE"/utf8>>
end.
-file("src/lightspeed/framework/verified_routes.gleam", 319).
?DOC(" Stable compile diagnostic label for fixture assertions.\n").
-spec diagnostic_label(route_diagnostic()) -> binary().
diagnostic_label(Diagnostic) ->
case Diagnostic of
{unknown_route, Name} ->
<<"unknown_route:"/utf8, Name/binary>>;
{method_mismatch, Name@1, Expected, Actual} ->
<<<<<<<<<<"method_mismatch:"/utf8, Name@1/binary>>/binary,
":expected="/utf8>>/binary,
(method_label(Expected))/binary>>/binary,
":actual="/utf8>>/binary,
(method_label(Actual))/binary>>;
{param_mismatch, Name@2, Expected@1, Actual@1} ->
<<<<<<<<<<"param_mismatch:"/utf8, Name@2/binary>>/binary,
":expected="/utf8>>/binary,
(join_with(<<","/utf8>>, Expected@1))/binary>>/binary,
":actual="/utf8>>/binary,
(join_with(<<","/utf8>>, Actual@1))/binary>>
end.
-file("src/lightspeed/framework/verified_routes.gleam", 353).
?DOC(" Stable router-index signature for deterministic fixture assertions.\n").
-spec index_signature(router_index()) -> binary().
index_signature(Index) ->
Labels = begin
_pipe = erlang:element(2, Index),
_pipe@1 = lists:reverse(_pipe),
gleam@list:map(
_pipe@1,
fun(Meta) ->
<<<<<<<<<<<<(erlang:element(2, Meta))/binary, "@"/utf8>>/binary,
(method_label(erlang:element(3, Meta)))/binary>>/binary,
"@"/utf8>>/binary,
(erlang:element(4, Meta))/binary>>/binary,
"@params="/utf8>>/binary,
(join_with(<<","/utf8>>, erlang:element(5, Meta)))/binary>>
end
)
end,
join_with(<<";"/utf8>>, Labels).