Current section

Files

Jump to
oaspec src oaspec@config.erl
Raw

src/oaspec@config.erl

-module(oaspec@config).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/config.gleam").
-export([parse_mode/1, with_mode/2, with_output/2, validate_output_package_match/1, error_to_string/1, load/1]).
-export_type([config/0, generate_mode/0, config_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.
-type config() :: {config,
binary(),
binary(),
binary(),
binary(),
generate_mode()}.
-type generate_mode() :: server | client | both.
-type config_error() :: {file_not_found, binary()} |
{file_read_error, binary(), binary()} |
{parse_error, binary()} |
{missing_field, binary()} |
{invalid_value, binary(), binary()}.
-file("src/oaspec/config.gleam", 36).
?DOC(" Parse a mode string into GenerateMode.\n").
-spec parse_mode(binary()) -> {ok, generate_mode()} | {error, config_error()}.
parse_mode(Mode) ->
case Mode of
<<"server"/utf8>> ->
{ok, server};
<<"client"/utf8>> ->
{ok, client};
<<"both"/utf8>> ->
{ok, both};
_ ->
{error,
{invalid_value,
<<"mode"/utf8>>,
<<"must be one of: server, client, both"/utf8>>}}
end.
-file("src/oaspec/config.gleam", 112).
?DOC(" Apply CLI overrides to a config.\n").
-spec with_mode(config(), generate_mode()) -> config().
with_mode(Config, Mode) ->
{config,
erlang:element(2, Config),
erlang:element(3, Config),
erlang:element(4, Config),
erlang:element(5, Config),
Mode}.
-file("src/oaspec/config.gleam", 118).
?DOC(
" Apply output base directory override.\n"
" Derives server/client paths as <dir>/<package> and <dir>_client/<package>.\n"
).
-spec with_output(config(), gleam@option:option(binary())) -> config().
with_output(Config, Output) ->
case Output of
{some, Dir} ->
{config,
erlang:element(2, Config),
<<<<Dir/binary, "/"/utf8>>/binary,
(erlang:element(5, Config))/binary>>,
<<<<Dir/binary, "_client/"/utf8>>/binary,
(erlang:element(5, Config))/binary>>,
erlang:element(5, Config),
erlang:element(6, Config)};
none ->
Config
end.
-file("src/oaspec/config.gleam", 170).
?DOC(" Get the basename of a path (last segment after /).\n").
-spec basename(binary()) -> binary().
basename(Path) ->
_pipe = Path,
_pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>),
_pipe@2 = gleam@list:last(_pipe@1),
gleam@result:unwrap(_pipe@2, <<""/utf8>>).
-file("src/oaspec/config.gleam", 132).
?DOC(
" Validate that output directory basenames match the package name.\n"
" Gleam imports require `import <package>/types`, so the directory must match.\n"
).
-spec validate_output_package_match(config()) -> {ok, nil} |
{error, config_error()}.
validate_output_package_match(Config) ->
_pipe = case erlang:element(6, Config) of
server ->
case basename(erlang:element(3, Config)) =:= erlang:element(
5,
Config
) of
true ->
{ok, nil};
false ->
{error,
{invalid_value,
<<"output.server"/utf8>>,
<<<<<<<<"Directory basename '"/utf8,
(basename(erlang:element(3, Config)))/binary>>/binary,
"' must match package '"/utf8>>/binary,
(erlang:element(5, Config))/binary>>/binary,
"'"/utf8>>}}
end;
both ->
case basename(erlang:element(3, Config)) =:= erlang:element(
5,
Config
) of
true ->
{ok, nil};
false ->
{error,
{invalid_value,
<<"output.server"/utf8>>,
<<<<<<<<"Directory basename '"/utf8,
(basename(erlang:element(3, Config)))/binary>>/binary,
"' must match package '"/utf8>>/binary,
(erlang:element(5, Config))/binary>>/binary,
"'"/utf8>>}}
end;
client ->
{ok, nil}
end,
gleam@result:'try'(_pipe, fun(_) -> case erlang:element(6, Config) of
client ->
case basename(erlang:element(4, Config)) =:= erlang:element(
5,
Config
) of
true ->
{ok, nil};
false ->
{error,
{invalid_value,
<<"output.client"/utf8>>,
<<<<<<<<"Directory basename '"/utf8,
(basename(
erlang:element(
4,
Config
)
))/binary>>/binary,
"' must match package '"/utf8>>/binary,
(erlang:element(5, Config))/binary>>/binary,
"'"/utf8>>}}
end;
both ->
case basename(erlang:element(4, Config)) =:= erlang:element(
5,
Config
) of
true ->
{ok, nil};
false ->
{error,
{invalid_value,
<<"output.client"/utf8>>,
<<<<<<<<"Directory basename '"/utf8,
(basename(
erlang:element(
4,
Config
)
))/binary>>/binary,
"' must match package '"/utf8>>/binary,
(erlang:element(5, Config))/binary>>/binary,
"'"/utf8>>}}
end;
server ->
{ok, nil}
end end).
-file("src/oaspec/config.gleam", 178).
?DOC(" Convert config error to a human-readable string.\n").
-spec error_to_string(config_error()) -> binary().
error_to_string(Error) ->
case Error of
{file_not_found, Path} ->
<<"Config file not found: "/utf8, Path/binary>>;
{file_read_error, Path@1, Detail} ->
<<<<<<"Error reading config file "/utf8, Path@1/binary>>/binary,
": "/utf8>>/binary,
Detail/binary>>;
{parse_error, Detail@1} ->
<<"Config parse error: "/utf8, Detail@1/binary>>;
{missing_field, Field} ->
<<"Missing required config field: "/utf8, Field/binary>>;
{invalid_value, Field@1, Detail@2} ->
<<<<<<"Invalid value for "/utf8, Field@1/binary>>/binary,
": "/utf8>>/binary,
Detail@2/binary>>
end.
-file("src/oaspec/config.gleam", 191).
?DOC(" Extract a nested string value from YAML like output.server.\n").
-spec extract_nested_string(yay:node_(), binary(), binary()) -> gleam@option:option(binary()).
extract_nested_string(Root, Key1, Key2) ->
case yay:select_sugar(
Root,
<<<<Key1/binary, "."/utf8>>/binary, Key2/binary>>
) of
{ok, {node_str, Value}} ->
{some, Value};
_ ->
none
end.
-file("src/oaspec/config.gleam", 203).
?DOC(" Convert a yay YAML error to string.\n").
-spec yaml_error_to_string(yay:yaml_error()) -> binary().
yaml_error_to_string(Error) ->
case Error of
unexpected_parsing_error ->
<<"Unexpected parsing error"/utf8>>;
{parsing_error, Msg, _} ->
Msg
end.
-file("src/oaspec/config.gleam", 50).
?DOC(" Load config from a YAML file.\n").
-spec load(binary()) -> {ok, config()} | {error, config_error()}.
load(Path) ->
gleam@result:'try'(
begin
_pipe = simplifile:read(Path),
gleam@result:map_error(_pipe, fun(_) -> {file_not_found, Path} end)
end,
fun(Content) ->
gleam@result:'try'(
begin
_pipe@1 = yaml_ffi:parse_string(Content),
gleam@result:map_error(
_pipe@1,
fun(E) ->
{parse_error,
<<"YAML parse error: "/utf8,
(yaml_error_to_string(E))/binary>>}
end
)
end,
fun(Docs) -> gleam@result:'try'(case Docs of
[First | _] ->
{ok, First};
[] ->
{error,
{parse_error,
<<"Empty YAML document"/utf8>>}}
end, fun(Doc) ->
Root = yay:document_root(Doc),
gleam@result:'try'(
begin
_pipe@2 = yay:extract_string(
Root,
<<"input"/utf8>>
),
gleam@result:map_error(
_pipe@2,
fun(_) ->
{missing_field, <<"input"/utf8>>}
end
)
end,
fun(Input) ->
Package = begin
_pipe@3 = yay:extract_optional_string(
Root,
<<"package"/utf8>>
),
_pipe@4 = gleam@result:unwrap(
_pipe@3,
none
),
gleam@option:unwrap(
_pipe@4,
<<"api"/utf8>>
)
end,
Output_dir = begin
_pipe@5 = extract_nested_string(
Root,
<<"output"/utf8>>,
<<"dir"/utf8>>
),
gleam@option:unwrap(
_pipe@5,
<<"./gen"/utf8>>
)
end,
Output_server = begin
_pipe@6 = extract_nested_string(
Root,
<<"output"/utf8>>,
<<"server"/utf8>>
),
gleam@option:unwrap(
_pipe@6,
<<<<Output_dir/binary, "/"/utf8>>/binary,
Package/binary>>
)
end,
Output_client = begin
_pipe@7 = extract_nested_string(
Root,
<<"output"/utf8>>,
<<"client"/utf8>>
),
gleam@option:unwrap(
_pipe@7,
<<<<Output_dir/binary,
"_client/"/utf8>>/binary,
Package/binary>>
)
end,
gleam@result:'try'(
case begin
_pipe@8 = yay:extract_optional_string(
Root,
<<"mode"/utf8>>
),
gleam@result:unwrap(_pipe@8, none)
end of
{some, <<"server"/utf8>>} ->
{ok, server};
{some, <<"client"/utf8>>} ->
{ok, client};
{some, <<"both"/utf8>>} ->
{ok, both};
none ->
{ok, both};
{some, Other} ->
{error,
{invalid_value,
<<"mode"/utf8>>,
<<<<"must be one of: server, client, both (got: "/utf8,
Other/binary>>/binary,
")"/utf8>>}}
end,
fun(Mode) ->
{ok,
{config,
Input,
Output_server,
Output_client,
Package,
Mode}}
end
)
end
)
end) end
)
end
).