Current section

Files

Jump to
oaspec src oaspec@transport.erl
Raw

src/oaspec@transport.erl

-module(oaspec@transport).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/transport.gleam").
-export([from_callback/1, resolve/1, run/2, map/2, await/2, map_try/2, try_await/2, credentials/0, with_api_key/3, with_bearer_token/3, with_basic_auth/3, with_digest_auth/3, with_base_url/2, with_default_header/3, with_default_headers/2, with_security/2]).
-export_type([method/0, body/0, security_requirement/0, security_alternative/0, request/0, response/0, transport_error/0, async/1, credentials/0, credential_entry/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(
" Pure, runtime-agnostic transport contract for generated OpenAPI clients.\n"
"\n"
" Generated client code depends on this module instead of any concrete\n"
" HTTP runtime. Adapters (e.g. `oaspec/httpc`, `oaspec/fetch`) bridge\n"
" `Send` / `AsyncSend` to a real runtime; tests can plug in arbitrary\n"
" fake transport values via `oaspec/mock`.\n"
).
-type method() :: get |
post |
put |
delete |
patch |
head |
options |
trace |
connect.
-type body() :: empty_body | {text_body, binary()} | {bytes_body, bitstring()}.
-type security_requirement() :: {api_key_header, binary(), binary()} |
{api_key_query, binary(), binary()} |
{api_key_cookie, binary(), binary()} |
{http_authorization, binary(), binary()}.
-type security_alternative() :: {security_alternative,
list(security_requirement())}.
-type request() :: {request,
method(),
gleam@option:option(binary()),
binary(),
list({binary(), binary()}),
list({binary(), binary()}),
body(),
list(security_alternative())}.
-type response() :: {response, integer(), list({binary(), binary()}), body()}.
-type transport_error() :: {connection_failed, binary()} |
timeout |
{invalid_base_url, binary()} |
{tls_failure, binary()} |
{unsupported, binary()}.
-opaque async(AANP) :: {async, fun((fun((AANP) -> nil)) -> nil)}.
-opaque credentials() :: {credentials, list(credential_entry())}.
-type credential_entry() :: {cred_api_key, binary(), binary()} |
{cred_bearer, binary(), binary()} |
{cred_basic, binary(), binary()} |
{cred_digest, binary(), binary()}.
-file("src/oaspec/transport.gleam", 90).
-spec from_callback(fun((fun((AANV) -> nil)) -> nil)) -> async(AANV).
from_callback(Register) ->
{async, Register}.
-file("src/oaspec/transport.gleam", 96).
-spec resolve(AANX) -> async(AANX).
resolve(Value) ->
{async, fun(Done) -> Done(Value) end}.
-file("src/oaspec/transport.gleam", 100).
-spec run(async(AANZ), fun((AANZ) -> nil)) -> nil.
run(Async, Done) ->
{async, Register} = Async,
Register(Done).
-file("src/oaspec/transport.gleam", 105).
-spec map(async(AAOB), fun((AAOB) -> AAOD)) -> async(AAOD).
map(Async, With_) ->
{async, fun(Done) -> run(Async, fun(Value) -> Done(With_(Value)) end) end}.
-file("src/oaspec/transport.gleam", 109).
-spec await(async(AAOF), fun((AAOF) -> async(AAOH))) -> async(AAOH).
await(Async, Next) ->
{async,
fun(Done) -> run(Async, fun(Value) -> run(Next(Value), Done) end) end}.
-file("src/oaspec/transport.gleam", 115).
-spec map_try(
async({ok, AAOK} | {error, AAOL}),
fun((AAOK) -> {ok, AAOP} | {error, AAOL})
) -> async({ok, AAOP} | {error, AAOL}).
map_try(Async, With_) ->
_pipe = Async,
map(_pipe, fun(Result) -> case Result of
{ok, Value} ->
With_(Value);
{error, Error} ->
{error, Error}
end end).
-file("src/oaspec/transport.gleam", 128).
-spec try_await(
async({ok, AAOV} | {error, AAOW}),
fun((AAOV) -> async({ok, AAPA} | {error, AAOW}))
) -> async({ok, AAPA} | {error, AAOW}).
try_await(Async, Next) ->
_pipe = Async,
await(_pipe, fun(Result) -> case Result of
{ok, Value} ->
Next(Value);
{error, Error} ->
resolve({error, Error})
end end).
-file("src/oaspec/transport.gleam", 159).
-spec credentials() -> credentials().
credentials() ->
{credentials, []}.
-file("src/oaspec/transport.gleam", 195).
-spec add_credential(credentials(), credential_entry()) -> credentials().
add_credential(Creds, Entry) ->
{credentials, Entries} = Creds,
{credentials, lists:append(Entries, [Entry])}.
-file("src/oaspec/transport.gleam", 163).
-spec with_api_key(credentials(), binary(), binary()) -> credentials().
with_api_key(Creds, Scheme_name, Value) ->
add_credential(Creds, {cred_api_key, Scheme_name, Value}).
-file("src/oaspec/transport.gleam", 171).
-spec with_bearer_token(credentials(), binary(), binary()) -> credentials().
with_bearer_token(Creds, Scheme_name, Token) ->
add_credential(Creds, {cred_bearer, Scheme_name, Token}).
-file("src/oaspec/transport.gleam", 179).
-spec with_basic_auth(credentials(), binary(), binary()) -> credentials().
with_basic_auth(Creds, Scheme_name, Value) ->
add_credential(Creds, {cred_basic, Scheme_name, Value}).
-file("src/oaspec/transport.gleam", 187).
-spec with_digest_auth(credentials(), binary(), binary()) -> credentials().
with_digest_auth(Creds, Scheme_name, Value) ->
add_credential(Creds, {cred_digest, Scheme_name, Value}).
-file("src/oaspec/transport.gleam", 208).
-spec with_base_url(fun((request()) -> AAPH), binary()) -> fun((request()) -> AAPH).
with_base_url(Send, Base_url) ->
fun(Req) ->
Send(
{request,
erlang:element(2, Req),
{some, Base_url},
erlang:element(4, Req),
erlang:element(5, Req),
erlang:element(6, Req),
erlang:element(7, Req),
erlang:element(8, Req)}
)
end.
-file("src/oaspec/transport.gleam", 283).
-spec has_header(list({binary(), binary()}), binary()) -> boolean().
has_header(Headers, Name) ->
Lowered = string:lowercase(Name),
gleam@list:any(
Headers,
fun(H) ->
{K, _} = H,
string:lowercase(K) =:= Lowered
end
).
-file("src/oaspec/transport.gleam", 218).
-spec with_default_header(fun((request()) -> AAPI), binary(), binary()) -> fun((request()) -> AAPI).
with_default_header(Send, Name, Value) ->
fun(Req) -> case has_header(erlang:element(6, Req), Name) of
true ->
Send(Req);
false ->
Send(
{request,
erlang:element(2, Req),
erlang:element(3, Req),
erlang:element(4, Req),
erlang:element(5, Req),
lists:append(erlang:element(6, Req), [{Name, Value}]),
erlang:element(7, Req),
erlang:element(8, Req)}
)
end end.
-file("src/oaspec/transport.gleam", 237).
-spec with_default_headers(fun((request()) -> AAPJ), list({binary(), binary()})) -> fun((request()) -> AAPJ).
with_default_headers(Send, Headers) ->
fun(Req) ->
Merged_rev = gleam@list:fold(
Headers,
lists:reverse(erlang:element(6, Req)),
fun(Acc_rev, Kv) ->
{Name, Value} = Kv,
case has_header(Acc_rev, Name) of
true ->
Acc_rev;
false ->
[{Name, Value} | Acc_rev]
end
end
),
Send(
{request,
erlang:element(2, Req),
erlang:element(3, Req),
erlang:element(4, Req),
erlang:element(5, Req),
lists:reverse(Merged_rev),
erlang:element(7, Req),
erlang:element(8, Req)}
)
end.
-file("src/oaspec/transport.gleam", 318).
-spec credential_matches(credential_entry(), security_requirement()) -> boolean().
credential_matches(Cred, Req) ->
case {Cred, Req} of
{{cred_api_key, S, _}, {api_key_header, T, _}} when S =:= T ->
true;
{{cred_api_key, S@1, _}, {api_key_query, T@1, _}} when S@1 =:= T@1 ->
true;
{{cred_api_key, S@2, _}, {api_key_cookie, T@2, _}} when S@2 =:= T@2 ->
true;
{{cred_bearer, S@3, _}, {http_authorization, T@3, Prefix}} when S@3 =:= T@3 ->
string:lowercase(Prefix) =:= <<"bearer"/utf8>>;
{{cred_basic, S@4, _}, {http_authorization, T@4, Prefix@1}} when S@4 =:= T@4 ->
string:lowercase(Prefix@1) =:= <<"basic"/utf8>>;
{{cred_digest, S@5, _}, {http_authorization, T@5, Prefix@2}} when S@5 =:= T@5 ->
string:lowercase(Prefix@2) =:= <<"digest"/utf8>>;
{_, _} ->
false
end.
-file("src/oaspec/transport.gleam", 309).
-spec find_credential(credentials(), security_requirement()) -> gleam@option:option(credential_entry()).
find_credential(Creds, Req) ->
{credentials, Entries} = Creds,
_pipe = gleam@list:find(Entries, fun(C) -> credential_matches(C, Req) end),
gleam@option:from_result(_pipe).
-file("src/oaspec/transport.gleam", 305).
-spec satisfiable(security_alternative(), credentials()) -> boolean().
satisfiable(Alt, Creds) ->
gleam@list:all(
erlang:element(2, Alt),
fun(Req) -> find_credential(Creds, Req) /= none end
).
-file("src/oaspec/transport.gleam", 291).
-spec pick_alternative(list(security_alternative()), credentials()) -> gleam@option:option(security_alternative()).
pick_alternative(Alts, Creds) ->
case Alts of
[] ->
none;
[Alt | Rest] ->
case satisfiable(Alt, Creds) of
true ->
{some, Alt};
false ->
pick_alternative(Rest, Creds)
end
end.
-file("src/oaspec/transport.gleam", 374).
-spec set_authorization(request(), binary(), binary()) -> request().
set_authorization(Req, Prefix, Value) ->
Header_value = <<<<Prefix/binary, " "/utf8>>/binary, Value/binary>>,
{request,
erlang:element(2, Req),
erlang:element(3, Req),
erlang:element(4, Req),
erlang:element(5, Req),
lists:append(
erlang:element(6, Req),
[{<<"authorization"/utf8>>, Header_value}]
),
erlang:element(7, Req),
erlang:element(8, Req)}.
-file("src/oaspec/transport.gleam", 386).
-spec merge_cookie(request(), binary(), binary()) -> request().
merge_cookie(Req, Cookie_name, Value) ->
Pair = <<<<Cookie_name/binary, "="/utf8>>/binary, Value/binary>>,
Lowered = <<"cookie"/utf8>>,
{Existing, Others} = gleam@list:partition(
erlang:element(6, Req),
fun(H) ->
{K, _} = H,
string:lowercase(K) =:= Lowered
end
),
Merged_value = case Existing of
[] ->
Pair;
[_ | _] ->
_pipe = gleam@list:map(
Existing,
fun(H@1) ->
{_, V} = H@1,
V
end
),
_pipe@1 = lists:append(_pipe, [Pair]),
gleam@string:join(_pipe@1, <<"; "/utf8>>)
end,
{request,
erlang:element(2, Req),
erlang:element(3, Req),
erlang:element(4, Req),
erlang:element(5, Req),
lists:append(Others, [{<<"Cookie"/utf8>>, Merged_value}]),
erlang:element(7, Req),
erlang:element(8, Req)}.
-file("src/oaspec/transport.gleam", 346).
-spec apply_one(request(), security_requirement(), credential_entry()) -> request().
apply_one(Req, Requirement, Cred) ->
case {Requirement, Cred} of
{{api_key_header, _, Header_name}, {cred_api_key, _, Value}} ->
{request,
erlang:element(2, Req),
erlang:element(3, Req),
erlang:element(4, Req),
erlang:element(5, Req),
lists:append(erlang:element(6, Req), [{Header_name, Value}]),
erlang:element(7, Req),
erlang:element(8, Req)};
{{api_key_query, _, Query_name}, {cred_api_key, _, Value@1}} ->
{request,
erlang:element(2, Req),
erlang:element(3, Req),
erlang:element(4, Req),
lists:append(erlang:element(5, Req), [{Query_name, Value@1}]),
erlang:element(6, Req),
erlang:element(7, Req),
erlang:element(8, Req)};
{{api_key_cookie, _, Cookie_name}, {cred_api_key, _, Value@2}} ->
merge_cookie(Req, Cookie_name, Value@2);
{{http_authorization, _, Prefix}, {cred_bearer, _, Token}} ->
set_authorization(Req, Prefix, Token);
{{http_authorization, _, Prefix@1}, {cred_basic, _, Value@3}} ->
set_authorization(Req, Prefix@1, Value@3);
{{http_authorization, _, Prefix@2}, {cred_digest, _, Value@4}} ->
set_authorization(Req, Prefix@2, Value@4);
{_, _} ->
Req
end.
-file("src/oaspec/transport.gleam", 333).
-spec apply_alternative(request(), security_alternative(), credentials()) -> request().
apply_alternative(Req, Alt, Creds) ->
gleam@list:fold(
erlang:element(2, Alt),
Req,
fun(Acc, Requirement) -> case find_credential(Creds, Requirement) of
{some, Cred} ->
apply_one(Acc, Requirement, Cred);
none ->
Acc
end end
).
-file("src/oaspec/transport.gleam", 266).
-spec with_security(fun((request()) -> AAPL), credentials()) -> fun((request()) -> AAPL).
with_security(Send, Creds) ->
fun(Req) ->
Prepared = case pick_alternative(erlang:element(8, Req), Creds) of
{some, Alt} ->
apply_alternative(Req, Alt, Creds);
none ->
Req
end,
Send(Prepared)
end.