-module(squirrel@internal@error). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([to_doc/1]). -export_type([error/0, value_identifier_error/0, type_identifier_error/0, enum_error/0, pointer/0, pointer_kind/0, printable_error/0, paragraph/0]). -type error() :: {pg_cannot_establish_tcp_connection, binary(), integer(), mug:error()} | {pg_invalid_user_database, binary(), binary()} | {pg_unexpected_auth_method_message, binary(), binary()} | {pg_invalid_password, binary()} | {pg_unexpected_cleartext_auth_message, binary(), binary()} | {pg_unexpected_sha256_auth_message, binary(), binary()} | pg_invalid_sha256_server_proof | {pg_unsupported_authentication, binary()} | {pg_cannot_send_message, binary()} | {pg_cannot_decode_received_message, binary()} | {pg_cannot_receive_message, binary()} | {pg_cannot_describe_query, binary(), binary(), binary(), binary()} | {pg_permission_denied, binary(), binary()} | {invalid_connection_string, binary()} | {cannot_read_file, binary(), simplifile:file_error()} | {cannot_write_to_file, binary(), simplifile:file_error()} | {query_file_has_invalid_name, binary(), gleam@option:option(binary()), value_identifier_error()} | {query_has_invalid_column, binary(), binary(), gleam@option:option(binary()), binary(), integer(), value_identifier_error()} | {query_has_unsupported_type, binary(), binary(), binary(), integer(), binary()} | {query_has_invalid_enum, binary(), binary(), integer(), binary(), enum_error()} | {cannot_parse_query, binary(), binary(), binary(), integer(), gleam@option:option(binary()), gleam@option:option(pointer()), gleam@option:option(binary()), gleam@option:option(binary())} | {query_returns_multiple_values_with_the_same_name, binary(), binary(), integer(), list(binary())}. -type value_identifier_error() :: {value_contains_invalid_grapheme, integer(), binary()} | value_is_empty. -type type_identifier_error() :: {type_contains_invalid_grapheme, integer(), binary()} | type_is_empty. -type enum_error() :: enum_with_no_variants | {invalid_enum_name, binary()} | {invalid_enum_variants, list(binary())}. -type pointer() :: {pointer, pointer_kind(), binary()}. -type pointer_kind() :: {name, binary()} | {byte_index, integer()}. -type printable_error() :: {printable_error, binary(), list(paragraph()), gleam@option:option(binary()), gleam@option:option(binary()), gleam@option:option(binary())}. -type paragraph() :: {simple, binary()} | {code, binary(), binary(), gleam@option:option(pointer()), integer()}. -spec style_file(binary()) -> binary(). style_file(File) -> gleam_community@ansi:underline(File). -spec style_inline_code(binary()) -> binary(). style_inline_code(Code) -> <<<<"`"/utf8, Code/binary>>/binary, "`"/utf8>>. -spec style_link(binary()) -> binary(). style_link(Link) -> gleam_community@ansi:underline(Link). -spec printable_error(binary()) -> printable_error(). printable_error(Title) -> {printable_error, Title, [], none, none, none}. -spec add_paragraph(printable_error(), binary()) -> printable_error(). add_paragraph(Error, String) -> erlang:setelement( 3, Error, lists:append(erlang:element(3, Error), [{simple, String}]) ). -spec add_code_paragraph( printable_error(), binary(), binary(), gleam@option:option(pointer()), integer() ) -> printable_error(). add_code_paragraph(Error, File, Content, Point, Starting_line) -> erlang:setelement( 3, Error, lists:append( erlang:element(3, Error), [{code, File, Content, Point, Starting_line}] ) ). -spec report_bug(printable_error(), binary()) -> printable_error(). report_bug(Error, Report_bug) -> erlang:setelement(4, Error, {some, Report_bug}). -spec hint(printable_error(), binary()) -> printable_error(). hint(Error, Hint) -> erlang:setelement(6, Error, {some, Hint}). -spec maybe_hint(printable_error(), gleam@option:option(binary())) -> printable_error(). maybe_hint(Error, Hint) -> erlang:setelement(6, Error, Hint). -spec call_to_action(printable_error(), binary()) -> printable_error(). call_to_action(Error, Wanted) -> erlang:setelement(5, Error, {some, Wanted}). -spec title_doc(binary()) -> glam@doc:document(). title_doc(Title) -> glam@doc:from_string( gleam_community@ansi:red( <<(gleam_community@ansi:bold(<<"Error: "/utf8>>))/binary, Title/binary>> ) ). -spec find_name_span(binary(), integer(), binary(), integer(), integer()) -> {ok, {integer(), integer(), integer()}} | {error, nil}. find_name_span(Name, Name_len, String, Row, Col) -> case gleam@string:starts_with(String, Name) of true -> {ok, {Row, Col, (Col + Name_len) - 1}}; false -> case gleam@string:pop_grapheme(String) of {ok, {<<"\n"/utf8>>, Rest}} -> find_name_span(Name, Name_len, Rest, Row + 1, 0); {ok, {_, Rest@1}} -> find_name_span(Name, Name_len, Rest@1, Row, Col + 1); {error, _} -> {error, nil} end end. -spec find_byte_span(integer(), binary(), integer(), integer()) -> {ok, {integer(), integer(), integer()}} | {error, nil}. find_byte_span(Position, String, Row, Col) -> case Position of 0 -> {ok, {Row, Col, Col}}; N -> case gleam@string:pop_grapheme(String) of {ok, {<<"\n"/utf8>>, Rest}} -> find_byte_span(N - 1, Rest, Row + 1, 0); {ok, {_, Rest@1}} -> find_byte_span(N - 1, Rest@1, Row, Col + 1); {error, _} -> {error, nil} end end. -spec find_span(pointer_kind(), binary()) -> {ok, {integer(), integer(), integer()}} | {error, nil}. find_span(Kind, String) -> case Kind of {name, Name} -> find_name_span(Name, gleam@string:length(Name), String, 0, 0); {byte_index, N} -> find_byte_span(N - 1, String, 0, 0) end. -spec flexible_string(binary()) -> glam@doc:document(). flexible_string(String) -> _pipe = gleam@string:split(String, <<"\n"/utf8>>), _pipe@1 = gleam@list:flat_map( _pipe, fun(_capture) -> gleam@string:split(_capture, <<" "/utf8>>) end ), _pipe@2 = gleam@list:map(_pipe@1, fun glam@doc:from_string/1), _pipe@3 = glam@doc:join(_pipe@2, {flex_break, <<" "/utf8>>, <<""/utf8>>}), glam@doc:group(_pipe@3). -spec pointer_doc(pointer(), binary()) -> {ok, {integer(), integer(), glam@doc:document()}} | {error, nil}. pointer_doc(Pointer, Content) -> {pointer, Kind, Message} = Pointer, gleam@result:'try'( find_span(Kind, Content), fun(_use0) -> {Line, From, To} = _use0, Width = (To - From) + 1, Doc = begin _pipe@1 = [glam@doc:zero_width_string(<<"\x{001B}[31m"/utf8>>), glam@doc:from_string( <<"┬"/utf8, (gleam@string:repeat(<<"─"/utf8>>, Width - 1))/binary>> ), {line, 1}, glam@doc:from_string(<<"╰─ "/utf8>>), begin _pipe = flexible_string(Message), glam@doc:nest(_pipe, 3) end, glam@doc:zero_width_string(<<"\x{001B}[0m"/utf8>>)], _pipe@2 = glam@doc:concat(_pipe@1), glam@doc:group(_pipe@2) end, {ok, {Line, From, Doc}} end ). -spec call_to_action_doc(binary()) -> glam@doc:document(). call_to_action_doc(Wanted) -> flexible_string( <<<<<<"If you would like for "/utf8, Wanted/binary>>/binary, ", please open an issue at "/utf8>>/binary, (style_link( <<"https://github.com/giacomocavalieri/squirrel/issues/new"/utf8>> ))/binary>> ). -spec hint_doc(binary()) -> glam@doc:document(). hint_doc(Hint) -> flexible_string(<<"Hint: "/utf8, Hint/binary>>). -spec option_to_doc(gleam@option:option(TWK), fun((TWK) -> glam@doc:document())) -> glam@doc:document(). option_to_doc(Option, Fun) -> case Option of {some, A} -> Fun(A); none -> {concat, []} end. -spec report_bug_doc(binary()) -> glam@doc:document(). report_bug_doc(Additional_info) -> _pipe@1 = [flexible_string( <<<<"Please open an issue at "/utf8, (style_link( <<"https://github.com/giacomocavalieri/squirrel/issues/new"/utf8>> ))/binary>>/binary, " with some details about what you where doing, including the following message:"/utf8>> ), begin _pipe = {line, 1}, glam@doc:nest(_pipe, 2) end, glam@doc:from_string(Additional_info)], _pipe@2 = glam@doc:concat(_pipe@1), glam@doc:group(_pipe@2). -spec syntax_highlight(binary()) -> binary(). syntax_highlight(Content) -> Keywords = gleam@string:join( [<<"and"/utf8>>, <<"any"/utf8>>, <<"as"/utf8>>, <<"asc"/utf8>>, <<"begin"/utf8>>, <<"between"/utf8>>, <<"by"/utf8>>, <<"case"/utf8>>, <<"commit"/utf8>>, <<"conflict"/utf8>>, <<"constraint"/utf8>>, <<"count"/utf8>>, <<"desc"/utf8>>, <<"distinct"/utf8>>, <<"do"/utf8>>, <<"else"/utf8>>, <<"end"/utf8>>, <<"exists"/utf8>>, <<"from"/utf8>>, <<"full"/utf8>>, <<"group"/utf8>>, <<"having"/utf8>>, <<"if"/utf8>>, <<"in"/utf8>>, <<"inner"/utf8>>, <<"insert"/utf8>>, <<"into"/utf8>>, <<"join"/utf8>>, <<"key"/utf8>>, <<"left"/utf8>>, <<"like"/utf8>>, <<"not"/utf8>>, <<"nothing"/utf8>>, <<"null"/utf8>>, <<"on"/utf8>>, <<"or"/utf8>>, <<"order"/utf8>>, <<"primary"/utf8>>, <<"revert"/utf8>>, <<"right"/utf8>>, <<"select"/utf8>>, <<"set"/utf8>>, <<"table"/utf8>>, <<"top"/utf8>>, <<"trigger"/utf8>>, <<"union"/utf8>>, <<"update"/utf8>>, <<"use"/utf8>>, <<"values"/utf8>>, <<"view"/utf8>>, <<"where"/utf8>>, <<"with"/utf8>>], <<"|"/utf8>> ), Not_inside_string = <<"(?=(?:[^']*'[^']*')*[^']*$)"/utf8>>, _assert_subject = begin _pipe = (<<<<<<"\\b("/utf8, Keywords/binary>>/binary, ")\\b"/utf8>>/binary, Not_inside_string/binary>>), gleam@regex:compile(_pipe, {options, true, false}) end, {ok, Keyword} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"squirrel/internal/error"/utf8>>, function => <<"syntax_highlight"/utf8>>, line => 804}) end, _assert_subject@1 = gleam@regex:from_string( <<"(?> ), {ok, Number} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"squirrel/internal/error"/utf8>>, function => <<"syntax_highlight"/utf8>>, line => 807}) end, _assert_subject@2 = gleam@regex:from_string(<<"(^\\s*--.*)"/utf8>>), {ok, Comment} = case _assert_subject@2 of {ok, _} -> _assert_subject@2; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@2, module => <<"squirrel/internal/error"/utf8>>, function => <<"syntax_highlight"/utf8>>, line => 809}) end, _assert_subject@3 = gleam@regex:from_string(<<"(\\'.*\\')"/utf8>>), {ok, String} = case _assert_subject@3 of {ok, _} -> _assert_subject@3; _assert_fail@3 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@3, module => <<"squirrel/internal/error"/utf8>>, function => <<"syntax_highlight"/utf8>>, line => 810}) end, _assert_subject@4 = gleam@regex:from_string( <<"(\\$\\d+)"/utf8, Not_inside_string/binary>> ), {ok, Hole} = case _assert_subject@4 of {ok, _} -> _assert_subject@4; _assert_fail@4 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@4, module => <<"squirrel/internal/error"/utf8>>, function => <<"syntax_highlight"/utf8>>, line => 811}) end, _pipe@1 = Content, _pipe@2 = gleam_stdlib:regex_replace( Comment, _pipe@1, <<"\x{001B}[2m\\1\x{001B}[0m"/utf8>> ), _pipe@3 = gleam_stdlib:regex_replace( Keyword, _pipe@2, <<"\x{001B}[36m\\1\x{001B}[39m"/utf8>> ), _pipe@4 = gleam_stdlib:regex_replace( String, _pipe@3, <<"\x{001B}[33m\\1\x{001B}[39m"/utf8>> ), _pipe@5 = gleam_stdlib:regex_replace( Number, _pipe@4, <<"\x{001B}[32m\\1\x{001B}[39m"/utf8>> ), gleam_stdlib:regex_replace( Hole, _pipe@5, <<"\x{001B}[35m\\1\x{001B}[39m"/utf8>> ). -spec code_doc(binary(), binary(), gleam@option:option(pointer()), integer()) -> glam@doc:document(). code_doc(File, Content, Pointer, Starting_line) -> Pointer@1 = begin _pipe = gleam@option:to_result(Pointer, nil), gleam@result:then( _pipe, fun(_capture) -> pointer_doc(_capture, Content) end ) end, Content@1 = syntax_highlight(Content), Lines = gleam@string:split(Content@1, <<"\n"/utf8>>), Lines_count = erlang:length(Lines), _assert_subject = gleam@int:digits(Lines_count + Starting_line, 10), {ok, Digits} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"squirrel/internal/error"/utf8>>, function => <<"code_doc"/utf8>>, line => 681}) end, Max_digits = erlang:length(Digits), Code_lines = (gleam@list:index_map( Lines, fun(Line, I) -> Prefix = begin _pipe@1 = gleam@int:to_string(I + Starting_line), gleam@string:pad_left(_pipe@1, Max_digits + 2, <<" "/utf8>>) end, _pipe@4 = case Pointer@1 of {ok, {Pointer_line, From, Pointer_doc}} when Pointer_line =:= I -> [glam@doc:from_string( gleam_community@ansi:dim( <> ) ), glam@doc:from_string(Line), begin _pipe@2 = [{line, 1}, Pointer_doc], _pipe@3 = glam@doc:concat(_pipe@2), glam@doc:nest(_pipe@3, (From + Max_digits) + 5) end]; {ok, _} -> [glam@doc:from_string( gleam_community@ansi:dim( <> ) ), glam@doc:from_string(gleam_community@ansi:dim(Line))]; {error, _} -> [glam@doc:from_string( <<(gleam_community@ansi:dim( <> ))/binary, Line/binary>> )] end, glam@doc:concat(_pipe@4) end )), Padding = gleam@string:repeat(<<" "/utf8>>, Max_digits + 3), _pipe@5 = [glam@doc:from_string( <>))/binary>> ), case Starting_line of 1 -> glam@doc:from_string( <>))/binary>> ); _ -> glam@doc:from_string( <>))/binary>> ) end | Code_lines], _pipe@6 = glam@doc:join(_pipe@5, {line, 1}), _pipe@7 = glam@doc:append(_pipe@6, {line, 1}), _pipe@8 = glam@doc:append( _pipe@7, glam@doc:from_string( <>))/binary>> ) ), glam@doc:group(_pipe@8). -spec paragraph_doc(paragraph()) -> glam@doc:document(). paragraph_doc(Paragraph) -> case Paragraph of {simple, String} -> flexible_string(String); {code, File, Content, Pointer, Starting_line} -> code_doc(File, Content, Pointer, Starting_line) end. -spec body_doc(list(paragraph())) -> glam@doc:document(). body_doc(Body) -> _pipe = gleam@list:map(Body, fun paragraph_doc/1), _pipe@1 = glam@doc:join(_pipe, glam@doc:lines(2)), glam@doc:group(_pipe@1). -spec printable_error_to_doc(printable_error()) -> glam@doc:document(). printable_error_to_doc(Error) -> {printable_error, Title, Body, Report_bug, Call_to_action, Hint} = Error, _pipe = [title_doc(Title), body_doc(Body), option_to_doc(Report_bug, fun report_bug_doc/1), option_to_doc(Call_to_action, fun call_to_action_doc/1), option_to_doc(Hint, fun hint_doc/1)], _pipe@1 = gleam@list:filter(_pipe, fun(Doc) -> Doc /= {concat, []} end), _pipe@2 = glam@doc:join(_pipe@1, glam@doc:lines(2)), glam@doc:group(_pipe@2). -spec to_doc(error()) -> glam@doc:document(). to_doc(Error) -> Printable_error = case Error of {pg_cannot_establish_tcp_connection, Host, Port, Reason} -> _pipe = printable_error(<<"Cannot establish TCP connection"/utf8>>), add_paragraph(_pipe, case Reason of econnrefused -> <<<<<<<<"I couldn't connect to the database because "/utf8, (style_inline_code(Host))/binary>>/binary, " refused the connection to port "/utf8>>/binary, (gleam@int:to_string(Port))/binary>>/binary, "."/utf8>>; closed -> <<<<<<<<"I couldn't connect to the database because "/utf8, (style_inline_code(Host))/binary>>/binary, " closed the connection to port "/utf8>>/binary, (gleam@int:to_string(Port))/binary>>/binary, "."/utf8>>; ehostunreach -> <<<<"I couldn't connect to the database because "/utf8, (style_inline_code(Host))/binary>>/binary, " is unreachable."/utf8>>; timeout -> <<<<<<<<"I couldn't connect to "/utf8, (style_inline_code(Host))/binary>>/binary, " at port "/utf8>>/binary, (gleam@int:to_string(Port))/binary>>/binary, " because the connection timed out."/utf8>>; _ -> <<<<<<<<<<"I couldn't connect to the database because I ran into the following problem while trying to establish a TCP connection to "/utf8, (style_inline_code(Host))/binary>>/binary, " at port "/utf8>>/binary, (gleam@int:to_string(Port))/binary>>/binary, ": "/utf8>>/binary, (gleam@string:inspect(Reason))/binary>> end); {pg_invalid_user_database, User, Database} -> _pipe@1 = printable_error(<<"Cannot connect"/utf8>>), _pipe@2 = add_paragraph( _pipe@1, <<<<<<<<"I couldn't connect to database "/utf8, (style_inline_code(Database))/binary>>/binary, " with user "/utf8>>/binary, (style_inline_code(User))/binary>>/binary, "."/utf8>> ), hint( _pipe@2, <<<<<<<<"You can change the default user and database by setting the "/utf8, (style_inline_code(<<"PGUSER"/utf8>>))/binary>>/binary, " and "/utf8>>/binary, (style_inline_code(<<"PGDATABASE"/utf8>>))/binary>>/binary, " environment variables."/utf8>> ); {pg_unexpected_auth_method_message, Expected, Got} -> _pipe@3 = printable_error( <<"Cannot authenticate (no-method)"/utf8>> ), _pipe@4 = add_paragraph( _pipe@3, <<"I ran into an unexpected problem while trying to authenticate with the Postgres server. This is most definitely a bug!"/utf8>> ), report_bug( _pipe@4, <<<<<<"Expected: "/utf8, Expected/binary>>/binary, ", Got: "/utf8>>/binary, Got/binary>> ); {pg_invalid_password, User@1} -> _pipe@5 = printable_error(<<"Cannot authenticate"/utf8>>), _pipe@6 = add_paragraph( _pipe@5, <<<<"Invalid password for user "/utf8, (style_inline_code(User@1))/binary>>/binary, "."/utf8>> ), hint( _pipe@6, <<<<"You can change the default password used to authenticate by setting the "/utf8, (style_inline_code(<<"PGPASSWORD"/utf8>>))/binary>>/binary, " environment variable."/utf8>> ); {pg_unexpected_cleartext_auth_message, Expected@1, Got@1} -> _pipe@7 = printable_error( <<"Cannot authenticate (cleartext)"/utf8>> ), _pipe@8 = add_paragraph( _pipe@7, <<"I ran into an unexpected problem while trying to authenticate with the Postgres server. This is most definitely a bug!"/utf8>> ), report_bug( _pipe@8, <<<<<<"Expected: "/utf8, Expected@1/binary>>/binary, ", Got: "/utf8>>/binary, Got@1/binary>> ); {pg_unexpected_sha256_auth_message, Expected@2, Got@2} -> _pipe@9 = printable_error(<<"Cannot authenticate (sha256)"/utf8>>), _pipe@10 = add_paragraph( _pipe@9, <<"I ran into an unexpected problem while trying to authenticate with the Postgres server. This is most definitely a bug!"/utf8>> ), report_bug( _pipe@10, <<<<<<"Expected: "/utf8, Expected@2/binary>>/binary, ", Got: "/utf8>>/binary, Got@2/binary>> ); pg_invalid_sha256_server_proof -> _pipe@11 = printable_error(<<"Cannot authenticate"/utf8>>), add_paragraph( _pipe@11, <<"I couldn't authenticate with the Postgres server."/utf8>> ); {pg_unsupported_authentication, Auth} -> _pipe@12 = printable_error( <<"Unsupported authentication method"/utf8>> ), _pipe@13 = add_paragraph( _pipe@12, <<<<"The Postgres server is asking to authenticate using the "/utf8, Auth/binary>>/binary, " authentication method, which I currently do not support."/utf8>> ), call_to_action( _pipe@13, <<"this authentication method to be supported"/utf8>> ); {pg_cannot_send_message, Reason@1} -> _pipe@14 = printable_error(<<"Cannot send message"/utf8>>), _pipe@15 = add_paragraph( _pipe@14, <<"I ran into an unexpected error while trying to talk to the Postgres database server."/utf8>> ), report_bug(_pipe@15, Reason@1); {pg_cannot_decode_received_message, Reason@2} -> _pipe@16 = printable_error(<<"Cannot decode message"/utf8>>), _pipe@17 = add_paragraph( _pipe@16, <<"I ran into an unexpected error while trying to decode a message received from the Postgres database server."/utf8>> ), report_bug(_pipe@17, Reason@2); {pg_cannot_receive_message, Reason@3} -> _pipe@18 = printable_error(<<"Cannot receive message"/utf8>>), _pipe@19 = add_paragraph( _pipe@18, <<"I ran into an unexpected error while trying to listen to the Postgres database server."/utf8>> ), report_bug(_pipe@19, Reason@3); {pg_cannot_describe_query, File, Query_name, Expected@3, Got@3} -> _pipe@20 = printable_error(<<"Cannot inspect query"/utf8>>), _pipe@21 = add_paragraph( _pipe@20, <<<<<<<<"I ran into an unexpected problem while trying to figure out the types of query "/utf8, (style_inline_code(Query_name))/binary>>/binary, " defined in "/utf8>>/binary, (style_file(File))/binary>>/binary, ". This is most definitely a bug!"/utf8>> ), report_bug( _pipe@21, <<<<<<"Expected: "/utf8, Expected@3/binary>>/binary, ", Got: "/utf8>>/binary, Got@3/binary>> ); {pg_permission_denied, Query_file, Reason@4} -> _pipe@22 = printable_error(<<"Permission denied"/utf8>>), _pipe@23 = add_paragraph( _pipe@22, <<<<<<<<"I cannot type the query defined in "/utf8, (style_link(Query_file))/binary>>/binary, " because the server denied me permission with the following message: "/utf8>>/binary, Reason@4/binary>>/binary, "."/utf8>> ), hint( _pipe@23, <<"Make sure the current user has the privileges to run this query."/utf8>> ); {invalid_connection_string, String} -> _pipe@24 = printable_error(<<"Invalid connection string"/utf8>>), _pipe@25 = add_paragraph( _pipe@24, <<<<<<<<"The value of the "/utf8, (style_inline_code(<<"DATABASE_URL"/utf8>>))/binary>>/binary, " variable "/utf8>>/binary, (style_inline_code(String))/binary>>/binary, " is not a valid connection string."/utf8>> ), hint( _pipe@25, <<"A connection string should have the following format: "/utf8, (style_inline_code( <<"postgres://username:password@host:port/database_name"/utf8>> ))/binary>> ); {cannot_read_file, File@1, Reason@5} -> _pipe@26 = printable_error(<<"Cannot read file"/utf8>>), add_paragraph( _pipe@26, <<<<<<"I couldn't read "/utf8, (style_file(File@1))/binary>>/binary, " because of the following error: "/utf8>>/binary, (simplifile:describe_error(Reason@5))/binary>> ); {cannot_write_to_file, File@2, Reason@6} -> _pipe@27 = printable_error(<<"Cannot write to file"/utf8>>), add_paragraph( _pipe@27, <<<<<<"I couldn't write to "/utf8, (style_file(File@2))/binary>>/binary, " because of the following error: "/utf8>>/binary, (simplifile:describe_error(Reason@6))/binary>> ); {query_file_has_invalid_name, File@3, Suggested_name, _} -> _pipe@28 = printable_error(<<"Query file with invalid name"/utf8>>), _pipe@29 = add_paragraph( _pipe@28, <<<<"File "/utf8, (style_file(File@3))/binary>>/binary, " doesn't have a valid name. The name of a file is used to generate a corresponding Gleam function, so it should be a valid Gleam name."/utf8>> ), hint( _pipe@29, <<"A file name must start with a lowercase letter and can only contain lowercase letters, numbers and underscores."/utf8, (case Suggested_name of {some, Name} -> <<<<"\nMaybe try renaming it to "/utf8, (style_inline_code(Name))/binary>>/binary, "?"/utf8>>; none -> <<""/utf8>> end)/binary>> ); {query_has_invalid_column, File@4, Column_name, Suggested_name@1, Content, Starting_line, Reason@7} -> case Reason@7 of value_is_empty -> _pipe@30 = printable_error( <<"Column with empty name"/utf8>> ), _pipe@31 = add_code_paragraph( _pipe@30, File@4, Content, none, Starting_line ), add_paragraph( _pipe@31, <<"A column returned by this query has the empty string as a name, all columns should have a valid Gleam name as name."/utf8>> ); _ -> _pipe@32 = printable_error( <<"Column with invalid name"/utf8>> ), _pipe@33 = add_code_paragraph( _pipe@32, File@4, Content, {some, {pointer, {name, Column_name}, case Suggested_name@1 of none -> <<"This is not a valid Gleam name"/utf8>>; {some, Suggestion} -> <<<<"This is not a valid Gleam name, maybe try "/utf8, (style_inline_code(Suggestion))/binary>>/binary, "?"/utf8>> end}}, Starting_line ), hint( _pipe@33, <<"A column name must start with a lowercase letter and can only contain lowercase letters, numbers and underscores."/utf8>> ) end; {query_has_invalid_enum, File@5, Content@1, Starting_line@1, Enum_name, Reason@8} -> _pipe@34 = printable_error(<<"Query with invalid enum"/utf8>>), _pipe@35 = add_code_paragraph( _pipe@34, File@5, Content@1, none, Starting_line@1 ), _pipe@37 = add_paragraph( _pipe@35, <<<<<<"One of the values in this query is the "/utf8, (style_inline_code(Enum_name))/binary>>/binary, " enum, but I cannot turn it into a Gleam type definition because "/utf8>>/binary, (case Reason@8 of enum_with_no_variants -> <<"it has no variants."/utf8>>; {invalid_enum_name, _} -> <<"its name cannot be turned into a valid type name."/utf8>>; {invalid_enum_variants, Fields} -> Pretty_fields = begin _pipe@36 = gleam@list:map( Fields, fun style_inline_code/1 ), gleam@string:join(_pipe@36, <<", "/utf8>>) end, <<<<"some of its possible values ("/utf8, Pretty_fields/binary>>/binary, ") cannot be turned into valid type variants."/utf8>> end)/binary>> ), maybe_hint(_pipe@37, case Reason@8 of {invalid_enum_variants, _} -> {some, <<"A valid enum variant must start with a letter and can only contain letters, underscores and numbers. I will take care of automatically converting any snake_case variant to PascalCase so that it can be used as a variant of a Gleam type!"/utf8>>}; {invalid_enum_name, _} -> {some, <<"A valid enum name must start with a letter and can only contain letters, underscores and numbers. I will take care automatically of converting any snake_case name to PascalCase so that it can be used as the name of a Gleam type!"/utf8>>}; enum_with_no_variants -> none end); {query_has_unsupported_type, File@6, _, Content@2, Starting_line@2, Type_} -> _pipe@38 = printable_error(<<"Unsupported type"/utf8>>), _pipe@39 = add_code_paragraph( _pipe@38, File@6, Content@2, none, Starting_line@2 ), _pipe@40 = add_paragraph( _pipe@39, <<<<"One of the rows returned by this query has type "/utf8, (style_inline_code(Type_))/binary>>/binary, " which I cannot currently generate code for."/utf8>> ), call_to_action(_pipe@40, <<"this type to be supported"/utf8>>); {cannot_parse_query, File@7, _, Content@3, Starting_line@3, Error_code, Pointer, Additional_error_message, Hint} -> Error@1 = begin _pipe@41 = printable_error(case Error_code of {some, Code} -> <<<<"Invalid query ["/utf8, Code/binary>>/binary, "]"/utf8>>; none -> <<"Invalid query"/utf8>> end), _pipe@42 = add_code_paragraph( _pipe@41, File@7, Content@3, Pointer, Starting_line@3 ), maybe_hint(_pipe@42, Hint) end, case Additional_error_message of {some, Message} -> add_paragraph(Error@1, Message); none -> Error@1 end; {query_returns_multiple_values_with_the_same_name, File@8, Content@4, Starting_line@4, Names} -> Pretty_names = begin _pipe@43 = gleam@list:map(Names, fun style_inline_code/1), gleam@string:join(_pipe@43, <<", "/utf8>>) end, Name@1 = case Names of [] -> <<"names"/utf8>>; [_, _ | _] -> <<"names"/utf8>>; [_] -> <<"name"/utf8>> end, _pipe@44 = printable_error(<<"Duplicate names"/utf8>>), _pipe@45 = add_code_paragraph( _pipe@44, File@8, Content@4, none, Starting_line@4 ), add_paragraph( _pipe@45, <<<<<<<<"This query returns multiple values sharing the same "/utf8, Name@1/binary>>/binary, ": "/utf8>>/binary, Pretty_names/binary>>/binary, "."/utf8>> ) end, printable_error_to_doc(Printable_error).