-module(version_bump@config). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/version_bump/config.gleam"). -export([default/0, parse_package_json_config/1, parse_gleam_toml_config/1, parse_toml_config/1, parse_json_config/1, load/1]). -export_type([plugin_spec/0, branch_config/0, config/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( " Configuration shapes plus the entry point for loading config from a project.\n" " The `load` implementation (reading .releaserc / release.config / package.json)\n" " is fleshed out by the config module work; the type is owned here so every\n" " other module can depend on it without a cycle.\n" ). -type plugin_spec() :: {plugin_spec, binary(), gleam@dict:dict(binary(), binary())}. -type branch_config() :: {branch_config, binary(), gleam@option:option(binary()), gleam@option:option(binary()), gleam@option:option(binary())}. -type config() :: {config, gleam@option:option(binary()), binary(), list(branch_config()), list(plugin_spec()), boolean(), boolean(), version_bump@semver:versioning_mode()}. -file("src/version_bump/config.gleam", 58). ?DOC( " The default configuration for a Gleam project: commit analysis, release\n" " notes, publishing to Hex, and a GitHub release, over the conventional release\n" " branches. (This is the Gleam-first analogue of semantic-release's defaults,\n" " which publish to npm; swap `hex` for `npm` to release a JavaScript package.)\n" ). -spec default() -> config(). default() -> {config, none, <<"v${version}"/utf8>>, [{branch_config, <<"main"/utf8>>, none, none, none}, {branch_config, <<"master"/utf8>>, none, none, none}, {branch_config, <<"next"/utf8>>, {some, <<"next"/utf8>>}, none, none}, {branch_config, <<"beta"/utf8>>, none, {some, <<"beta"/utf8>>}, none}, {branch_config, <<"alpha"/utf8>>, none, {some, <<"alpha"/utf8>>}, none}], [{plugin_spec, <<"commit-analyzer"/utf8>>, maps:new()}, {plugin_spec, <<"release-notes-generator"/utf8>>, maps:new()}, {plugin_spec, <<"hex"/utf8>>, maps:new()}, {plugin_spec, <<"git"/utf8>>, maps:new()}, {plugin_spec, <<"github"/utf8>>, maps:new()}], false, true, stable}. -file("src/version_bump/config.gleam", 83). ?DOC(" Map the boolean `initial_development` config key to a `VersioningMode`.\n"). -spec versioning_mode_of(boolean()) -> version_bump@semver:versioning_mode(). versioning_mode_of(Initial_development) -> case Initial_development of true -> initial_development; false -> stable end. -file("src/version_bump/config.gleam", 154). ?DOC( " Read a file, returning `Some(contents)` when it can be read and `None`\n" " otherwise. Unreadable or missing files are treated as absent so the loader\n" " falls through to the next candidate (and ultimately to `default()`).\n" ). -spec read_if_present(binary()) -> gleam@option:option(binary()). read_if_present(Path) -> case simplifile:read(Path) of {ok, Contents} -> {some, Contents}; {error, _} -> none end. -file("src/version_bump/config.gleam", 163). ?DOC( " Join a directory and a filename with a single `/` separator, tolerating a\n" " trailing slash on the directory.\n" ). -spec join_path(binary(), binary()) -> binary(). join_path(Dir, Name) -> case gleam_stdlib:string_ends_with(Dir, <<"/"/utf8>>) of true -> <>; false -> <<<>/binary, Name/binary>> end. -file("src/version_bump/config.gleam", 135). -spec try_sources( binary(), list({binary(), fun((binary()) -> {ok, config()} | {error, version_bump@error:release_error()})}) ) -> gleam@option:option({ok, config()} | {error, version_bump@error:release_error()}). try_sources(Cwd, Sources) -> case Sources of [] -> none; [{Filename, Parser} | Rest] -> Path = join_path(Cwd, Filename), case read_if_present(Path) of {some, Contents} -> {some, Parser(Contents)}; none -> try_sources(Cwd, Rest) end end. -file("src/version_bump/config.gleam", 326). -spec describe_decode_error(gleam@dynamic@decode:decode_error()) -> binary(). describe_decode_error(Err) -> <<<<<<<<"expected "/utf8, (erlang:element(2, Err))/binary>>/binary, ", found "/utf8>>/binary, (erlang:element(3, Err))/binary>>/binary, (case erlang:element(4, Err) of [] -> <<""/utf8>>; Path -> <<" at "/utf8, (gleam@string:join(Path, <<"."/utf8>>))/binary>> end)/binary>>. -file("src/version_bump/config.gleam", 315). -spec describe_json_error(gleam@json:decode_error()) -> binary(). describe_json_error(Err) -> case Err of unexpected_end_of_input -> <<"unexpected end of input"/utf8>>; {unexpected_byte, Byte} -> <<"unexpected byte "/utf8, Byte/binary>>; {unexpected_sequence, Seq} -> <<"unexpected sequence "/utf8, Seq/binary>>; {unable_to_decode, Errors} -> <<"unable to decode: "/utf8, (gleam@string:join( gleam@list:map(Errors, fun describe_decode_error/1), <<"; "/utf8>> ))/binary>> end. -file("src/version_bump/config.gleam", 306). ?DOC( " Decode any scalar JSON value (string / bool / int / float) into its string\n" " form. Values that are not scalars decode to an empty string.\n" ). -spec scalar_to_string_decoder() -> gleam@dynamic@decode:decoder(binary()). scalar_to_string_decoder() -> gleam@dynamic@decode:one_of( {decoder, fun gleam@dynamic@decode:decode_string/1}, [begin _pipe = {decoder, fun gleam@dynamic@decode:decode_bool/1}, gleam@dynamic@decode:map(_pipe, fun gleam@bool:to_string/1) end, begin _pipe@1 = {decoder, fun gleam@dynamic@decode:decode_int/1}, gleam@dynamic@decode:map( _pipe@1, fun erlang:integer_to_binary/1 ) end, begin _pipe@2 = {decoder, fun gleam@dynamic@decode:decode_float/1}, gleam@dynamic@decode:map( _pipe@2, fun gleam_stdlib:float_to_string/1 ) end, gleam@dynamic@decode:success(<<""/utf8>>)] ). -file("src/version_bump/config.gleam", 300). ?DOC( " Plugin options are kept as a string-keyed dictionary of stringified scalar\n" " values. Non-scalar values (nested objects / arrays) are skipped, since the\n" " core keeps options as strings and individual plugins reparse what they need.\n" ). -spec options_decoder() -> gleam@dynamic@decode:decoder(gleam@dict:dict(binary(), binary())). options_decoder() -> gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, scalar_to_string_decoder() ). -file("src/version_bump/config.gleam", 285). ?DOC( " A plugin entry is either a bare string (the module name with no options) or\n" " a two-element array of `[name, options]`.\n" ). -spec plugin_decoder() -> gleam@dynamic@decode:decoder(plugin_spec()). plugin_decoder() -> String_plugin = begin _pipe = {decoder, fun gleam@dynamic@decode:decode_string/1}, gleam@dynamic@decode:map( _pipe, fun(Name) -> {plugin_spec, Name, maps:new()} end ) end, Array_plugin = begin gleam@dynamic@decode:field( 0, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Name@1) -> gleam@dynamic@decode:optional_field( 1, maps:new(), options_decoder(), fun(Options) -> gleam@dynamic@decode:success( {plugin_spec, Name@1, Options} ) end ) end ) end, gleam@dynamic@decode:one_of(String_plugin, [Array_plugin]). -file("src/version_bump/config.gleam", 271). ?DOC( " `prerelease` may be given as a string (the identifier) or as `true`, in\n" " which case the branch name is used as the identifier. We can only know the\n" " name in the object case, so a bare `true` maps to an empty identifier that\n" " branch resolution can later default from the name.\n" ). -spec prerelease_decoder() -> gleam@dynamic@decode:decoder(gleam@option:option(binary())). prerelease_decoder() -> As_bool = begin _pipe = {decoder, fun gleam@dynamic@decode:decode_bool/1}, gleam@dynamic@decode:map(_pipe, fun(B) -> case B of true -> {some, <<""/utf8>>}; false -> none end end) end, gleam@dynamic@decode:one_of( gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_string/1} ), [As_bool] ). -file("src/version_bump/config.gleam", 241). ?DOC( " A branch entry is either a bare string (the branch name) or an object with\n" " a `name` plus optional `channel`, `prerelease`, and `range` keys.\n" ). -spec branch_decoder() -> gleam@dynamic@decode:decoder(branch_config()). branch_decoder() -> String_branch = begin _pipe = {decoder, fun gleam@dynamic@decode:decode_string/1}, gleam@dynamic@decode:map( _pipe, fun(Name) -> {branch_config, Name, none, none, none} end ) end, Object_branch = begin gleam@dynamic@decode:field( <<"name"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Name@1) -> gleam@dynamic@decode:optional_field( <<"channel"/utf8>>, none, gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_string/1} ), fun(Channel) -> gleam@dynamic@decode:optional_field( <<"prerelease"/utf8>>, none, prerelease_decoder(), fun(Prerelease) -> gleam@dynamic@decode:optional_field( <<"range"/utf8>>, none, gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_string/1} ), fun(Range) -> gleam@dynamic@decode:success( {branch_config, Name@1, Channel, Prerelease, Range} ) end ) end ) end ) end ) end, gleam@dynamic@decode:one_of(String_branch, [Object_branch]). -file("src/version_bump/config.gleam", 199). ?DOC( " Decode a `Config`, starting from `default()` and overriding each field that\n" " is present in the document.\n" ). -spec config_decoder() -> gleam@dynamic@decode:decoder(config()). config_decoder() -> D = default(), gleam@dynamic@decode:optional_field( <<"repositoryUrl"/utf8>>, erlang:element(2, D), gleam@dynamic@decode:optional( {decoder, fun gleam@dynamic@decode:decode_string/1} ), fun(Repository_url) -> gleam@dynamic@decode:optional_field( <<"tagFormat"/utf8>>, erlang:element(3, D), {decoder, fun gleam@dynamic@decode:decode_string/1}, fun(Tag_format) -> gleam@dynamic@decode:optional_field( <<"branches"/utf8>>, erlang:element(4, D), gleam@dynamic@decode:list(branch_decoder()), fun(Branches) -> gleam@dynamic@decode:optional_field( <<"plugins"/utf8>>, erlang:element(5, D), gleam@dynamic@decode:list(plugin_decoder()), fun(Plugins) -> gleam@dynamic@decode:optional_field( <<"dryRun"/utf8>>, erlang:element(6, D), {decoder, fun gleam@dynamic@decode:decode_bool/1}, fun(Dry_run) -> gleam@dynamic@decode:optional_field( <<"ci"/utf8>>, erlang:element(7, D), {decoder, fun gleam@dynamic@decode:decode_bool/1}, fun(Ci) -> gleam@dynamic@decode:optional_field( <<"initialDevelopment"/utf8>>, false, {decoder, fun gleam@dynamic@decode:decode_bool/1}, fun(Initial_development) -> gleam@dynamic@decode:success( {config, Repository_url, Tag_format, Branches, Plugins, Dry_run, Ci, versioning_mode_of( Initial_development )} ) end ) end ) end ) end ) end ) end ) end ). -file("src/version_bump/config.gleam", 184). ?DOC( " Parse the `\"release\"` object out of a `package.json` document. If there is\n" " no `\"release\"` key the project simply has no semantic-release config there,\n" " so the defaults are returned.\n" ). -spec parse_package_json_config(binary()) -> {ok, config()} | {error, version_bump@error:release_error()}. parse_package_json_config(Json_string) -> Release_decoder = begin gleam@dynamic@decode:optional_field( <<"release"/utf8>>, default(), config_decoder(), fun(Release) -> gleam@dynamic@decode:success(Release) end ) end, _pipe = gleam@json:parse(Json_string, Release_decoder), gleam@result:map_error( _pipe, fun(Err) -> {config_error, <<"invalid package.json: "/utf8, (describe_json_error(Err))/binary>>} end ). -file("src/version_bump/config.gleam", 535). -spec toml_scalar_to_string(tom:toml()) -> gleam@option:option(binary()). toml_scalar_to_string(Value) -> case Value of {string, S} -> {some, S}; {bool, B} -> {some, gleam@bool:to_string(B)}; {int, I} -> {some, erlang:integer_to_binary(I)}; {float, F} -> {some, gleam_stdlib:float_to_string(F)}; _ -> none end. -file("src/version_bump/config.gleam", 525). -spec toml_table_string(gleam@dict:dict(binary(), tom:toml()), binary()) -> gleam@option:option(binary()). toml_table_string(Fields, Key) -> case gleam_stdlib:map_get(Fields, Key) of {ok, Value} -> toml_scalar_to_string(Value); {error, _} -> none end. -file("src/version_bump/config.gleam", 516). -spec toml_options(gleam@dict:dict(binary(), tom:toml())) -> gleam@dict:dict(binary(), binary()). toml_options(Fields) -> gleam@dict:fold( Fields, maps:new(), fun(Acc, Key, Value) -> case toml_scalar_to_string(Value) of {some, S} -> gleam@dict:insert(Acc, Key, S); none -> Acc end end ). -file("src/version_bump/config.gleam", 496). -spec toml_plugin(tom:toml()) -> plugin_spec(). toml_plugin(Value) -> case Value of {string, Name} -> {plugin_spec, Name, maps:new()}; {array, Items} -> case Items of [{string, Name@1}, {inline_table, Opts}] -> {plugin_spec, Name@1, toml_options(Opts)}; [{string, Name@1}, {table, Opts}] -> {plugin_spec, Name@1, toml_options(Opts)}; [{string, Name@2}] -> {plugin_spec, Name@2, maps:new()}; _ -> {plugin_spec, <<""/utf8>>, maps:new()} end; {inline_table, Fields} -> {plugin_spec, begin _pipe = toml_table_string(Fields, <<"name"/utf8>>), gleam@option:unwrap(_pipe, <<""/utf8>>) end, maps:new()}; {table, Fields} -> {plugin_spec, begin _pipe = toml_table_string(Fields, <<"name"/utf8>>), gleam@option:unwrap(_pipe, <<""/utf8>>) end, maps:new()}; _ -> {plugin_spec, <<""/utf8>>, maps:new()} end. -file("src/version_bump/config.gleam", 430). ?DOC(" Prefix a key path with the `[tools.version_bump]` table location.\n"). -spec sr(list(binary())) -> list(binary()). sr(Keys) -> lists:append([<<"tools"/utf8>>, <<"version_bump"/utf8>>], Keys). -file("src/version_bump/config.gleam", 469). ?DOC( " Merge any `[tools.version_bump.plugin_options.]` sub-tables into the\n" " matching plugin specs' options.\n" ). -spec apply_plugin_options( list(plugin_spec()), gleam@dict:dict(binary(), tom:toml()) ) -> list(plugin_spec()). apply_plugin_options(Plugins, Table) -> gleam@list:map( Plugins, fun(Spec) -> case tom:get_table( Table, sr([<<"plugin_options"/utf8>>, erlang:element(2, Spec)]) ) of {ok, Opts} -> {plugin_spec, erlang:element(2, Spec), maps:merge(erlang:element(3, Spec), toml_options(Opts))}; {error, _} -> Spec end end ). -file("src/version_bump/config.gleam", 482). -spec toml_branch(tom:toml()) -> branch_config(). toml_branch(Value) -> case Value of {string, Name} -> {branch_config, Name, none, none, none}; {inline_table, Fields} -> {branch_config, begin _pipe = toml_table_string(Fields, <<"name"/utf8>>), gleam@option:unwrap(_pipe, <<""/utf8>>) end, toml_table_string(Fields, <<"channel"/utf8>>), toml_table_string(Fields, <<"prerelease"/utf8>>), toml_table_string(Fields, <<"range"/utf8>>)}; {table, Fields} -> {branch_config, begin _pipe = toml_table_string(Fields, <<"name"/utf8>>), gleam@option:unwrap(_pipe, <<""/utf8>>) end, toml_table_string(Fields, <<"channel"/utf8>>), toml_table_string(Fields, <<"prerelease"/utf8>>), toml_table_string(Fields, <<"range"/utf8>>)}; _ -> {branch_config, <<""/utf8>>, none, none, none} end. -file("src/version_bump/config.gleam", 452). ?DOC( " The host for a gleam.toml `[repository]` field, by its `type` (falling back to\n" " an explicit `host` key for `type = \"custom\"`).\n" ). -spec repository_host(gleam@dict:dict(binary(), tom:toml())) -> gleam@option:option(binary()). repository_host(Table) -> case tom:get_string(Table, [<<"repository"/utf8>>, <<"type"/utf8>>]) of {ok, <<"github"/utf8>>} -> {some, <<"github.com"/utf8>>}; {ok, <<"gitlab"/utf8>>} -> {some, <<"gitlab.com"/utf8>>}; {ok, <<"bitbucket"/utf8>>} -> {some, <<"bitbucket.org"/utf8>>}; {ok, <<"codeberg"/utf8>>} -> {some, <<"codeberg.org"/utf8>>}; {ok, <<"sourcehut"/utf8>>} -> {some, <<"git.sr.ht"/utf8>>}; _ -> case tom:get_string(Table, [<<"repository"/utf8>>, <<"host"/utf8>>]) of {ok, Host} -> {some, Host}; {error, _} -> none end end. -file("src/version_bump/config.gleam", 436). ?DOC( " Derive a repository URL from gleam.toml's standard `[repository]` field, e.g.\n" " `repository = { type = \"github\", user = \"u\", repo = \"r\" }` -> the GitHub URL.\n" ). -spec derive_repository_url(gleam@dict:dict(binary(), tom:toml())) -> gleam@option:option(binary()). derive_repository_url(Table) -> case {tom:get_string(Table, [<<"repository"/utf8>>, <<"user"/utf8>>]), tom:get_string(Table, [<<"repository"/utf8>>, <<"repo"/utf8>>])} of {{ok, User}, {ok, Repo}} -> case repository_host(Table) of {some, Host} -> {some, <<<<<<<<<<"https://"/utf8, Host/binary>>/binary, "/"/utf8>>/binary, User/binary>>/binary, "/"/utf8>>/binary, Repo/binary>>}; none -> none end; {_, _} -> none end. -file("src/version_bump/config.gleam", 390). ?DOC( " Parse the `[tools.version_bump]` table out of a `gleam.toml` — the\n" " Gleam-native config location. Keys use snake_case (`tag_format`, `dry_run`,\n" " `branches`, `plugins`). `repository_url` is taken from the table if present,\n" " otherwise derived from gleam.toml's standard `[repository]` field. Per-plugin\n" " options live in `[tools.version_bump.plugin_options.]` sub-tables.\n" "\n" " A `gleam.toml` with no `[tools.version_bump]` table still yields a working\n" " config (defaults plus the derived repository URL). Exposed for testing.\n" ). -spec parse_gleam_toml_config(binary()) -> {ok, config()} | {error, version_bump@error:release_error()}. parse_gleam_toml_config(Toml_string) -> gleam@result:'try'( begin _pipe = tom:parse(Toml_string), gleam@result:map_error( _pipe, fun(_) -> {config_error, <<"invalid gleam.toml"/utf8>>} end ) end, fun(Table) -> D = default(), Repository_url = case tom:get_string( Table, sr([<<"repository_url"/utf8>>]) ) of {ok, Url} -> {some, Url}; {error, _} -> gleam@option:'or'( derive_repository_url(Table), erlang:element(2, D) ) end, Tag_format = begin _pipe@1 = tom:get_string(Table, sr([<<"tag_format"/utf8>>])), gleam@result:unwrap(_pipe@1, erlang:element(3, D)) end, Dry_run = begin _pipe@2 = tom:get_bool(Table, sr([<<"dry_run"/utf8>>])), gleam@result:unwrap(_pipe@2, erlang:element(6, D)) end, Ci = begin _pipe@3 = tom:get_bool(Table, sr([<<"ci"/utf8>>])), gleam@result:unwrap(_pipe@3, erlang:element(7, D)) end, Initial_development = begin _pipe@4 = tom:get_bool( Table, sr([<<"initial_development"/utf8>>]) ), gleam@result:unwrap(_pipe@4, false) end, Branches = case tom:get_array(Table, sr([<<"branches"/utf8>>])) of {ok, Items} -> gleam@list:map(Items, fun toml_branch/1); {error, _} -> erlang:element(4, D) end, Plugins = case tom:get_array(Table, sr([<<"plugins"/utf8>>])) of {ok, Items@1} -> apply_plugin_options( gleam@list:map(Items@1, fun toml_plugin/1), Table ); {error, _} -> erlang:element(5, D) end, {ok, {config, Repository_url, Tag_format, Branches, Plugins, Dry_run, Ci, versioning_mode_of(Initial_development)}} end ). -file("src/version_bump/config.gleam", 341). ?DOC( " Parse a TOML configuration document, merging recognised keys over the\n" " defaults. Exposed for testing.\n" ). -spec parse_toml_config(binary()) -> {ok, config()} | {error, version_bump@error:release_error()}. parse_toml_config(Toml_string) -> gleam@result:'try'( begin _pipe = tom:parse(Toml_string), gleam@result:map_error( _pipe, fun(_) -> {config_error, <<"invalid TOML config"/utf8>>} end ) end, fun(Table) -> D = default(), Repository_url = case tom:get_string( Table, [<<"repositoryUrl"/utf8>>] ) of {ok, Url} -> {some, Url}; {error, _} -> erlang:element(2, D) end, Tag_format = begin _pipe@1 = tom:get_string(Table, [<<"tagFormat"/utf8>>]), gleam@result:unwrap(_pipe@1, erlang:element(3, D)) end, Dry_run = begin _pipe@2 = tom:get_bool(Table, [<<"dryRun"/utf8>>]), gleam@result:unwrap(_pipe@2, erlang:element(6, D)) end, Ci = begin _pipe@3 = tom:get_bool(Table, [<<"ci"/utf8>>]), gleam@result:unwrap(_pipe@3, erlang:element(7, D)) end, Initial_development = begin _pipe@4 = tom:get_bool(Table, [<<"initialDevelopment"/utf8>>]), gleam@result:unwrap(_pipe@4, false) end, Branches = case tom:get_array(Table, [<<"branches"/utf8>>]) of {ok, Items} -> gleam@list:map(Items, fun toml_branch/1); {error, _} -> erlang:element(4, D) end, Plugins = case tom:get_array(Table, [<<"plugins"/utf8>>]) of {ok, Items@1} -> gleam@list:map(Items@1, fun toml_plugin/1); {error, _} -> erlang:element(5, D) end, {ok, {config, Repository_url, Tag_format, Branches, Plugins, Dry_run, Ci, versioning_mode_of(Initial_development)}} end ). -file("src/version_bump/config.gleam", 174). ?DOC( " Parse a JSON configuration document, merging any recognised keys over the\n" " defaults. Unknown keys are ignored. Exposed for testing.\n" ). -spec parse_json_config(binary()) -> {ok, config()} | {error, version_bump@error:release_error()}. parse_json_config(Json_string) -> _pipe = gleam@json:parse(Json_string, config_decoder()), gleam@result:map_error( _pipe, fun(Err) -> {config_error, <<"invalid JSON config: "/utf8, (describe_json_error(Err))/binary>>} end ). -file("src/version_bump/config.gleam", 123). ?DOC( " Walk the candidate sources in order, returning the parsed config (or parse\n" " error) for the first source that exists, or `None` if none exist.\n" ). -spec find_and_parse(binary()) -> gleam@option:option({ok, config()} | {error, version_bump@error:release_error()}). find_and_parse(Cwd) -> Json_files = gleam@list:map( [<<".releaserc.json"/utf8>>, <<".releaserc"/utf8>>, <<"release.config.json"/utf8>>], fun(Name) -> {Name, fun parse_json_config/1} end ), Sources = lists:append( Json_files, [{<<".releaserc.toml"/utf8>>, fun parse_toml_config/1}, {<<"gleam.toml"/utf8>>, fun parse_gleam_toml_config/1}, {<<"package.json"/utf8>>, fun parse_package_json_config/1}] ), try_sources(Cwd, Sources). -file("src/version_bump/config.gleam", 114). ?DOC( " Load configuration from the project rooted at `cwd`, falling back to\n" " `default()` when no config file is present.\n" "\n" " The lookup order is:\n" " 1. `.releaserc.json`\n" " 2. `.releaserc` (parsed as JSON)\n" " 3. `release.config.json`\n" " 4. `.releaserc.toml` (parsed as TOML)\n" " 5. `[tools.version_bump]` in `gleam.toml` (the Gleam-native location;\n" " also derives `repository_url` from the `[repository]` field)\n" " 6. the `\"release\"` key of `package.json`\n" "\n" " The first file that exists and parses wins; its values are merged over\n" " `default()`. Since every Gleam project has a `gleam.toml`, step 5 means a\n" " Gleam package needs no separate config file: with no `[tools.version_bump]`\n" " table it still releases using the defaults plus the derived repository URL.\n" " When nothing is found, `Ok(default())` is returned.\n" ). -spec load(binary()) -> {ok, config()} | {error, version_bump@error:release_error()}. load(Cwd) -> case find_and_parse(Cwd) of {some, Result} -> Result; none -> {ok, default()} end.