Current section
Files
Jump to
Current section
Files
src/squirrel@internal@query.erl
-module(squirrel@internal@query).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([add_types/3, from_file/1, generate_code/2]).
-export_type([untyped_query/0, typed_query/0, code_gen_state/0, enum_code_gen_data/0, enum_required_helpers/0]).
-type untyped_query() :: {untyped_query,
binary(),
integer(),
squirrel@internal@gleam:value_identifier(),
list(binary()),
binary()}.
-type typed_query() :: {typed_query,
binary(),
integer(),
squirrel@internal@gleam:value_identifier(),
list(binary()),
binary(),
list(squirrel@internal@gleam:type()),
list(squirrel@internal@gleam:field())}.
-type code_gen_state() :: {code_gen_state,
gleam@dict:dict(binary(), gleam@set:set(binary())),
boolean(),
boolean(),
boolean(),
gleam@dict:dict(squirrel@internal@gleam:type_identifier(), enum_code_gen_data())}.
-type enum_code_gen_data() :: {enum_code_gen_data,
enum_required_helpers(),
binary(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())}.
-type enum_required_helpers() :: needs_encoder_and_decoder |
needs_decoder |
needs_encoder |
no_helpers.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 90).
-spec duplicate_names(list(squirrel@internal@gleam:field())) -> list(binary()).
duplicate_names(Fields) ->
Names = (gleam@list:fold(
Fields,
tote@bag:new(),
fun(Bag, _use1) ->
{field, Label, _} = _use1,
tote@bag:insert(
Bag,
1,
squirrel@internal@gleam:value_identifier_to_string(Label)
)
end
)),
tote@bag:fold(
Names,
[],
fun(Duplicate_names, Field, Copies) -> case Copies of
1 ->
Duplicate_names;
_ ->
[Field | Duplicate_names]
end end
).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 61).
-spec add_types(
untyped_query(),
list(squirrel@internal@gleam:type()),
list(squirrel@internal@gleam:field())
) -> {ok, typed_query()} | {error, squirrel@internal@error:error()}.
add_types(Query, Params, Returns) ->
{untyped_query, File, Starting_line, Name, Comment, Content} = Query,
case duplicate_names(Returns) of
[] ->
{ok,
{typed_query,
File,
Starting_line,
Name,
Comment,
Content,
Params,
Returns}};
Names ->
{error,
{query_returns_multiple_values_with_the_same_name,
File,
Content,
Starting_line,
Names}}
end.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 145).
-spec do_take_comment(binary(), list(binary())) -> list(binary()).
do_take_comment(Query, Lines) ->
case gleam@string:trim_start(Query) of
<<"--"/utf8, Rest/binary>> ->
case gleam@string:split_once(Rest, <<"\n"/utf8>>) of
{ok, {Line, Rest@1}} ->
do_take_comment(Rest@1, [gleam@string:trim(Line) | Lines]);
_ ->
do_take_comment(
<<""/utf8>>,
[gleam@string:trim(Rest) | Lines]
)
end;
_ ->
lists:reverse(Lines)
end.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 141).
-spec take_comment(binary()) -> list(binary()).
take_comment(Query) ->
do_take_comment(Query, []).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 109).
-spec from_file(binary()) -> {ok, untyped_query()} |
{error, squirrel@internal@error:error()}.
from_file(File) ->
Read_file = begin
_pipe = simplifile:read(File),
gleam@result:map_error(
_pipe,
fun(_capture) -> {cannot_read_file, File, _capture} end
)
end,
gleam@result:'try'(
Read_file,
fun(Content) ->
File_name = begin
_pipe@1 = filepath:base_name(File),
filepath:strip_extension(_pipe@1)
end,
Name = begin
_pipe@2 = squirrel@internal@gleam:value_identifier(File_name),
gleam@result:map_error(
_pipe@2,
fun(_capture@1) ->
{query_file_has_invalid_name,
File,
begin
_pipe@3 = squirrel@internal@gleam:similar_value_identifier_string(
File_name
),
gleam@option:from_result(_pipe@3)
end,
_capture@1}
end
)
end,
gleam@result:'try'(
Name,
fun(Name@1) ->
{ok,
{untyped_query,
File,
1,
Name@1,
take_comment(Content),
Content}}
end
)
end
).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 249).
-spec enum_decoder_name(squirrel@internal@gleam:type_identifier()) -> binary().
enum_decoder_name(Enum_name) ->
_pipe = squirrel@internal@gleam:type_identifier_to_value_identifier(
Enum_name
),
_pipe@1 = squirrel@internal@gleam:value_identifier_to_string(_pipe),
gleam@string:append(_pipe@1, <<"_decoder"/utf8>>).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 299).
-spec enum_encoder_name(squirrel@internal@gleam:type_identifier()) -> binary().
enum_encoder_name(Enum_name) ->
_pipe = squirrel@internal@gleam:type_identifier_to_value_identifier(
Enum_name
),
_pipe@1 = squirrel@internal@gleam:value_identifier_to_string(_pipe),
gleam@string:append(_pipe@1, <<"_encoder"/utf8>>).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 406).
-spec separator_comment(binary()) -> glam@doc:document().
separator_comment(Value) ->
_pipe = gleam@string:pad_end(
<<<<"// --- "/utf8, Value/binary>>/binary, " "/utf8>>,
80,
<<"-"/utf8>>
),
glam@doc:from_string(_pipe).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 512).
-spec function_doc(binary(), typed_query()) -> binary().
function_doc(Version, Query) ->
{typed_query, File, _, Name, Comment, _, _, _} = Query,
Function_name = squirrel@internal@gleam:value_identifier_to_string(Name),
Base = case Comment of
[] ->
<<<<<<<<"/// Runs the `"/utf8, Function_name/binary>>/binary,
"` query
/// defined in `"/utf8>>/binary,
File/binary>>/binary,
"`."/utf8>>;
[_ | _] ->
_pipe = gleam@list:map(
Comment,
fun(_capture) ->
gleam@string:append(<<"/// "/utf8>>, _capture)
end
),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end,
<<<<<<Base/binary,
"
///
/// > 🐿️ This function was generated automatically using "/utf8>>/binary,
Version/binary>>/binary,
" of
/// > the [squirrel package](https://github.com/giacomocavalieri/squirrel).
///"/utf8>>.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 871).
-spec let_var(binary(), glam@doc:document()) -> glam@doc:document().
let_var(Name, Body) ->
_pipe = [glam@doc:from_string(
<<<<"let "/utf8, Name/binary>>/binary, " ="/utf8>>
),
{break, <<" "/utf8>>, <<""/utf8>>},
Body],
glam@doc:concat(_pipe).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 881).
-spec string_doc(binary()) -> glam@doc:document().
string_doc(Content) ->
Escaped_string = begin
_pipe = Content,
_pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>),
glam@doc:from_string(_pipe@2)
end,
_pipe@3 = [glam@doc:from_string(<<"\""/utf8>>),
Escaped_string,
glam@doc:from_string(<<"\""/utf8>>)],
glam@doc:concat(_pipe@3).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 915).
-spec import_module(code_gen_state(), binary()) -> code_gen_state().
import_module(State, Name) ->
Imports = case gleam@dict:has_key(erlang:element(2, State), Name) of
false ->
gleam@dict:insert(erlang:element(2, State), Name, gleam@set:new());
true ->
erlang:element(2, State)
end,
erlang:setelement(2, State, Imports).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 197).
-spec default_codegen_state() -> code_gen_state().
default_codegen_state() ->
_pipe = {code_gen_state,
gleam@dict:new(),
false,
false,
false,
gleam@dict:new()},
_pipe@1 = import_module(_pipe, <<"decode/zero"/utf8>>),
import_module(_pipe@1, <<"pog"/utf8>>).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 923).
-spec import_qualified(code_gen_state(), binary(), binary()) -> code_gen_state().
import_qualified(State, Module, Imported) ->
Imports = gleam@dict:upsert(
erlang:element(2, State),
Module,
fun(Imported_values) -> case Imported_values of
{some, Imported_values@1} ->
gleam@set:insert(Imported_values@1, Imported);
none ->
gleam@set:from_list([Imported])
end end
),
erlang:setelement(2, State, Imports).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 939).
-spec register_enum_type(
code_gen_state(),
binary(),
squirrel@internal@gleam:type_identifier(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())
) -> code_gen_state().
register_enum_type(State, Original_name, Name, Variants) ->
Enums = case gleam@dict:has_key(erlang:element(6, State), Name) of
true ->
erlang:element(6, State);
false ->
gleam@dict:insert(
erlang:element(6, State),
Name,
{enum_code_gen_data, no_helpers, Original_name, Variants}
)
end,
erlang:setelement(6, State, Enums).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 958).
-spec enum_needs_encoder(
code_gen_state(),
binary(),
squirrel@internal@gleam:type_identifier(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())
) -> code_gen_state().
enum_needs_encoder(State, Original_name, Name, Variants) ->
Enums = gleam@dict:upsert(
erlang:element(6, State),
Name,
fun(Value) -> case Value of
{some, {enum_code_gen_data, no_helpers, _, _} = Data} ->
erlang:setelement(2, Data, needs_encoder);
{some, {enum_code_gen_data, needs_decoder, _, _} = Data@1} ->
erlang:setelement(2, Data@1, needs_encoder_and_decoder);
{some, {enum_code_gen_data, needs_encoder, _, _} = Data@2} ->
Data@2;
{some,
{enum_code_gen_data, needs_encoder_and_decoder, _, _} = Data@2} ->
Data@2;
none ->
{enum_code_gen_data, needs_encoder, Original_name, Variants}
end end
),
erlang:setelement(6, State, Enums).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 988).
-spec enum_needs_decoder(
code_gen_state(),
binary(),
squirrel@internal@gleam:type_identifier(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())
) -> code_gen_state().
enum_needs_decoder(State, Original_name, Name, Variants) ->
Enums = gleam@dict:upsert(
erlang:element(6, State),
Name,
fun(Value) -> case Value of
{some, {enum_code_gen_data, no_helpers, _, _} = Data} ->
erlang:setelement(2, Data, needs_decoder);
{some, {enum_code_gen_data, needs_encoder, _, _} = Data@1} ->
erlang:setelement(2, Data@1, needs_encoder_and_decoder);
{some, {enum_code_gen_data, needs_decoder, _, _} = Data@2} ->
Data@2;
{some,
{enum_code_gen_data, needs_encoder_and_decoder, _, _} = Data@2} ->
Data@2;
none ->
{enum_code_gen_data, needs_decoder, Original_name, Variants}
end end
),
erlang:setelement(6, State, Enums).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 1020).
-spec prepend_if(list(VBU), boolean(), VBU) -> list(VBU).
prepend_if(List, Condition, Item) ->
case Condition of
true ->
[Item | List];
false ->
List
end.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 411).
-spec imports_doc(gleam@dict:dict(binary(), gleam@set:set(binary()))) -> glam@doc:document().
imports_doc(Imports) ->
Sorted_imports = begin
_pipe = maps:to_list(Imports),
gleam@list:sort(
_pipe,
fun(One, Other) ->
gleam@string:compare(
erlang:element(1, One),
erlang:element(1, Other)
)
end
)
end,
_pipe@9 = (gleam@list:map(
Sorted_imports,
fun(_use0) ->
{Module, Imported_values} = _use0,
Import_line = glam@doc:from_string(
<<"import "/utf8, Module/binary>>
),
gleam@bool:guard(
gleam@set:is_empty(Imported_values),
Import_line,
fun() ->
Imported_values@1 = begin
_pipe@1 = gleam@set:to_list(Imported_values),
_pipe@2 = gleam@list:sort(
_pipe@1,
fun gleam@string:compare/2
),
_pipe@3 = gleam@list:map(
_pipe@2,
fun glam@doc:from_string/1
),
_pipe@4 = glam@doc:join(
_pipe@3,
glam@doc:break(<<", "/utf8>>, <<","/utf8>>)
),
glam@doc:group(_pipe@4)
end,
_pipe@8 = [Import_line,
glam@doc:from_string(<<".{"/utf8>>),
begin
_pipe@5 = [{break, <<""/utf8>>, <<""/utf8>>},
Imported_values@1],
_pipe@6 = glam@doc:concat(_pipe@5),
_pipe@7 = glam@doc:group(_pipe@6),
glam@doc:nest(_pipe@7, 2)
end,
{break, <<""/utf8>>, <<""/utf8>>},
glam@doc:from_string(<<"}"/utf8>>)],
glam@doc:concat(_pipe@8)
end
)
end
)),
glam@doc:join(_pipe@9, {line, 1}).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 829).
-spec block(list(glam@doc:document())) -> glam@doc:document().
block(Body) ->
_pipe@2 = [glam@doc:from_string(<<"{"/utf8>>),
begin
_pipe = [{line, 1} | Body],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:nest(_pipe@1, 2)
end,
{line, 1},
glam@doc:from_string(<<"}"/utf8>>)],
glam@doc:concat(_pipe@2).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 629).
-spec enum_type_definition_doc(
binary(),
squirrel@internal@gleam:type_identifier(),
binary(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())
) -> glam@doc:document().
enum_type_definition_doc(Version, Enum_name, Original_name, Variants) ->
String_enum_name = squirrel@internal@gleam:type_identifier_to_string(
Enum_name
),
Variants@1 = non_empty_list:map(
Variants,
fun(Variant) ->
_pipe = squirrel@internal@gleam:type_identifier_to_string(
erlang:element(2, Variant)
),
glam@doc:from_string(_pipe)
end
),
Enum_doc = <<<<<<<<"/// Corresponds to the Postgres `"/utf8,
Original_name/binary>>/binary,
"` enum.
///
/// > 🐿️ This type definition was generated automatically using "/utf8>>/binary,
Version/binary>>/binary,
" of the
/// > [squirrel package](https://github.com/giacomocavalieri/squirrel).
///"/utf8>>,
_pipe@4 = [glam@doc:from_string(Enum_doc),
{line, 1},
glam@doc:from_string(
<<<<"pub type "/utf8, String_enum_name/binary>>/binary, " "/utf8>>
),
begin
_pipe@1 = Variants@1,
_pipe@2 = non_empty_list:to_list(_pipe@1),
_pipe@3 = gleam@list:intersperse(_pipe@2, {line, 1}),
block(_pipe@3)
end],
glam@doc:concat(_pipe@4).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 661).
-spec enum_encoder_doc(
squirrel@internal@gleam:type_identifier(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())
) -> glam@doc:document().
enum_encoder_doc(Name, Variants) ->
Case_lines = (non_empty_list:map(
Variants,
fun(Variant) ->
_pipe = [glam@doc:from_string(
squirrel@internal@gleam:type_identifier_to_string(
erlang:element(2, Variant)
)
),
glam@doc:from_string(<<" -> "/utf8>>),
string_doc(erlang:element(3, Variant))],
glam@doc:concat(_pipe)
end
)),
Body = [glam@doc:from_string(<<"case variant "/utf8>>),
begin
_pipe@1 = Case_lines,
_pipe@2 = non_empty_list:to_list(_pipe@1),
_pipe@3 = gleam@list:intersperse(_pipe@2, {line, 1}),
block(_pipe@3)
end,
{line, 1},
glam@doc:from_string(<<"|> pog.text"/utf8>>)],
_pipe@4 = glam@doc:from_string(
<<<<"fn "/utf8, (enum_encoder_name(Name))/binary>>/binary,
"(variant) "/utf8>>
),
glam@doc:append(_pipe@4, block(Body)).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 894).
-spec comma_list(binary(), list(glam@doc:document()), binary()) -> glam@doc:document().
comma_list(Open, Content, Close) ->
_pipe@3 = [glam@doc:from_string(Open),
begin
_pipe = [{break, <<""/utf8>>, <<""/utf8>>},
glam@doc:join(
Content,
glam@doc:break(<<", "/utf8>>, <<","/utf8>>)
)],
_pipe@1 = glam@doc:concat(_pipe),
_pipe@2 = glam@doc:group(_pipe@1),
glam@doc:nest(_pipe@2, 2)
end,
glam@doc:break(<<""/utf8>>, <<","/utf8>>),
glam@doc:from_string(Close)],
_pipe@4 = glam@doc:concat(_pipe@3),
glam@doc:group(_pipe@4).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 821).
-spec call_doc(binary(), list(glam@doc:document())) -> glam@doc:document().
call_doc(Function, Args) ->
_pipe = [glam@doc:from_string(Function),
comma_list(<<"("/utf8>>, Args, <<")"/utf8>>)],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:group(_pipe@1).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 209).
-spec gleam_type_to_decoder(code_gen_state(), squirrel@internal@gleam:type()) -> {code_gen_state(),
glam@doc:document()}.
gleam_type_to_decoder(State, Type_) ->
case Type_ of
uuid ->
State@1 = begin
_pipe = erlang:setelement(3, State, true),
import_module(_pipe, <<"youid/uuid"/utf8>>)
end,
{State@1, glam@doc:from_string(<<"uuid_decoder()"/utf8>>)};
{list, Type_@1} ->
{State@2, Inner_decoder} = gleam_type_to_decoder(State, Type_@1),
{State@2, call_doc(<<"zero.list"/utf8>>, [Inner_decoder])};
{option, Type_@2} ->
{State@3, Inner_decoder@1} = gleam_type_to_decoder(State, Type_@2),
{State@3, call_doc(<<"zero.optional"/utf8>>, [Inner_decoder@1])};
date ->
State@4 = erlang:setelement(4, State, true),
{State@4, glam@doc:from_string(<<"date_decoder()"/utf8>>)};
timestamp ->
State@5 = erlang:setelement(5, State, true),
{State@5, glam@doc:from_string(<<"timestamp_decoder()"/utf8>>)};
int ->
{State, glam@doc:from_string(<<"zero.int"/utf8>>)};
float ->
{State, glam@doc:from_string(<<"zero.float"/utf8>>)};
bool ->
{State, glam@doc:from_string(<<"zero.bool"/utf8>>)};
string ->
{State, glam@doc:from_string(<<"zero.string"/utf8>>)};
bit_array ->
{State, glam@doc:from_string(<<"zero.bit_array"/utf8>>)};
json ->
{State, glam@doc:from_string(<<"zero.string"/utf8>>)};
{enum, Original_name, Enum_name, Variants} ->
{begin
_pipe@1 = State,
enum_needs_decoder(
_pipe@1,
Original_name,
Enum_name,
Variants
)
end,
glam@doc:from_string(
<<(enum_decoder_name(Enum_name))/binary, "()"/utf8>>
)}
end.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 305).
-spec gleam_type_to_field_type(code_gen_state(), squirrel@internal@gleam:type()) -> {code_gen_state(),
glam@doc:document()}.
gleam_type_to_field_type(State, Type_) ->
case Type_ of
{list, Type_@1} ->
{State@1, Inner_type} = gleam_type_to_field_type(State, Type_@1),
{State@1, call_doc(<<"List"/utf8>>, [Inner_type])};
{option, Type_@2} ->
State@2 = begin
_pipe = State,
import_qualified(
_pipe,
<<"gleam/option"/utf8>>,
<<"type Option"/utf8>>
)
end,
{State@3, Inner_type@1} = gleam_type_to_field_type(State@2, Type_@2),
{State@3, call_doc(<<"Option"/utf8>>, [Inner_type@1])};
uuid ->
{begin
_pipe@1 = State,
import_qualified(
_pipe@1,
<<"youid/uuid"/utf8>>,
<<"type Uuid"/utf8>>
)
end,
glam@doc:from_string(<<"Uuid"/utf8>>)};
date ->
{State, glam@doc:from_string(<<"pog.Date"/utf8>>)};
timestamp ->
{State, glam@doc:from_string(<<"pog.Timestamp"/utf8>>)};
int ->
{State, glam@doc:from_string(<<"Int"/utf8>>)};
float ->
{State, glam@doc:from_string(<<"Float"/utf8>>)};
bool ->
{State, glam@doc:from_string(<<"Bool"/utf8>>)};
string ->
{State, glam@doc:from_string(<<"String"/utf8>>)};
json ->
{State, glam@doc:from_string(<<"String"/utf8>>)};
bit_array ->
{State, glam@doc:from_string(<<"BitArray"/utf8>>)};
{enum, Original_name, Name, Variants} ->
{begin
_pipe@2 = State,
register_enum_type(_pipe@2, Original_name, Name, Variants)
end,
begin
_pipe@3 = squirrel@internal@gleam:type_identifier_to_string(
Name
),
glam@doc:from_string(_pipe@3)
end}
end.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 538).
-spec record_doc(code_gen_state(), binary(), binary(), typed_query()) -> {ok,
{code_gen_state(), glam@doc:document()}} |
{error, nil}.
record_doc(State, Version, Type_name, Query) ->
{typed_query, File, _, Name, _, _, _, Returns} = Query,
gleam@bool:guard(
Returns =:= [],
{error, nil},
fun() ->
Function_name = squirrel@internal@gleam:value_identifier_to_string(
Name
),
Record_doc = <<<<<<<<<<<<"/// A row you get from running the `"/utf8,
Function_name/binary>>/binary,
"` query
/// defined in `"/utf8>>/binary,
File/binary>>/binary,
"`.
///
/// > 🐿️ This type definition was generated automatically using "/utf8>>/binary,
Version/binary>>/binary,
" of the
/// > [squirrel package](https://github.com/giacomocavalieri/squirrel).
///"/utf8>>,
{State@3, Fields@1} = (gleam@list:fold(
Returns,
{State, []},
fun(_use0, Field) ->
{State@1, Fields} = _use0,
Label = glam@doc:from_string(
<<(squirrel@internal@gleam:value_identifier_to_string(
erlang:element(2, Field)
))/binary,
": "/utf8>>
),
{State@2, Field_type} = gleam_type_to_field_type(
State@1,
erlang:element(3, Field)
),
Field@1 = begin
_pipe = [Label, Field_type],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:group(_pipe@1)
end,
{State@2, [Field@1 | Fields]}
end
)),
Fields@2 = lists:reverse(Fields@1),
Result = begin
_pipe@6 = [glam@doc:from_string(Record_doc),
{line, 1},
begin
_pipe@4 = [glam@doc:from_string(
<<<<"pub type "/utf8, Type_name/binary>>/binary,
" {"/utf8>>
),
begin
_pipe@2 = [{line, 1},
call_doc(Type_name, Fields@2)],
_pipe@3 = glam@doc:concat(_pipe@2),
glam@doc:nest(_pipe@3, 2)
end,
{line, 1},
glam@doc:from_string(<<"}"/utf8>>)],
_pipe@5 = glam@doc:concat(_pipe@4),
glam@doc:group(_pipe@5)
end],
glam@doc:concat(_pipe@6)
end,
{ok, {State@3, Result}}
end
).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 686).
-spec enum_decoder_doc(
squirrel@internal@gleam:type_identifier(),
non_empty_list:non_empty_list(squirrel@internal@gleam:enum_variant())
) -> glam@doc:document().
enum_decoder_doc(Name, Variants) ->
Success_case_lines = (non_empty_list:map(
Variants,
fun(Variant) ->
glam@doc:concat(
[string_doc(erlang:element(3, Variant)),
glam@doc:from_string(<<" -> "/utf8>>),
call_doc(
<<"zero.success"/utf8>>,
[begin
_pipe = squirrel@internal@gleam:type_identifier_to_string(
erlang:element(2, Variant)
),
glam@doc:from_string(_pipe)
end]
)]
)
end
)),
Failure_case_line = begin
_pipe@1 = [glam@doc:from_string(<<"_ -> "/utf8>>),
call_doc(
<<"zero.failure"/utf8>>,
[glam@doc:from_string(
squirrel@internal@gleam:type_identifier_to_string(
erlang:element(2, erlang:element(2, Variants))
)
),
string_doc(
squirrel@internal@gleam:type_identifier_to_string(Name)
)]
)],
glam@doc:concat(_pipe@1)
end,
Body = begin
_pipe@6 = [glam@doc:from_string(
<<"use variant <- zero.then(zero.string)"/utf8>>
),
{line, 1},
glam@doc:from_string(<<"case variant "/utf8>>),
begin
_pipe@2 = Success_case_lines,
_pipe@3 = non_empty_list:to_list(_pipe@2),
_pipe@4 = lists:append(_pipe@3, [Failure_case_line]),
_pipe@5 = gleam@list:intersperse(_pipe@4, {line, 1}),
block(_pipe@5)
end],
glam@doc:concat(_pipe@6)
end,
_pipe@7 = glam@doc:from_string(
<<<<"fn "/utf8, (enum_decoder_name(Name))/binary>>/binary, "() "/utf8>>
),
glam@doc:append(_pipe@7, block([Body])).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 601).
-spec enum_doc(
binary(),
squirrel@internal@gleam:type_identifier(),
enum_code_gen_data()
) -> glam@doc:document().
enum_doc(Version, Enum_name, Enum_data) ->
{enum_code_gen_data, Required_helpers, Original_name, Variants} = Enum_data,
_pipe = case Required_helpers of
needs_decoder ->
[enum_type_definition_doc(
Version,
Enum_name,
Original_name,
Variants
),
enum_decoder_doc(Enum_name, Variants)];
needs_encoder ->
[enum_type_definition_doc(
Version,
Enum_name,
Original_name,
Variants
),
enum_encoder_doc(Enum_name, Variants)];
needs_encoder_and_decoder ->
[enum_type_definition_doc(
Version,
Enum_name,
Original_name,
Variants
),
enum_decoder_doc(Enum_name, Variants),
enum_encoder_doc(Enum_name, Variants)];
no_helpers ->
[enum_type_definition_doc(
Version,
Enum_name,
Original_name,
Variants
)]
end,
glam@doc:join(_pipe, glam@doc:lines(2)).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 590).
-spec enums_doc(
binary(),
gleam@dict:dict(squirrel@internal@gleam:type_identifier(), enum_code_gen_data())
) -> glam@doc:document().
enums_doc(Version, Enums) ->
gleam@dict:fold(
Enums,
{concat, []},
fun(Doc, Name, Enum_data) ->
glam@doc:append(Doc, enum_doc(Version, Name, Enum_data))
end
).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 810).
-spec pipe_call_doc(binary(), glam@doc:document(), list(glam@doc:document())) -> glam@doc:document().
pipe_call_doc(Function, First, Rest) ->
_pipe = [First, {line, 1}, call_doc(<<"|> "/utf8, Function/binary>>, Rest)],
glam@doc:concat(_pipe).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 507).
-spec pipe_all_encoders(glam@doc:document(), list(glam@doc:document())) -> glam@doc:document().
pipe_all_encoders(Doc, Decoders) ->
gleam@list:fold(Decoders, Doc, fun(Doc@1, Decoder) -> _pipe = Doc@1,
pipe_call_doc(<<"pog.parameter"/utf8>>, _pipe, [Decoder]) end).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 843).
-spec fun_doc(binary(), list(binary()), list(glam@doc:document())) -> glam@doc:document().
fun_doc(Name, Args, Body) ->
Args@1 = gleam@list:map(Args, fun glam@doc:from_string/1),
_pipe@1 = [glam@doc:from_string(<<"pub fn "/utf8, Name/binary>>),
comma_list(<<"("/utf8>>, Args@1, <<") "/utf8>>),
block(
[begin
_pipe = Body,
glam@doc:join(_pipe, glam@doc:lines(2))
end]
)],
_pipe@2 = glam@doc:concat(_pipe@1),
glam@doc:group(_pipe@2).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 855).
-spec fn_doc(list(binary()), glam@doc:document()) -> glam@doc:document().
fn_doc(Args, Body) ->
_pipe@2 = [glam@doc:from_string(<<"fn"/utf8>>),
comma_list(
<<"("/utf8>>,
gleam@list:map(Args, fun glam@doc:from_string/1),
<<") {"/utf8>>
),
begin
_pipe = [{break, <<" "/utf8>>, <<""/utf8>>}, Body],
_pipe@1 = glam@doc:concat(_pipe),
glam@doc:nest(_pipe@1, 2)
end,
{break, <<" "/utf8>>, <<""/utf8>>},
glam@doc:from_string(<<"}"/utf8>>)],
_pipe@3 = glam@doc:concat(_pipe@2),
glam@doc:group(_pipe@3).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 255).
-spec gleam_type_to_encoder(
code_gen_state(),
squirrel@internal@gleam:type(),
binary()
) -> {code_gen_state(), glam@doc:document()}.
gleam_type_to_encoder(State, Type_, Name) ->
Name@1 = glam@doc:from_string(Name),
case Type_ of
{list, Type_@1} ->
State@1 = begin
_pipe = State,
import_module(_pipe, <<"gleam/list"/utf8>>)
end,
{State@2, Inner_encoder} = gleam_type_to_encoder(
State@1,
Type_@1,
<<"value"/utf8>>
),
Map_fn = fn_doc([<<"value"/utf8>>], Inner_encoder),
Doc = call_doc(<<"pog.array"/utf8>>, [Map_fn, Name@1]),
{State@2, Doc};
{option, Type_@2} ->
{State@3, Inner_encoder@1} = gleam_type_to_encoder(
State,
Type_@2,
<<"value"/utf8>>
),
Doc@1 = call_doc(
<<"pog.nullable"/utf8>>,
[fn_doc([<<"value"/utf8>>], Inner_encoder@1), Name@1]
),
{State@3, Doc@1};
uuid ->
State@4 = begin
_pipe@1 = State,
import_module(_pipe@1, <<"youid/uuid"/utf8>>)
end,
Doc@2 = call_doc(
<<"pog.text"/utf8>>,
[call_doc(<<"uuid.to_string"/utf8>>, [Name@1])]
),
{State@4, Doc@2};
json ->
State@5 = begin
_pipe@2 = State,
import_module(_pipe@2, <<"gleam/json"/utf8>>)
end,
Doc@3 = call_doc(
<<"pog.text"/utf8>>,
[call_doc(<<"json.to_string"/utf8>>, [Name@1])]
),
{State@5, Doc@3};
date ->
{State, call_doc(<<"pog.date"/utf8>>, [Name@1])};
timestamp ->
{State, call_doc(<<"pog.timestamp"/utf8>>, [Name@1])};
int ->
{State, call_doc(<<"pog.int"/utf8>>, [Name@1])};
float ->
{State, call_doc(<<"pog.float"/utf8>>, [Name@1])};
bool ->
{State, call_doc(<<"pog.bool"/utf8>>, [Name@1])};
string ->
{State, call_doc(<<"pog.text"/utf8>>, [Name@1])};
bit_array ->
{State, call_doc(<<"pog.bytea"/utf8>>, [Name@1])};
{enum, Original_name, Enum_name, Variants} ->
{begin
_pipe@3 = State,
enum_needs_encoder(
_pipe@3,
Original_name,
Enum_name,
Variants
)
end,
call_doc(enum_encoder_name(Enum_name), [Name@1])}
end.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 770).
-spec decoder_doc(
code_gen_state(),
binary(),
list(squirrel@internal@gleam:field())
) -> {code_gen_state(), glam@doc:document()}.
decoder_doc(State, Constructor, Returns) ->
Fallback = {State,
glam@doc:from_string(<<"zero.map(zero.dynamic, fn(_) { Nil })"/utf8>>)},
gleam@bool:guard(
Returns =:= [],
Fallback,
fun() ->
{State@3, Parameters@2, Labelled_names@2} = (gleam@list:index_fold(
Returns,
{State, [], []},
fun(Acc, Field, I) ->
{State@1, Parameters, Labelled_names} = Acc,
Label = squirrel@internal@gleam:value_identifier_to_string(
erlang:element(2, Field)
),
Labelled_names@1 = [glam@doc:from_string(
<<Label/binary, ":"/utf8>>
) |
Labelled_names],
Position = begin
_pipe = gleam@int:to_string(I),
glam@doc:from_string(_pipe)
end,
{State@2, Decoder} = gleam_type_to_decoder(
State@1,
erlang:element(3, Field)
),
Param = begin
_pipe@1 = glam@doc:from_string(
<<<<"use "/utf8, Label/binary>>/binary,
" <- "/utf8>>
),
glam@doc:append(
_pipe@1,
call_doc(<<"zero.field"/utf8>>, [Position, Decoder])
)
end,
Parameters@1 = [Param | Parameters],
{State@2, Parameters@1, Labelled_names@1}
end
)),
Parameters@3 = lists:reverse(Parameters@2),
Labelled_names@3 = lists:reverse(Labelled_names@2),
Doc = block(
[glam@doc:join(Parameters@3, {line, 1}),
{line, 1},
call_doc(
<<"zero.success"/utf8>>,
[call_doc(Constructor, Labelled_names@3)]
)]
),
{State@3, Doc}
end
).
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 446).
-spec query_doc(code_gen_state(), binary(), typed_query()) -> {code_gen_state(),
glam@doc:document()}.
query_doc(State, Version, Query) ->
{typed_query, _, _, Name, _, Content, Params, Returns} = Query,
Constructor_name = begin
_pipe = squirrel@internal@gleam:value_identifier_to_type_identifier(
Name
),
_pipe@1 = squirrel@internal@gleam:type_identifier_to_string(_pipe),
gleam@string:append(_pipe@1, <<"Row"/utf8>>)
end,
Record_result = record_doc(State, Version, Constructor_name, Query),
{State@2, Record@1} = case Record_result of
{ok, {State@1, Record}} ->
{State@1, glam@doc:append(Record, glam@doc:lines(2))};
{error, _} ->
{State, {concat, []}}
end,
{State@5, Inputs@1, Encoders@1} = begin
Acc = {State@2, [], []},
gleam@list:index_fold(
Params,
Acc,
fun(Acc@1, Param, I) ->
{State@3, Inputs, Encoders} = Acc@1,
Input = <<"arg_"/utf8, (gleam@int:to_string(I + 1))/binary>>,
{State@4, Encoder} = gleam_type_to_encoder(
State@3,
Param,
Input
),
{State@4, [Input | Inputs], [Encoder | Encoders]}
end
)
end,
Inputs@2 = lists:reverse(Inputs@1),
Encoders@2 = lists:reverse(Encoders@1),
{State@6, Decoder} = decoder_doc(State@5, Constructor_name, Returns),
Zero_decoder = call_doc(
<<"zero.run"/utf8>>,
[glam@doc:from_string(<<"_"/utf8>>),
glam@doc:from_string(<<"decoder"/utf8>>)]
),
Code = begin
_pipe@5 = [Record@1,
glam@doc:from_string(function_doc(Version, Query)),
{line, 1},
fun_doc(
squirrel@internal@gleam:value_identifier_to_string(Name),
[<<"db"/utf8>> | Inputs@2],
[let_var(<<"decoder"/utf8>>, Decoder),
let_var(<<"query"/utf8>>, string_doc(Content)),
begin
_pipe@2 = call_doc(
<<"pog.query"/utf8>>,
[glam@doc:from_string(<<"query"/utf8>>)]
),
_pipe@3 = pipe_all_encoders(_pipe@2, Encoders@2),
_pipe@4 = pipe_call_doc(
<<"pog.returning"/utf8>>,
_pipe@3,
[Zero_decoder]
),
pipe_call_doc(
<<"pog.execute"/utf8>>,
_pipe@4,
[glam@doc:from_string(<<"db"/utf8>>)]
)
end]
)],
glam@doc:concat(_pipe@5)
end,
{State@6, Code}.
-file("/home/runner/work/squirrel/squirrel/src/squirrel/internal/query.gleam", 340).
-spec generate_code(list(typed_query()), binary()) -> binary().
generate_code(Queries, Version) ->
{State@3, Queries_docs} = begin
State = default_codegen_state(),
gleam@list:fold(
Queries,
{State, []},
fun(_use0, Query) ->
{State@1, Docs} = _use0,
{State@2, Doc} = query_doc(State@1, Version, Query),
{State@2, [Doc | Docs]}
end
)
end,
Queries_docs@1 = lists:reverse(Queries_docs),
{code_gen_state,
Imports,
Needs_uuid_decoder,
Needs_date_decoder,
Needs_timestamp_decoder,
Enums} = State@3,
Utils = begin
_pipe = [],
_pipe@1 = prepend_if(
_pipe,
Needs_uuid_decoder,
glam@doc:from_string(
<<"/// A decoder to decode `Uuid`s coming from a Postgres query.
///
fn uuid_decoder() {
use bit_array <- zero.then(zero.bit_array)
case uuid.from_bit_array(bit_array) {
Ok(uuid) -> zero.success(uuid)
Error(_) -> zero.failure(uuid.v7(), \"uuid\")
}
}"/utf8>>
)
),
_pipe@2 = prepend_if(
_pipe@1,
Needs_date_decoder,
glam@doc:from_string(
<<"/// A decoder to decode `date`s coming from a Postgres query.
///
fn date_decoder() {
use dynamic <- zero.then(zero.dynamic)
case pog.decode_date(dynamic) {
Ok(date) -> zero.success(date)
Error(_) -> zero.failure(pog.Date(0, 0, 0), \"date\")
}
}"/utf8>>
)
),
prepend_if(
_pipe@2,
Needs_timestamp_decoder,
glam@doc:from_string(
<<"/// A decoder to decode `timestamp`s coming from a Postgres query.
///
fn timestamp_decoder() {
use dynamic <- zero.then(zero.dynamic)
case pog.decode_timestamp(dynamic) {
Ok(timestamp) -> zero.success(timestamp)
Error(_) -> {
let date = pog.Date(0, 0, 0)
let time = pog.Time(0, 0, 0, 0)
zero.failure(pog.Timestamp(date:, time:), \"timestamp\")
}
}
}"/utf8>>
)
)
end,
Code = begin
_pipe@3 = [imports_doc(Imports),
glam@doc:lines(2),
glam@doc:join(Queries_docs@1, glam@doc:lines(2))],
glam@doc:concat(_pipe@3)
end,
Code@1 = case gleam@dict:is_empty(Enums) of
true ->
Code;
false ->
_pipe@4 = [Code,
glam@doc:lines(2),
separator_comment(<<"Enums"/utf8>>),
glam@doc:lines(2),
enums_doc(Version, Enums)],
glam@doc:concat(_pipe@4)
end,
Code@2 = case Utils of
[] ->
Code@1;
[_ | _] ->
_pipe@5 = [Code@1,
glam@doc:lines(2),
separator_comment(<<"Encoding/decoding utils"/utf8>>),
glam@doc:lines(2),
glam@doc:join(Utils, glam@doc:lines(2))],
glam@doc:concat(_pipe@5)
end,
_pipe@6 = Code@2,
_pipe@7 = glam@doc:append(_pipe@6, {line, 1}),
glam@doc:to_string(_pipe@7, 80).