-module(caffeine_lang@parser@artifacts). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/caffeine_lang/parser/artifacts.gleam"). -export([parse_semver/1, parse_standard_library/0, parse_from_file/1]). -export_type([artifact/0, semver/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 artifact() :: {artifact, binary(), semver(), gleam@dict:dict(binary(), caffeine_lang@common@accepted_types:accepted_types()), gleam@dict:dict(binary(), caffeine_lang@common@accepted_types:accepted_types())}. -type semver() :: {semver, integer(), integer(), integer()}. -file("src/caffeine_lang/parser/artifacts.gleam", 76). ?DOC( " Parse a single semver part - must be non-negative and no leading zeros\n" " (except for \"0\" itself).\n" ). -spec parse_semver_part(binary()) -> {ok, integer()} | {error, nil}. parse_semver_part(S) -> case S of <<""/utf8>> -> {error, nil}; <<"0"/utf8>> -> {ok, 0}; _ -> case gleam_stdlib:string_starts_with(S, <<"0"/utf8>>) orelse gleam_stdlib:string_starts_with( S, <<"-"/utf8>> ) of true -> {error, nil}; false -> gleam_stdlib:parse_int(S) end end. -file("src/caffeine_lang/parser/artifacts.gleam", 65). ?DOC(false). -spec parse_semver(binary()) -> {ok, semver()} | {error, nil}. parse_semver(Version_string) -> case begin _pipe = Version_string, _pipe@1 = gleam@string:split(_pipe, <<"."/utf8>>), gleam@list:map(_pipe@1, fun parse_semver_part/1) end of [{ok, Major}, {ok, Minor}, {ok, Patch}] -> {ok, {semver, Major, Minor, Patch}}; _ -> {error, nil} end. -file("src/caffeine_lang/parser/artifacts.gleam", 89). ?DOC(" Decoder for semantic version strings (e.g., \"1.2.3\").\n"). -spec semantic_version_decoder() -> gleam@dynamic@decode:decoder(semver()). semantic_version_decoder() -> Err_default = {semver, 0, 0, 0}, gleam@dynamic@decode:new_primitive_decoder( <<"Semver"/utf8>>, fun(Dyn) -> gleam@result:'try'( begin _pipe = gleam@dynamic@decode:run( Dyn, {decoder, fun gleam@dynamic@decode:decode_string/1} ), gleam@result:replace_error(_pipe, Err_default) end, fun(Str) -> _pipe@1 = parse_semver(Str), gleam@result:replace_error(_pipe@1, Err_default) end ) end ). -file("src/caffeine_lang/parser/artifacts.gleam", 99). -spec parse_from_string(binary()) -> {ok, list(artifact())} | {error, gleam@json:decode_error()}. parse_from_string(Json_string) -> Artifact_decoder = begin gleam@dynamic@decode:field( <<"name"/utf8>>, caffeine_lang@common@decoders:non_empty_string_decoder(), fun(Name) -> gleam@dynamic@decode:field( <<"version"/utf8>>, semantic_version_decoder(), fun(Version) -> gleam@dynamic@decode:field( <<"inherited_params"/utf8>>, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, caffeine_lang@common@decoders:accepted_types_decoder( ) ), fun(Inherited_params) -> gleam@dynamic@decode:field( <<"required_params"/utf8>>, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, caffeine_lang@common@decoders:accepted_types_decoder( ) ), fun(Required_params) -> gleam@dynamic@decode:success( {artifact, Name, Version, Inherited_params, Required_params} ) end ) end ) end ) end ) end, Artifacts_decoded = begin gleam@dynamic@decode:field( <<"artifacts"/utf8>>, gleam@dynamic@decode:list(Artifact_decoder), fun(Artifacts) -> gleam@dynamic@decode:success(Artifacts) end ) end, gleam@json:parse(Json_string, Artifacts_decoded). -file("src/caffeine_lang/parser/artifacts.gleam", 45). ?DOC(" The actual, common parsing logic.\n"). -spec internal_parse_from_string(binary()) -> {ok, list(artifact())} | {error, caffeine_lang@common@errors:compilation_error()}. internal_parse_from_string(Content) -> gleam@result:'try'(case parse_from_string(Content) of {ok, Artifacts} -> {ok, Artifacts}; {error, Err} -> {error, caffeine_lang@common@errors:format_json_decode_error(Err)} end, fun(Artifacts@1) -> gleam@result:'try'( caffeine_lang@common@validations:validate_relevant_uniqueness( Artifacts@1, fun(A) -> erlang:element(2, A) end, <<"artifact names"/utf8>> ), fun(_) -> {ok, Artifacts@1} end ) end). -file("src/caffeine_lang/parser/artifacts.gleam", 33). ?DOC(" Parses the embedded standard library artifacts.\n"). -spec parse_standard_library() -> {ok, list(artifact())} | {error, caffeine_lang@common@errors:compilation_error()}. parse_standard_library() -> internal_parse_from_string( <<" { \"artifacts\": [ { \"name\": \"SLO\", \"version\": \"0.0.1\", \"inherited_params\": { \"threshold\": \"Float\", \"window_in_days\": \"Defaulted(Integer, 30)\" }, \"required_params\": { \"queries\": \"Dict(String, String)\", \"value\": \"String\", \"vendor\": \"String\"} } ] } "/utf8>> ). -file("src/caffeine_lang/parser/artifacts.gleam", 38). ?DOC(" Parses an artifact from an artifacts.json file.\n"). -spec parse_from_file(binary()) -> {ok, list(artifact())} | {error, caffeine_lang@common@errors:compilation_error()}. parse_from_file(File_path) -> gleam@result:'try'( caffeine_lang@common@helpers:json_from_file(File_path), fun(Json_string) -> internal_parse_from_string(Json_string) end ).