-module(atproto_codegen). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/atproto_codegen.gleam"). -export([main/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( " Lexicon -> Gleam codegen. Reads `/**/*.json` and writes\n" " typed modules into ``, importable as `/...`.\n" "\n" " Pipeline: read lexicon files, decode via `atproto_lexicon/decoding` into\n" " `ast.LexiconDoc`, `codegen/lower` flattens those into the view plugins\n" " consume, `codegen/plugin` runs the registered plugins and assembles\n" " their per-module sections, `codegen/module_header` computes each\n" " module's import header, then this module writes the files.\n" ). -file("src/atproto_codegen.gleam", 216). -spec parent_dir(binary()) -> binary(). parent_dir(Path) -> case begin _pipe = gleam@string:split(Path, <<"/"/utf8>>), lists:reverse(_pipe) end of [_ | Rest] -> _pipe@1 = Rest, _pipe@2 = lists:reverse(_pipe@1), gleam@string:join(_pipe@2, <<"/"/utf8>>); [] -> <<"."/utf8>> end. -file("src/atproto_codegen.gleam", 127). ?DOC(" The xrpc-client plugin owns a whole file, so this writes its `WholeFile` content verbatim instead of the per-lexicon banner/header wrapping above.\n"). -spec write_client( atproto_codegen@config:config(), gleam@dict:dict(binary(), binary()) ) -> nil. write_client(Cfg, Bodies) -> case erlang:element(6, Cfg) of none -> nil; {some, Path} -> Full_path = <<<<<<(erlang:element(3, Cfg))/binary, "/"/utf8>>/binary, Path/binary>>/binary, ".gleam"/utf8>>, Content@1 = case gleam_stdlib:map_get( Bodies, <> ) of {ok, Content} -> Content; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"write_client"/utf8>>, line => 132, value => _assert_fail, start => 4540, 'end' => 4599, pattern_start => 4551, pattern_end => 4562}) end, case simplifile:create_directory_all(parent_dir(Full_path)) of {ok, _} -> nil; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"write_client"/utf8>>, line => 133, value => _assert_fail@1, start => 4606, 'end' => 4679, pattern_start => 4617, pattern_end => 4622}) end, case simplifile:write(Full_path, Content@1) of {ok, _} -> nil; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"write_client"/utf8>>, line => 134, value => _assert_fail@2, start => 4686, 'end' => 4755, pattern_start => 4697, pattern_end => 4702}) end, gleam_stdlib:println(<<" gen "/utf8, Full_path/binary>>) end. -file("src/atproto_codegen.gleam", 59). ?DOC(" `types` then `decode-json` interleave per section; the opt-in `xrpc-client` runs last and owns its own whole file, so it never interleaves.\n"). -spec plugin_order(atproto_codegen@config:config()) -> list(binary()). plugin_order(Cfg) -> case erlang:element(6, Cfg) of {some, _} -> [<<"types"/utf8>>, <<"decode-json"/utf8>>, <<"xrpc-client"/utf8>>]; none -> [<<"types"/utf8>>, <<"decode-json"/utf8>>] end. -file("src/atproto_codegen.gleam", 66). -spec plugins(atproto_codegen@config:config()) -> list(atproto_codegen@plugin:plugin()). plugins(Cfg) -> case erlang:element(6, Cfg) of {some, _} -> [atproto_codegen@plugins@types:plugin(), atproto_codegen@plugins@decode_json:plugin(), atproto_codegen@plugins@xrpc_client:plugin()]; none -> [atproto_codegen@plugins@types:plugin(), atproto_codegen@plugins@decode_json:plugin()] end. -file("src/atproto_codegen.gleam", 141). -spec internal_template() -> binary(). internal_template() -> Priv = begin _pipe = gleam_erlang_ffi:priv_directory(<<"atproto_codegen"/utf8>>), gleam@result:unwrap(_pipe, <<"priv"/utf8>>) end, <>. -file("src/atproto_codegen.gleam", 211). -spec ref_key(binary(), binary()) -> list(binary()). ref_key(Current, Ref) -> R = atproto_codegen@naming:parse_ref(Current, Ref), [<<<<(erlang:element(2, R))/binary, "#"/utf8>>/binary, (erlang:element(3, R))/binary>>]. -file("src/atproto_codegen.gleam", 202). -spec field_ref_keys(binary(), atproto_codegen@lower:flat_type()) -> list(binary()). field_ref_keys(Current, Ft) -> case Ft of {t_ref, Ref} -> ref_key(Current, Ref); {t_union, Refs, _} -> gleam@list:flat_map( Refs, fun(_capture) -> ref_key(Current, _capture) end ); {t_array, Inner} -> field_ref_keys(Current, Inner); _ -> [] end. -file("src/atproto_codegen.gleam", 173). ?DOC(" Warn about any `ref` pointing at a def we never generate, which would otherwise emit Gleam that doesn't compile with no signal from codegen.\n"). -spec report_unresolved_refs(list(atproto_codegen@lower:flat_lexicon())) -> nil. report_unresolved_refs(Lexicons) -> Known = gleam@list:flat_map( Lexicons, fun(Lex) -> gleam@list:filter_map(erlang:element(4, Lex), fun(D) -> case D of {flat_record, Nsid, _} -> {ok, <>}; {flat_object, Nsid@1, Name, _} -> {ok, <<<>/binary, Name/binary>>}; _ -> {error, nil} end end) end ), Refs = gleam@list:flat_map( Lexicons, fun(Lex@1) -> gleam@list:flat_map( erlang:element(4, Lex@1), fun(D@1) -> gleam@list:flat_map( atproto_codegen@lower:properties_of(D@1), fun(P) -> field_ref_keys( erlang:element(2, Lex@1), erlang:element(3, P) ) end ) end ) end ), _pipe = Refs, _pipe@1 = gleam@list:unique(_pipe), _pipe@2 = gleam@list:filter( _pipe@1, fun(Key) -> not gleam@list:contains(Known, Key) end ), gleam@list:each( _pipe@2, fun(Key@1) -> gleam_stdlib:println( <<<<" WARN unresolved ref "/utf8, Key@1/binary>>/binary, " (referencing def won't compile)"/utf8>> ) end ). -file("src/atproto_codegen.gleam", 158). ?DOC(" Loud on purpose: a dropped def must never be silent.\n"). -spec report_unsupported(list(atproto_codegen@lower:flat_lexicon())) -> nil. report_unsupported(Lexicons) -> gleam@list:each( Lexicons, fun(Lex) -> gleam@list:each(erlang:element(4, Lex), fun(D) -> case D of {flat_unsupported, Nsid, Name, Reason} -> gleam_stdlib:println( <<<<<<<<<<" WARN skipping "/utf8, Nsid/binary>>/binary, "#"/utf8>>/binary, Name/binary>>/binary, ": "/utf8>>/binary, Reason/binary>> ); _ -> nil end end) end ). -file("src/atproto_codegen.gleam", 148). -spec load_doc(binary()) -> {ok, atproto_lexicon@ast:lexicon_doc()} | {error, binary()}. load_doc(Path) -> gleam@result:'try'( begin _pipe = simplifile:read(Path), gleam@result:map_error( _pipe, fun(E) -> <<"read failed: "/utf8, (gleam@string:inspect(E))/binary>> end ) end, fun(Contents) -> _pipe@1 = atproto_lexicon@decoding:decode_json(Contents), gleam@result:map_error( _pipe@1, fun(E@1) -> <<"parse failed: "/utf8, (gleam@string:inspect(E@1))/binary>> end ) end ). -file("src/atproto_codegen.gleam", 73). -spec run(atproto_codegen@config:config()) -> nil. run(Cfg) -> Files@1 = case simplifile:get_files(erlang:element(2, Cfg)) of {ok, Files} -> Files; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 74, value => _assert_fail, start => 2509, 'end' => 2570, pattern_start => 2520, pattern_end => 2529}) end, Docs = begin _pipe = Files@1, _pipe@1 = gleam@list:filter( _pipe, fun(_capture) -> gleam_stdlib:string_ends_with(_capture, <<".json"/utf8>>) end ), gleam@list:filter_map(_pipe@1, fun(Path) -> case load_doc(Path) of {ok, Doc} -> {ok, Doc}; {error, Reason} -> gleam_stdlib:println( <<<<<<" WARN skipping "/utf8, Path/binary>>/binary, ": "/utf8>>/binary, Reason/binary>> ), {error, nil} end end) end, Lexicons = atproto_codegen@lower:lower(Docs), report_unsupported(Lexicons), report_unresolved_refs(Lexicons), case simplifile:create_directory_all(erlang:element(3, Cfg)) of {ok, _} -> nil; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 92, value => _assert_fail@1, start => 2978, 'end' => 3041, pattern_start => 2989, pattern_end => 2994}) end, Internal@1 = case simplifile:read(internal_template()) of {ok, Internal} -> Internal; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 93, value => _assert_fail@2, start => 3044, 'end' => 3106, pattern_start => 3055, pattern_end => 3067}) end, case simplifile:write( <<(erlang:element(3, Cfg))/binary, "/internal.gleam"/utf8>>, <<"//// Generated by codegen from priv/internal.gleam. Do not edit by hand.\n\n"/utf8, Internal@1/binary>> ) of {ok, _} -> nil; _assert_fail@3 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 94, value => _assert_fail@3, start => 3109, 'end' => 3245, pattern_start => 3120, pattern_end => 3125}) end, Outputs@1 = case atproto_codegen@plugin:run( plugins(Cfg), Cfg, Docs, Lexicons ) of {ok, Outputs} -> Outputs; _assert_fail@4 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 100, value => _assert_fail@4, start => 3249, 'end' => 3319, pattern_start => 3260, pattern_end => 3271}) end, Assembled@1 = case atproto_codegen@plugin:assemble( Outputs@1, plugin_order(Cfg) ) of {ok, Assembled} -> Assembled; _assert_fail@5 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 101, value => _assert_fail@5, start => 3322, 'end' => 3392, pattern_start => 3333, pattern_end => 3346}) end, Bodies = maps:from_list(Assembled@1), gleam@list:each( Lexicons, fun(Lex) -> case gleam@list:filter( erlang:element(4, Lex), fun atproto_codegen@lower:is_emittable/1 ) of [] -> nil; Defs -> Subpath = atproto_codegen@naming:module_subpath( erlang:element(5, Cfg), erlang:element(2, Lex) ), Path@1 = <>, Body@1 = case gleam_stdlib:map_get(Bodies, Path@1) of {ok, Body} -> Body; _assert_fail@6 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 110, value => _assert_fail@6, start => 3672, 'end' => 3716, pattern_start => 3683, pattern_end => 3691}) end, Header = atproto_codegen@module_header:header( Cfg, erlang:element(2, Lex), Defs ), Source = <<<<<<<<"//// Generated by codegen from lexicons/. Do not edit by hand.\n\n"/utf8, Header/binary>>/binary, "\n"/utf8>>/binary, Body@1/binary>>/binary, "\n"/utf8>>, Full_path = <<<<(erlang:element(3, Cfg))/binary, "/"/utf8>>/binary, Path@1/binary>>, case simplifile:create_directory_all(parent_dir(Full_path)) of {ok, _} -> nil; _assert_fail@7 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 114, value => _assert_fail@7, start => 3908, 'end' => 3991, pattern_start => 3919, pattern_end => 3924}) end, case simplifile:write(Full_path, Source) of {ok, _} -> nil; _assert_fail@8 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"atproto_codegen"/utf8>>, function => <<"run"/utf8>>, line => 116, value => _assert_fail@8, start => 4000, 'end' => 4068, pattern_start => 4011, pattern_end => 4016}) end, gleam_stdlib:println(<<" gen "/utf8, Full_path/binary>>) end end ), write_client(Cfg, Bodies), gleam_stdlib:println(<<"codegen: done"/utf8>>). -file("src/atproto_codegen.gleam", 36). -spec main() -> nil. main() -> case erlang:element(4, argv:load()) of [Lexicons_dir, Out_dir, Out_module, Prefixes] -> run( {config, Lexicons_dir, Out_dir, Out_module, gleam@string:split(Prefixes, <<","/utf8>>), none} ); [Lexicons_dir@1, Out_dir@1, Out_module@1, Prefixes@1, Client] -> run( {config, Lexicons_dir@1, Out_dir@1, Out_module@1, gleam@string:split(Prefixes@1, <<","/utf8>>), {some, Client}} ); _ -> gleam_stdlib:println( <<"usage: gleam run -- [,...] []"/utf8>> ) end.