-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] -> <<<>/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; _ -> <<<>/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).