Packages
oaspec
0.47.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.1
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.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.3
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.1.3
Generate Gleam code from OpenAPI 3.x specifications
Current section
Files
Jump to
Current section
Files
src/oaspec@internal@cli.erl
-module(oaspec@internal@cli).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/internal/cli.gleam").
-export([resolve_path_from_cwd/2, resolved_path_entries/3, app/0]).
-export_type([duplicate_output_path_error/0, load_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.
?MODULEDOC(false).
-type duplicate_output_path_error() :: {duplicate_output_path, binary()}.
-type load_config_error() :: {config_load_error, oaspec@config:config_error()} |
{mode_parse_error, oaspec@config:config_error()} |
{output_validation_error, oaspec@config:config_error()}.
-file("src/oaspec/internal/cli.gleam", 30).
?DOC(false).
-spec maybe_pretty_help(glint:glint(XSI)) -> glint:glint(XSI).
maybe_pretty_help(Glint) ->
case {oaspec_ffi:is_stdout_tty(), oaspec_ffi:no_color_set()} of
{true, false} ->
glint:pretty_help(Glint, glint:default_pretty_help());
{_, _} ->
Glint
end.
-file("src/oaspec/internal/cli.gleam", 60).
?DOC(false).
-spec version_command() -> glint:command(nil).
version_command() ->
glint:command_help(
<<"Print the oaspec version and exit"/utf8>>,
fun() ->
glint:command(
fun(_, _, _) ->
gleam_stdlib:println(
<<"oaspec v"/utf8, (<<"0.47.0"/utf8>>)/binary>>
)
end
)
end
).
-file("src/oaspec/internal/cli.gleam", 463).
?DOC(false).
-spec active_output_paths(oaspec@config:config()) -> list(binary()).
active_output_paths(Cfg) ->
case oaspec@config:mode(Cfg) of
server ->
[oaspec@config:output_server(Cfg)];
client ->
[oaspec@config:output_client(Cfg)];
both ->
[oaspec@config:output_server(Cfg), oaspec@config:output_client(Cfg)]
end.
-file("src/oaspec/internal/cli.gleam", 479).
?DOC(false).
-spec find_duplicate_path(list(binary()), list(binary())) -> {ok, nil} |
{error, duplicate_output_path_error()}.
find_duplicate_path(Remaining, Seen) ->
case Remaining of
[] ->
{ok, nil};
[Path | Rest] ->
case gleam@list:contains(Seen, Path) of
true ->
{error, {duplicate_output_path, Path}};
false ->
find_duplicate_path(Rest, [Path | Seen])
end
end.
-file("src/oaspec/internal/cli.gleam", 445).
?DOC(false).
-spec validate_no_target_overlap(list(oaspec@config:config())) -> {ok, nil} |
{error, load_config_error()}.
validate_no_target_overlap(Cfgs) ->
Paths = begin
_pipe = Cfgs,
gleam@list:flat_map(_pipe, fun(Cfg) -> active_output_paths(Cfg) end)
end,
_pipe@1 = find_duplicate_path(Paths, []),
gleam@result:map_error(
_pipe@1,
fun(Err) ->
{duplicate_output_path, Path} = Err,
{output_validation_error,
{invalid_value,
<<"targets"/utf8>>,
<<<<"two targets resolve to the same output directory '"/utf8,
Path/binary>>/binary,
"' — give them distinct package or output paths so generated files do not clobber each other"/utf8>>}}
end
).
-file("src/oaspec/internal/cli.gleam", 558).
?DOC(false).
-spec is_ascii_letter(binary()) -> boolean().
is_ascii_letter(Value) ->
case string:lowercase(Value) of
<<"a"/utf8>> ->
true;
<<"b"/utf8>> ->
true;
<<"c"/utf8>> ->
true;
<<"d"/utf8>> ->
true;
<<"e"/utf8>> ->
true;
<<"f"/utf8>> ->
true;
<<"g"/utf8>> ->
true;
<<"h"/utf8>> ->
true;
<<"i"/utf8>> ->
true;
<<"j"/utf8>> ->
true;
<<"k"/utf8>> ->
true;
<<"l"/utf8>> ->
true;
<<"m"/utf8>> ->
true;
<<"n"/utf8>> ->
true;
<<"o"/utf8>> ->
true;
<<"p"/utf8>> ->
true;
<<"q"/utf8>> ->
true;
<<"r"/utf8>> ->
true;
<<"s"/utf8>> ->
true;
<<"t"/utf8>> ->
true;
<<"u"/utf8>> ->
true;
<<"v"/utf8>> ->
true;
<<"w"/utf8>> ->
true;
<<"x"/utf8>> ->
true;
<<"y"/utf8>> ->
true;
<<"z"/utf8>> ->
true;
_ ->
false
end.
-file("src/oaspec/internal/cli.gleam", 549).
?DOC(false).
-spec is_windows_drive_absolute(binary()) -> boolean().
is_windows_drive_absolute(Path) ->
Prefix = gleam@string:slice(Path, 0, 3),
case gleam@string:to_graphemes(Prefix) of
[Drive, <<":"/utf8>>, Slash] ->
is_ascii_letter(Drive) andalso ((Slash =:= <<"/"/utf8>>) orelse (Slash
=:= <<"\\"/utf8>>));
_ ->
false
end.
-file("src/oaspec/internal/cli.gleam", 542).
?DOC(false).
-spec path_is_absolute(binary()) -> boolean().
path_is_absolute(Path) ->
((filepath:is_absolute(Path) orelse gleam_stdlib:string_starts_with(
Path,
<<"\\\\"/utf8>>
))
orelse gleam_stdlib:string_starts_with(Path, <<"//"/utf8>>))
orelse is_windows_drive_absolute(Path).
-file("src/oaspec/internal/cli.gleam", 534).
?DOC(false).
-spec resolve_path_from_cwd(binary(), binary()) -> binary().
resolve_path_from_cwd(Path, Cwd) ->
Candidate = case path_is_absolute(Path) of
true ->
Path;
false ->
filepath:join(Cwd, Path)
end,
_pipe = filepath:expand(Candidate),
gleam@result:unwrap(_pipe, Candidate).
-file("src/oaspec/internal/cli.gleam", 410).
?DOC(false).
-spec print_target_outputs(oaspec@config:config(), binary(), binary()) -> nil.
print_target_outputs(Cfg, Cwd, Prefix) ->
case oaspec@config:mode(Cfg) of
server ->
gleam_stdlib:println(
<<<<Prefix/binary, "output.server: "/utf8>>/binary,
(resolve_path_from_cwd(
oaspec@config:output_server(Cfg),
Cwd
))/binary>>
);
client ->
gleam_stdlib:println(
<<<<Prefix/binary, "output.client: "/utf8>>/binary,
(resolve_path_from_cwd(
oaspec@config:output_client(Cfg),
Cwd
))/binary>>
);
both ->
gleam_stdlib:println(
<<<<Prefix/binary, "output.server: "/utf8>>/binary,
(resolve_path_from_cwd(
oaspec@config:output_server(Cfg),
Cwd
))/binary>>
),
gleam_stdlib:println(
<<<<Prefix/binary, "output.client: "/utf8>>/binary,
(resolve_path_from_cwd(
oaspec@config:output_client(Cfg),
Cwd
))/binary>>
)
end.
-file("src/oaspec/internal/cli.gleam", 509).
?DOC(false).
-spec resolved_path_entries(binary(), oaspec@config:config(), binary()) -> list({binary(),
binary()}).
resolved_path_entries(Config_path, Cfg, Cwd) ->
Base_entries = [{<<"config"/utf8>>, resolve_path_from_cwd(Config_path, Cwd)},
{<<"input"/utf8>>, resolve_path_from_cwd(oaspec@config:input(Cfg), Cwd)}],
Output_entries = case oaspec@config:mode(Cfg) of
server ->
[{<<"output.server"/utf8>>,
resolve_path_from_cwd(oaspec@config:output_server(Cfg), Cwd)}];
client ->
[{<<"output.client"/utf8>>,
resolve_path_from_cwd(oaspec@config:output_client(Cfg), Cwd)}];
both ->
[{<<"output.server"/utf8>>,
resolve_path_from_cwd(oaspec@config:output_server(Cfg), Cwd)},
{<<"output.client"/utf8>>,
resolve_path_from_cwd(oaspec@config:output_client(Cfg), Cwd)}]
end,
lists:append(Base_entries, Output_entries).
-file("src/oaspec/internal/cli.gleam", 493).
?DOC(false).
-spec print_resolved_paths(binary(), oaspec@config:config()) -> nil.
print_resolved_paths(Config_path, Cfg) ->
case simplifile:current_directory() of
{ok, Cwd} ->
gleam_stdlib:println(<<"Resolved paths:"/utf8>>),
_pipe = resolved_path_entries(Config_path, Cfg, Cwd),
gleam@list:each(
_pipe,
fun(Entry) ->
{Label, Path} = Entry,
gleam_stdlib:println(
<<<<<<" "/utf8, Label/binary>>/binary, ": "/utf8>>/binary,
Path/binary>>
)
end
);
{error, _} ->
nil
end.
-file("src/oaspec/internal/cli.gleam", 380).
?DOC(false).
-spec print_resolved_paths_for_all(binary(), list(oaspec@config:config())) -> nil.
print_resolved_paths_for_all(Config_path, Cfgs) ->
case Cfgs of
[Single] ->
print_resolved_paths(Config_path, Single);
Multiple ->
case simplifile:current_directory() of
{ok, Cwd} ->
gleam_stdlib:println(<<"Resolved paths:"/utf8>>),
gleam_stdlib:println(
<<" config: "/utf8,
(resolve_path_from_cwd(Config_path, Cwd))/binary>>
),
Inputs = begin
_pipe = Multiple,
_pipe@1 = gleam@list:map(
_pipe,
fun(C) -> oaspec@config:input(C) end
),
gleam@list:unique(_pipe@1)
end,
gleam@list:each(
Inputs,
fun(P) ->
gleam_stdlib:println(
<<" input: "/utf8,
(resolve_path_from_cwd(P, Cwd))/binary>>
)
end
),
gleam@list:each(
Multiple,
fun(Cfg) ->
gleam_stdlib:println(
<<<<" target ["/utf8,
(oaspec@config:package(Cfg))/binary>>/binary,
"]:"/utf8>>
),
print_target_outputs(Cfg, Cwd, <<" "/utf8>>)
end
);
{error, _} ->
nil
end
end.
-file("src/oaspec/internal/cli.gleam", 618).
?DOC(false).
-spec print_dep_hints(list(oaspec@internal@codegen@context:generated_file())) -> nil.
print_dep_hints(Files) ->
Needs_regexp = gleam@list:any(
Files,
fun(F) ->
gleam_stdlib:contains_string(
erlang:element(3, F),
<<"import gleam/regexp"/utf8>>
)
end
),
case Needs_regexp of
true ->
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<"Note: generated code imports gleam/regexp for pattern validation."/utf8>>
),
gleam_stdlib:println(
<<" Run 'gleam add gleam_regexp' in your project before 'gleam build'."/utf8>>
);
false ->
nil
end.
-file("src/oaspec/internal/cli.gleam", 761).
?DOC(false).
-spec unique_id() -> binary().
unique_id() ->
Integer_value = erlang:unique_integer(),
case Integer_value < 0 of
true ->
<<"n"/utf8, (erlang:integer_to_binary(- Integer_value))/binary>>;
false ->
erlang:integer_to_binary(Integer_value)
end.
-file("src/oaspec/internal/cli.gleam", 709).
?DOC(false).
-spec format_resolved_content(list({binary(), binary()})) -> list({binary(),
binary()}).
format_resolved_content(Resolved) ->
Temp_dir = <<"/tmp/oaspec_check_"/utf8, (unique_id())/binary>>,
case simplifile:create_directory_all(Temp_dir) of
{error, _} ->
Resolved;
{ok, nil} ->
Temp_entries = gleam@list:index_map(
Resolved,
fun(Entry, Idx) ->
{Original_path, Content} = Entry,
Temp_path = <<<<<<Temp_dir/binary, "/"/utf8>>/binary,
(erlang:integer_to_binary(Idx))/binary>>/binary,
".gleam"/utf8>>,
_ = simplifile:write(Temp_path, Content),
{Original_path, Temp_path}
end
),
Temp_paths = gleam@list:map(
Temp_entries,
fun(Entry@1) -> erlang:element(2, Entry@1) end
),
Formatted_resolved = case oaspec@internal@formatter:format_files(
Temp_paths
) of
{ok, nil} ->
gleam@list:map(
Temp_entries,
fun(Entry@2) ->
{Original_path@1, Temp_path@1} = Entry@2,
case simplifile:read(Temp_path@1) of
{ok, Formatted} ->
{Original_path@1, Formatted};
{error, _} ->
Content@1 = begin
_pipe = gleam@list:find(
Resolved,
fun(R) ->
erlang:element(1, R) =:= Original_path@1
end
),
_pipe@1 = gleam@result:map(
_pipe,
fun(R@1) ->
erlang:element(2, R@1)
end
),
gleam@result:unwrap(
_pipe@1,
<<""/utf8>>
)
end,
{Original_path@1, Content@1}
end
end
);
{error, _} ->
Resolved
end,
_ = simplifile_erl:delete(Temp_dir),
Formatted_resolved
end.
-file("src/oaspec/internal/cli.gleam", 826).
?DOC(false).
-spec load_config_error_to_string(load_config_error()) -> binary().
load_config_error_to_string(Error) ->
Detail = case Error of
{config_load_error, Error@1} ->
oaspec@config:error_to_string(Error@1);
{mode_parse_error, Error@2} ->
oaspec@config:error_to_string(Error@2);
{output_validation_error, Error@3} ->
oaspec@config:error_to_string(Error@3)
end,
<<"Error: "/utf8, Detail/binary>>.
-file("src/oaspec/internal/cli.gleam", 888).
?DOC(false).
-spec validate_target_paths(oaspec@config:config()) -> {ok, nil} |
{error, load_config_error()}.
validate_target_paths(Cfg) ->
gleam@result:'try'(
begin
_pipe = oaspec@config:validate_output_package_match(Cfg),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {output_validation_error, Field@0} end
)
end,
fun(_) -> _pipe@1 = oaspec@config:validate_output_dir_layout(Cfg),
gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {output_validation_error, Field@0} end
) end
).
-file("src/oaspec/internal/cli.gleam", 841).
?DOC(false).
-spec load_configs(
binary(),
gleam@option:option(binary()),
gleam@option:option(binary())
) -> {ok, list(oaspec@config:config())} | {error, load_config_error()}.
load_configs(Config_path, Mode_opt, Output_opt) ->
gleam@result:'try'(
begin
_pipe = oaspec@config:load_all(Config_path),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {config_load_error, Field@0} end
)
end,
fun(Cfgs) -> gleam@result:'try'(case Mode_opt of
none ->
{ok, Cfgs};
{some, Mode_str} ->
_pipe@1 = oaspec@config:parse_mode(Mode_str),
_pipe@2 = gleam@result:map(
_pipe@1,
fun(Parsed) ->
gleam@list:map(
Cfgs,
fun(C) ->
oaspec@config:with_mode(C, Parsed)
end
)
end
),
gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {mode_parse_error, Field@0} end
)
end, fun(Cfgs@1) ->
gleam@result:'try'(case {Output_opt, Cfgs@1} of
{none, _} ->
{ok, Cfgs@1};
{{some, Path}, [Single]} ->
{ok,
[oaspec@config:with_output(
Single,
{some, Path}
)]};
{{some, _}, [_, _ | _]} ->
{error,
{output_validation_error,
{invalid_value,
<<"--output"/utf8>>,
<<"cannot override the output directory for a multi-target config; each target already declares its own output (set per-target output: in oaspec.yaml or drop the --output flag)"/utf8>>}}};
{{some, _}, []} ->
{error,
{output_validation_error,
{invalid_value,
<<"targets"/utf8>>,
<<"must declare at least one target"/utf8>>}}}
end, fun(Cfgs@2) ->
gleam@result:'try'(
begin
_pipe@3 = Cfgs@2,
_pipe@4 = gleam@list:try_map(
_pipe@3,
fun(Cfg) ->
validate_target_paths(Cfg)
end
),
gleam@result:map(_pipe@4, fun(_) -> nil end)
end,
fun(_) -> {ok, Cfgs@2} end
)
end)
end) end
).
-file("src/oaspec/internal/cli.gleam", 914).
?DOC(false).
-spec format_generate_error(oaspec@generate:generate_error()) -> binary().
format_generate_error(Err) ->
{validation_errors, Errors} = Err,
<<"Error: OpenAPI spec contains unsupported features:\n"/utf8,
(gleam@string:join(
gleam@list:map(
Errors,
fun(Validation_error) ->
<<" - "/utf8,
(oaspec@openapi@diagnostic:to_short_string(
Validation_error
))/binary>>
end
),
<<"\n"/utf8>>
))/binary>>.
-file("src/oaspec/internal/cli.gleam", 927).
?DOC(false).
-spec print_warnings(list(oaspec@openapi@diagnostic:diagnostic())) -> nil.
print_warnings(Warnings) ->
case Warnings of
[] ->
nil;
_ ->
gleam_stdlib:println_error(<<"Warnings:"/utf8>>),
gleam@list:each(
Warnings,
fun(W) ->
gleam_stdlib:println_error(
<<" - "/utf8,
(oaspec@openapi@diagnostic:to_short_string(W))/binary>>
)
end
)
end.
-file("src/oaspec/internal/cli.gleam", 198).
?DOC(false).
-spec run_init(binary()) -> nil.
run_init(Path) ->
Template = <<"# oaspec configuration file
# See https://github.com/nao1215/oaspec for documentation.
# Path to your OpenAPI 3.x specification (YAML or JSON).
input: openapi.yaml
# Gleam module namespace for generated code.
# Generated imports will be `import <package>/types`, etc.
package: api
# Generation mode: server, client, or both (default: both).
# mode: both
# Enable guard validation in generated server/client code.
# Default: true for mode: server / both (fail-closed: server handlers
# should not receive schema-invalid input by default), false for
# mode: client (clients pre-validating before sending is nice but
# optional). When enabled, generated routers validate request bodies
# against schema constraints and return 422 on failure. Generated
# clients validate request bodies before sending. Set explicitly to
# override the mode-dependent default.
# validate: true
# Output settings (optional).
# output:
# dir: ./gen # Base directory; default paths are
# # server -> <dir>/<package>
# # client -> <dir>/<package>_client
# # so a single `gleam build` rooted at <dir>
# # picks up both.
# server: ./gen/api # Override server output path
# client: ./gen/api_client # Override client output path
# Operation filter (optional, Issue #387). When set, codegen only
# emits operations whose tag list intersects `tags` OR whose path
# matches one of `paths` (the two lists are unioned, not
# intersected). Path patterns ending in `/**` match any path that
# extends the prefix with a `/<rest>` segment. Both lists empty /
# both keys omitted = no filter.
# include:
# tags:
# - issues
# paths:
# - \"/users/{username}\"
# - \"/repos/**\"
# Multi-target codegen (optional, Issue #387). When `targets:` is
# set, the same input spec is generated once per entry, each with
# its own `package`, `output`, and `include`. The top-level
# `input`, `mode`, and `validate` are shared across every target.
# Targets whose output paths overlap are rejected at config-load
# time. `--output` cannot be used with multi-target configs.
# targets:
# - package: my_app/issues
# output:
# dir: ./src
# include:
# tags: [issues]
# - package: my_app/repos
# output:
# dir: ./src
# include:
# paths: [\"/repos/**\"]
"/utf8>>,
case simplifile_erl:is_file(Path) of
{ok, true} ->
gleam_stdlib:println_error(
<<<<"Error: "/utf8, Path/binary>>/binary,
" already exists"/utf8>>
),
erlang:halt(1);
_ ->
case simplifile:write(Path, Template) of
{ok, _} ->
gleam_stdlib:println(<<"Created "/utf8, Path/binary>>);
{error, Write_err} ->
gleam_stdlib:println_error(
<<<<<<"Error: failed to write "/utf8, Path/binary>>/binary,
": "/utf8>>/binary,
(simplifile:describe_error(Write_err))/binary>>
),
erlang:halt(1)
end
end.
-file("src/oaspec/internal/cli.gleam", 180).
?DOC(false).
-spec init_command() -> glint:command(nil).
init_command() ->
begin
glint:flag(
begin
_pipe = glint:string_flag(<<"output"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, <<"./oaspec.yaml"/utf8>>),
glint:flag_help(
_pipe@1,
<<"Output path for the config file"/utf8>>
)
end,
fun(Output_path) ->
glint:command_help(
<<"Create a oaspec.yaml config file"/utf8>>,
fun() ->
glint:command(
fun(_, _, Flags) ->
Path = begin
_pipe@2 = Output_path(Flags),
gleam@result:unwrap(
_pipe@2,
<<"./oaspec.yaml"/utf8>>
)
end,
run_init(Path)
end
)
end
)
end
)
end.
-file("src/oaspec/internal/cli.gleam", 642).
?DOC(false).
-spec run_check(
list(oaspec@internal@codegen@context:generated_file()),
oaspec@config:config()
) -> nil.
run_check(Files, Cfg) ->
gleam_stdlib:println(
<<"Checking generated code against existing files..."/utf8>>
),
Resolved = oaspec@codegen@writer:resolve_paths(Files, Cfg),
Expected_paths = oaspec@codegen@writer:expected_paths(Files, Cfg),
Resolved@1 = format_resolved_content(Resolved),
Diffs = gleam@list:filter_map(
Resolved@1,
fun(Entry) ->
{Path, Content} = Entry,
case simplifile:read(Path) of
{error, _} ->
{ok, <<Path/binary, " (missing)"/utf8>>};
{ok, Existing} ->
case gleam@string:compare(Existing, Content) of
eq ->
{error, nil};
_ ->
{ok, <<Path/binary, " (differs)"/utf8>>}
end
end
end
),
Output_dirs = oaspec@codegen@writer:output_dirs(Cfg),
Orphans = gleam@list:flat_map(
Output_dirs,
fun(Dir) -> case simplifile_erl:read_directory(Dir) of
{error, _} ->
[];
{ok, Entries} ->
gleam@list:filter_map(
Entries,
fun(Name) ->
case gleam_stdlib:string_ends_with(
Name,
<<".gleam"/utf8>>
) of
false ->
{error, nil};
true ->
Full_path = <<<<Dir/binary, "/"/utf8>>/binary,
Name/binary>>,
case gleam@list:contains(
Expected_paths,
Full_path
) of
true ->
{error, nil};
false ->
{ok,
<<Full_path/binary,
" (orphaned)"/utf8>>}
end
end
end
)
end end
),
All_issues = lists:append(Diffs, Orphans),
case All_issues of
[] ->
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"All files up to date, check passed."/utf8>>);
_ ->
gleam_stdlib:println_error(<<""/utf8>>),
gleam@list:each(
All_issues,
fun(D) ->
gleam_stdlib:println_error(<<" "/utf8, D/binary>>)
end
),
gleam_stdlib:println_error(
<<<<"\n"/utf8,
(erlang:integer_to_binary(erlang:length(All_issues)))/binary>>/binary,
" file(s) out of date. Run 'oaspec generate' to update."/utf8>>
),
erlang:halt(1)
end.
-file("src/oaspec/internal/cli.gleam", 899).
?DOC(false).
-spec require(
{ok, XTP} | {error, XTQ},
fun((XTQ) -> binary()),
fun((XTP) -> nil)
) -> nil.
require(Result, To_message, Continue) ->
case Result of
{ok, Value} ->
Continue(Value);
{error, Err} ->
gleam_stdlib:println_error(To_message(Err)),
erlang:halt(1)
end.
-file("src/oaspec/internal/cli.gleam", 591).
?DOC(false).
-spec write_files(
list(oaspec@internal@codegen@context:generated_file()),
oaspec@config:config()
) -> nil.
write_files(Files, Cfg) ->
gleam_stdlib:println(<<"Generating code..."/utf8>>),
require(
oaspec@codegen@writer:write_all(
Files,
Cfg,
fun(Path) ->
gleam_stdlib:println(<<" Generated: "/utf8, Path/binary>>)
end
),
fun(E) ->
<<"Error: "/utf8,
(oaspec@codegen@writer:error_to_string(E))/binary>>
end,
fun(Written) ->
require(
oaspec@internal@formatter:format_files(
oaspec@codegen@writer:output_dirs(Cfg)
),
fun(E@1) ->
<<"Error: "/utf8,
(oaspec@internal@formatter:error_to_string(E@1))/binary>>
end,
fun(_) ->
gleam_stdlib:println(<<" Formatted generated code"/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<<<"Successfully generated "/utf8,
(erlang:integer_to_binary(
erlang:length(Written)
))/binary>>/binary,
" files"/utf8>>
),
print_dep_hints(Files)
end
)
end
).
-file("src/oaspec/internal/cli.gleam", 290).
?DOC(false).
-spec run_generate(
binary(),
gleam@option:option(binary()),
gleam@option:option(binary()),
boolean(),
boolean(),
boolean()
) -> nil.
run_generate(
Config_path,
Mode_opt,
Output_opt,
Check_mode,
Fail_on_warnings,
Validate_mode
) ->
gleam_stdlib:println(<<"oaspec v"/utf8, (<<"0.47.0"/utf8>>)/binary>>),
gleam_stdlib:println(<<"Loading config from: "/utf8, Config_path/binary>>),
require(
load_configs(Config_path, Mode_opt, Output_opt),
fun load_config_error_to_string/1,
fun(Cfgs) ->
Cfgs@1 = gleam@list:map(Cfgs, fun(C) -> case Validate_mode of
true ->
oaspec@config:with_validate(C, true);
false ->
C
end end),
require(
validate_no_target_overlap(Cfgs@1),
fun load_config_error_to_string/1,
fun(_) ->
print_resolved_paths_for_all(Config_path, Cfgs@1),
First_cfg@1 = case Cfgs@1 of
[First_cfg | _] -> First_cfg;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"oaspec/internal/cli"/utf8>>,
function => <<"run_generate"/utf8>>,
line => 330,
value => _assert_fail,
start => 10860,
'end' => 10893,
pattern_start => 10871,
pattern_end => 10886})
end,
Shared_input = oaspec@config:input(First_cfg@1),
gleam_stdlib:println(
<<"Parsing OpenAPI spec: "/utf8, Shared_input/binary>>
),
Reporter = oaspec@internal@progress:stdout_with_elapsed(),
require(
oaspec@openapi@parser:parse_file_with_progress(
Shared_input,
Reporter
),
fun(E) ->
<<"Error: "/utf8,
(oaspec@openapi@parser:parse_error_to_string(E))/binary>>
end,
fun(Spec) ->
Multi_target = case Cfgs@1 of
[_, _ | _] ->
true;
_ ->
false
end,
gleam@list:each(
Cfgs@1,
fun(Cfg) ->
case Multi_target of
true ->
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<<<"[target: "/utf8,
(oaspec@config:package(
Cfg
))/binary>>/binary,
"]"/utf8>>
);
false ->
nil
end,
require(
oaspec@generate:generate_with_progress(
Spec,
Cfg,
Reporter
),
fun format_generate_error/1,
fun(Summary) ->
gleam_stdlib:println(
<<"Spec loaded: "/utf8,
(erlang:element(3, Summary))/binary>>
),
print_warnings(
erlang:element(4, Summary)
),
case Fail_on_warnings andalso (erlang:element(
4,
Summary
)
/= []) of
true ->
gleam_stdlib:println_error(
<<""/utf8>>
),
gleam_stdlib:println_error(
<<"Error: warnings present and --fail-on-warnings is set."/utf8>>
),
erlang:halt(1);
false ->
nil
end,
case Check_mode of
true ->
run_check(
erlang:element(
2,
Summary
),
Cfg
);
false ->
write_files(
erlang:element(
2,
Summary
),
Cfg
)
end
end
)
end
)
end
)
end
)
end
).
-file("src/oaspec/internal/cli.gleam", 69).
?DOC(false).
-spec generate_command() -> glint:command(nil).
generate_command() ->
begin
glint:flag(
begin
_pipe = glint:string_flag(<<"config"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, <<"./oaspec.yaml"/utf8>>),
glint:flag_help(_pipe@1, <<"Path to config file"/utf8>>)
end,
fun(Config_path) ->
glint:flag(
begin
_pipe@2 = glint:string_flag(<<"mode"/utf8>>),
_pipe@3 = glint:flag_default(_pipe@2, <<""/utf8>>),
glint:flag_help(
_pipe@3,
<<"Generation mode: server, client, or both (overrides config)"/utf8>>
)
end,
fun(Mode) ->
glint:flag(
begin
_pipe@4 = glint:string_flag(<<"output"/utf8>>),
_pipe@5 = glint:flag_default(
_pipe@4,
<<""/utf8>>
),
glint:flag_help(
_pipe@5,
<<"Output directory override"/utf8>>
)
end,
fun(Output) ->
glint:flag(
begin
_pipe@6 = glint:bool_flag(
<<"check"/utf8>>
),
_pipe@7 = glint:flag_default(
_pipe@6,
false
),
glint:flag_help(
_pipe@7,
<<"Check that generated code matches existing files without writing"/utf8>>
)
end,
fun(Check) ->
glint:flag(
begin
_pipe@8 = glint:bool_flag(
<<"fail-on-warnings"/utf8>>
),
_pipe@9 = glint:flag_default(
_pipe@8,
false
),
glint:flag_help(
_pipe@9,
<<"Treat warnings as errors"/utf8>>
)
end,
fun(Fail_on_warnings) ->
glint:flag(
begin
_pipe@10 = glint:bool_flag(
<<"validate"/utf8>>
),
_pipe@11 = glint:flag_default(
_pipe@10,
false
),
glint:flag_help(
_pipe@11,
<<"Force-enable guard validation in generated server/client code. One-way override: cannot disable validation set by oaspec.yaml. Set validate: false in the config to turn it off."/utf8>>
)
end,
fun(Validate) ->
glint:command_help(
<<"Generate Gleam code from an OpenAPI specification"/utf8>>,
fun() ->
glint:command(
fun(
_,
_,
Flags
) ->
Config_path@1 = begin
_pipe@12 = Config_path(
Flags
),
gleam@result:unwrap(
_pipe@12,
<<"./oaspec.yaml"/utf8>>
)
end,
Mode_opt = case begin
_pipe@13 = Mode(
Flags
),
gleam@result:unwrap(
_pipe@13,
<<""/utf8>>
)
end of
<<""/utf8>> ->
none;
S ->
{some,
S}
end,
Output_opt = case begin
_pipe@14 = Output(
Flags
),
gleam@result:unwrap(
_pipe@14,
<<""/utf8>>
)
end of
<<""/utf8>> ->
none;
S@1 ->
{some,
S@1}
end,
Check_mode = begin
_pipe@15 = Check(
Flags
),
gleam@result:unwrap(
_pipe@15,
false
)
end,
Fail_on_warnings_mode = begin
_pipe@16 = Fail_on_warnings(
Flags
),
gleam@result:unwrap(
_pipe@16,
false
)
end,
Validate_mode = begin
_pipe@17 = Validate(
Flags
),
gleam@result:unwrap(
_pipe@17,
false
)
end,
run_generate(
Config_path@1,
Mode_opt,
Output_opt,
Check_mode,
Fail_on_warnings_mode,
Validate_mode
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end.
-file("src/oaspec/internal/cli.gleam", 772).
?DOC(false).
-spec run_validate(binary(), gleam@option:option(binary())) -> nil.
run_validate(Config_path, Mode_opt) ->
gleam_stdlib:println(<<"oaspec v"/utf8, (<<"0.47.0"/utf8>>)/binary>>),
gleam_stdlib:println(<<"Loading config from: "/utf8, Config_path/binary>>),
require(
load_configs(Config_path, Mode_opt, none),
fun load_config_error_to_string/1,
fun(Cfgs) ->
First_cfg@1 = case Cfgs of
[First_cfg | _] -> First_cfg;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"oaspec/internal/cli"/utf8>>,
function => <<"run_validate"/utf8>>,
line => 784,
value => _assert_fail,
start => 25523,
'end' => 25556,
pattern_start => 25534,
pattern_end => 25549})
end,
Shared_input = oaspec@config:input(First_cfg@1),
gleam_stdlib:println(
<<"Parsing OpenAPI spec: "/utf8, Shared_input/binary>>
),
Reporter = oaspec@internal@progress:stdout_with_elapsed(),
require(
oaspec@openapi@parser:parse_file_with_progress(
Shared_input,
Reporter
),
fun(E) ->
<<"Error: "/utf8,
(oaspec@openapi@parser:parse_error_to_string(E))/binary>>
end,
fun(Spec) ->
Multi_target = case Cfgs of
[_, _ | _] ->
true;
_ ->
false
end,
gleam@list:each(
Cfgs,
fun(Cfg) ->
case Multi_target of
true ->
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<<<"[target: "/utf8,
(oaspec@config:package(Cfg))/binary>>/binary,
"]"/utf8>>
);
false ->
nil
end,
require(
oaspec@generate:validate_only_with_progress(
Spec,
Cfg,
Reporter
),
fun format_generate_error/1,
fun(Summary) ->
gleam_stdlib:println(
<<"Spec loaded: "/utf8,
(erlang:element(2, Summary))/binary>>
),
print_warnings(erlang:element(3, Summary))
end
)
end
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Validation passed."/utf8>>)
end
)
end
).
-file("src/oaspec/internal/cli.gleam", 146).
?DOC(false).
-spec validate_command() -> glint:command(nil).
validate_command() ->
begin
glint:flag(
begin
_pipe = glint:string_flag(<<"config"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, <<"./oaspec.yaml"/utf8>>),
glint:flag_help(_pipe@1, <<"Path to config file"/utf8>>)
end,
fun(Config_path) ->
glint:flag(
begin
_pipe@2 = glint:string_flag(<<"mode"/utf8>>),
_pipe@3 = glint:flag_default(_pipe@2, <<""/utf8>>),
glint:flag_help(
_pipe@3,
<<"Generation mode: server, client, or both (overrides config)"/utf8>>
)
end,
fun(Mode) ->
glint:command_help(
<<"Validate an OpenAPI specification without generating code"/utf8>>,
fun() ->
glint:command(
fun(_, _, Flags) ->
Config_path@1 = begin
_pipe@4 = Config_path(Flags),
gleam@result:unwrap(
_pipe@4,
<<"./oaspec.yaml"/utf8>>
)
end,
Mode_opt = case begin
_pipe@5 = Mode(Flags),
gleam@result:unwrap(
_pipe@5,
<<""/utf8>>
)
end of
<<""/utf8>> ->
none;
S ->
{some, S}
end,
run_validate(Config_path@1, Mode_opt)
end
)
end
)
end
)
end
)
end.
-file("src/oaspec/internal/cli.gleam", 46).
?DOC(false).
-spec app() -> glint:glint(nil).
app() ->
_pipe = glint:new(),
_pipe@1 = glint:with_name(_pipe, <<"oaspec"/utf8>>),
_pipe@2 = glint:global_help(
_pipe@1,
<<"Generate Gleam code from OpenAPI 3.x specifications\n\nCommands:\n init Create a default oaspec.yaml config file\n generate Generate Gleam code from an OpenAPI spec\n validate Validate an OpenAPI spec without generating code\n version Print the oaspec version and exit\n\nRun 'oaspec <command> --help' for more information.\nUse 'oaspec --version' for a flag-style version check."/utf8>>
),
_pipe@3 = maybe_pretty_help(_pipe@2),
_pipe@4 = glint:add(_pipe@3, [<<"init"/utf8>>], init_command()),
_pipe@5 = glint:add(_pipe@4, [<<"generate"/utf8>>], generate_command()),
_pipe@6 = glint:add(_pipe@5, [<<"validate"/utf8>>], validate_command()),
glint:add(_pipe@6, [<<"version"/utf8>>], version_command()).