-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(XVB)) -> glint:glint(XVB). 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.48.0"/utf8>>)/binary>> ) end ) end ). -file("src/oaspec/internal/cli.gleam", 469). ?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", 485). ?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", 451). ?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", 564). ?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", 555). ?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", 548). ?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", 540). ?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", 416). ?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( <<<>/binary, (resolve_path_from_cwd( oaspec@config:output_server(Cfg), Cwd ))/binary>> ); client -> gleam_stdlib:println( <<<>/binary, (resolve_path_from_cwd( oaspec@config:output_client(Cfg), Cwd ))/binary>> ); both -> gleam_stdlib:println( <<<>/binary, (resolve_path_from_cwd( oaspec@config:output_server(Cfg), Cwd ))/binary>> ), gleam_stdlib:println( <<<>/binary, (resolve_path_from_cwd( oaspec@config:output_client(Cfg), Cwd ))/binary>> ) end. -file("src/oaspec/internal/cli.gleam", 515). ?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", 499). ?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", 386). ?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", 624). ?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", 767). ?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", 715). ?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 = <<<<<>/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", 838). ?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", 900). ?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", 853). ?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", 931). ?DOC(false). -spec format_generate_error_for(binary()) -> fun((oaspec@generate:generate_error()) -> binary()). format_generate_error_for(File_path) -> fun(Err) -> {validation_errors, Errors} = Err, File_opt = case File_path of <<""/utf8>> -> none; _ -> {some, File_path} end, <<"Error: OpenAPI spec contains unsupported features:\n"/utf8, (gleam@string:join( gleam@list:map( Errors, fun(Validation_error) -> <<" - "/utf8, (case erlang:element(7, Validation_error) of {source_loc, _, _} -> oaspec@openapi@diagnostic:render( Validation_error, File_opt ); no_source_loc -> oaspec@openapi@diagnostic:to_short_string( Validation_error ) end)/binary>> end ), <<"\n"/utf8>> ))/binary>> end. -file("src/oaspec/internal/cli.gleam", 958). ?DOC(false). -spec print_warnings_for(binary(), list(oaspec@openapi@diagnostic:diagnostic())) -> nil. print_warnings_for(File_path, Warnings) -> File_opt = case File_path of <<""/utf8>> -> none; _ -> {some, File_path} end, case Warnings of [] -> nil; _ -> gleam_stdlib:println_error(<<"Warnings:"/utf8>>), gleam@list:each( Warnings, fun(W) -> Rendered = case erlang:element(7, W) of {source_loc, _, _} -> oaspec@openapi@diagnostic:render(W, File_opt); no_source_loc -> oaspec@openapi@diagnostic:to_short_string(W) end, gleam_stdlib:println_error(<<" - "/utf8, Rendered/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 /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 -> / # # client -> /_client # # so a single `gleam build` rooted at # # 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 `/` 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", 648). ?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, <>}; {ok, Existing} -> case gleam@string:compare(Existing, Content) of eq -> {error, nil}; _ -> {ok, <>} 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 = <<<>/binary, Name/binary>>, case gleam@list:contains( Expected_paths, Full_path ) of true -> {error, nil}; false -> {ok, <>} 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", 911). ?DOC(false). -spec require( {ok, XWI} | {error, XWJ}, fun((XWJ) -> binary()), fun((XWI) -> 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", 597). ?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.48.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 => <>, 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_and_locations( Shared_input, Reporter ), fun(E) -> <<"Error: "/utf8, (oaspec@openapi@parser:parse_error_to_string(E))/binary>> end, fun(Parsed) -> {Spec, Locations} = Parsed, 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_and_locations( Spec, Locations, Cfg, Reporter ), format_generate_error_for(Shared_input), fun(Summary) -> gleam_stdlib:println( <<"Spec loaded: "/utf8, (erlang:element(3, Summary))/binary>> ), print_warnings_for( Shared_input, 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", 778). ?DOC(false). -spec run_validate(binary(), gleam@option:option(binary())) -> nil. run_validate(Config_path, Mode_opt) -> gleam_stdlib:println(<<"oaspec v"/utf8, (<<"0.48.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 => <>, module => <<"oaspec/internal/cli"/utf8>>, function => <<"run_validate"/utf8>>, line => 790, value => _assert_fail, start => 25675, 'end' => 25708, pattern_start => 25686, pattern_end => 25701}) 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_and_locations( Shared_input, Reporter ), fun(E) -> <<"Error: "/utf8, (oaspec@openapi@parser:parse_error_to_string(E))/binary>> end, fun(Parsed) -> {Spec, Locations} = Parsed, 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_and_locations( Spec, Locations, Cfg, Reporter ), format_generate_error_for(Shared_input), fun(Summary) -> gleam_stdlib:println( <<"Spec loaded: "/utf8, (erlang:element(2, Summary))/binary>> ), print_warnings_for( Shared_input, 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 --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()).