Packages

A SurrealDB Orm for Gleam!

Current section

Files

Jump to
surreal_gleam src sg_engine.erl
Raw

src/sg_engine.erl

-module(sg_engine).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([root_sign_in/2, exec/1, execute_transaction/2, create_database/1, create_namespace/1, use_namespace/1, use_database/1, find_field/1, emit_fields/2, create_table_schemafull/2, create_table_schemaless/2, add_field/3, add_default_field/4, generate/1]).
-spec build_request(binary(), binary(), gleam@http:method()) -> gleam@http@request:request(binary()).
build_request(Base, Endpoint, Method) ->
_assert_subject = gleam@http@request:to(<<Base/binary, Endpoint/binary>>),
{ok, Request} = 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 => <<"sg_engine"/utf8>>,
function => <<"build_request"/utf8>>,
line => 19})
end,
gleam@http@request:set_method(Request, Method).
-spec with_token(gleam@http@request:request(binary()), binary()) -> gleam@http@request:request(binary()).
with_token(Request, Token) ->
_pipe = Request,
gleam@http@request:prepend_header(
_pipe,
<<"Authorization"/utf8>>,
<<"Bearer "/utf8, Token/binary>>
).
-spec with_header(gleam@http@request:request(binary()), binary(), binary()) -> gleam@http@request:request(binary()).
with_header(Request, Key, Value) ->
_pipe = Request,
gleam@http@request:prepend_header(_pipe, Key, Value).
-spec execute_request(gleam@http@request:request(binary())) -> {ok,
gleam@http@response:response(binary())} |
{error, gleam@hackney:error()}.
execute_request(Request) ->
_pipe = Request,
gleam@hackney:send(_pipe).
-spec root_sign_in(binary(), binary()) -> {ok, binary()} | {error, binary()}.
root_sign_in(Username, Password) ->
Error_msg = <<"Failed to Sign In!"/utf8>>,
Request = begin
_pipe = build_request(
<<"http://localhost:8000/"/utf8>>,
<<"signin"/utf8>>,
post
),
_pipe@1 = gleam@http@request:prepend_header(
_pipe,
<<"Accept"/utf8>>,
<<"application/json"/utf8>>
),
gleam@http@request:set_body(
_pipe@1,
<<<<<<<<"{ \"user\":\""/utf8, Username/binary>>/binary,
"\", \"pass\":\""/utf8>>/binary,
Password/binary>>/binary,
"\"}"/utf8>>
)
end,
Response = execute_request(Request),
case Response of
{ok, Resp} ->
case erlang:element(2, Resp) of
200 ->
Token_json = begin
_pipe@2 = erlang:element(4, Resp),
_pipe@3 = gleam@string:replace(
_pipe@2,
<<"}"/utf8>>,
<<""/utf8>>
),
_pipe@4 = gleam@string:replace(
_pipe@3,
<<"\""/utf8>>,
<<""/utf8>>
),
_pipe@5 = gleam@string:split(_pipe@4, <<","/utf8>>),
gleam@list:filter(_pipe@5, fun(X) -> _pipe@6 = X,
gleam_stdlib:contains_string(
_pipe@6,
<<"token"/utf8>>
) end)
end,
case begin
_pipe@7 = Token_json,
gleam@list:first(_pipe@7)
end of
{ok, X@1} ->
case begin
_pipe@8 = gleam@string:split(X@1, <<":"/utf8>>),
gleam@list:last(_pipe@8)
end of
{ok, X@2} ->
{ok, X@2};
{error, _} ->
{error, Error_msg}
end;
_ ->
{error, Error_msg}
end;
_ ->
{error, Error_msg}
end;
{error, _} ->
{error, Error_msg}
end.
-spec exec(list({ok, binary()} | {error, binary()})) -> nil.
exec(Lines) ->
_pipe = Lines,
gleam@list:each(_pipe, fun(Res) -> case Res of
{ok, X} ->
gleam@io:println(X);
{error, X@1} ->
gleam@io:print_error(X@1)
end end).
-spec inner_iterate(
list({ok, binary()} | {error, binary()}),
list({ok, binary()} | {error, binary()})
) -> list({ok, binary()} | {error, binary()}).
inner_iterate(Statements, Acc) ->
case Statements of
[Head | Rest] ->
case Head of
{ok, X} ->
inner_iterate(Rest, [{ok, X} | Acc]);
{error, X@1} ->
inner_iterate(Rest, [{error, X@1} | Acc])
end;
[] ->
Acc
end.
-spec iterate(list({ok, binary()} | {error, binary()})) -> list({ok, binary()} |
{error, binary()}).
iterate(Statements) ->
inner_iterate(
begin
_pipe = Statements,
lists:reverse(_pipe)
end,
[]
).
-spec execute_transaction(list({ok, binary()} | {error, binary()}), binary()) -> {ok,
binary()} |
{error, binary()}.
execute_transaction(Statements, Token) ->
Generated_lines = begin
_pipe = [{ok, <<"BEGIN TRANSACTION;"/utf8>>}],
_pipe@1 = lists:append(_pipe, Statements),
_pipe@2 = lists:append(_pipe@1, [{ok, <<"COMMIT TRANSACTION;"/utf8>>}]),
iterate(_pipe@2)
end,
Errors = begin
_pipe@3 = Generated_lines,
gleam@list:filter(_pipe@3, fun(A) -> case A of
{error, _} ->
true;
_ ->
false
end end)
end,
case erlang:length(Errors) of
X when X > 0 ->
Errors;
_ ->
_pipe@4 = Generated_lines,
gleam@list:map(_pipe@4, fun(X@1) -> case X@1 of
{ok, Val} ->
{ok, Val};
_ ->
{ok, <<""/utf8>>}
end end)
end,
Error_msg = <<"Failed to Sign In!"/utf8>>,
Body = gleam@list:fold(Statements, <<""/utf8>>, fun(A@1, B) -> case B of
{ok, X@2} ->
<<A@1/binary, X@2/binary>>;
_ ->
<<""/utf8>>
end end),
gleam@io:debug(Body),
Request = begin
_pipe@5 = build_request(
<<"http://localhost:8000/"/utf8>>,
<<"sql"/utf8>>,
post
),
_pipe@6 = gleam@http@request:prepend_header(
_pipe@5,
<<"Accept"/utf8>>,
<<"application/json"/utf8>>
),
_pipe@7 = with_token(_pipe@6, Token),
gleam@http@request:set_body(_pipe@7, Body)
end,
Response = execute_request(Request),
case Response of
{ok, Resp} ->
case erlang:element(2, Resp) of
200 ->
{ok, erlang:element(4, Resp)};
_ ->
{error, Error_msg}
end;
{error, _} ->
{error, Error_msg}
end.
-spec create_database(binary()) -> {ok, binary()} | {error, binary()}.
create_database(Name) ->
{ok, <<<<"DEFINE DATABASE "/utf8, Name/binary>>/binary, ";"/utf8>>}.
-spec create_namespace(binary()) -> {ok, binary()} | {error, binary()}.
create_namespace(Name) ->
{ok, <<<<"DEFINE NAMESPACE "/utf8, Name/binary>>/binary, ";"/utf8>>}.
-spec use_namespace(binary()) -> {ok, binary()} | {error, binary()}.
use_namespace(Name) ->
{ok, <<<<"USE NAMESPACE "/utf8, Name/binary>>/binary, ";"/utf8>>}.
-spec use_database(binary()) -> {ok, binary()} | {error, binary()}.
use_database(Name) ->
{ok, <<<<"USE db "/utf8, Name/binary>>/binary, ";"/utf8>>}.
-spec find_field(types:field_type()) -> binary().
find_field(X) ->
case X of
int ->
<<"int"/utf8>>;
float ->
<<"float"/utf8>>;
decimal ->
<<"decimal"/utf8>>;
string ->
<<"string"/utf8>>;
boolean ->
<<"bool"/utf8>>;
date_time ->
<<"datetime"/utf8>>;
record ->
<<"record"/utf8>>;
object ->
<<"object"/utf8>>;
{set, X@1} ->
<<<<"Set<"/utf8, (find_field(X@1))/binary>>/binary, ">"/utf8>>;
{option, X@2} ->
find_field(X@2);
{array, X@3} ->
<<<<"array<"/utf8, (find_field(X@3))/binary>>/binary, ">"/utf8>>;
{geometry, Shape} ->
<<"geometry"/utf8, (case Shape of
feature ->
<<"<feature>"/utf8>>;
point ->
<<"<point>"/utf8>>;
multi_point ->
<<"<multipoint>"/utf8>>;
line_string ->
<<"<LineString>"/utf8>>;
multi_line ->
<<"<multiline>"/utf8>>;
polygon ->
<<"<polygon>"/utf8>>;
multi_polygon ->
<<"<multipolygon>"/utf8>>;
collection ->
<<"<collection"/utf8>>
end)/binary>>;
none ->
<<"NONE"/utf8>>;
_ ->
<<""/utf8>>
end.
-spec emit_fields(
list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}),
binary()
) -> list({ok, binary()} | {error, binary()}).
emit_fields(X, Table) ->
_pipe = X,
_pipe@1 = lists:reverse(_pipe),
gleam@list:map(_pipe@1, fun(Entity) -> case Entity of
{<<""/utf8>>, none, {ok, X@1}} ->
{ok, X@1};
{Name, Field_type, {ok, Default}} ->
Ft = find_field(Field_type),
{ok,
<<<<<<<<<<<<<<<<"DEFINE FIELD "/utf8, Name/binary>>/binary,
" ON TABLE "/utf8>>/binary,
Table/binary>>/binary,
" TYPE "/utf8>>/binary,
Ft/binary>>/binary,
" "/utf8>>/binary,
Default/binary>>/binary,
";"/utf8>>};
{Field, _, {error, _}} ->
{error,
<<"FAILED::: DEFINE FIELD FOR "/utf8, Field/binary>>}
end end).
-spec create_table_schemafull(
list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}),
binary()
) -> {ok, types:table_entity()} |
{error, list({ok, binary()} | {error, binary()})}.
create_table_schemafull(Entity_definition, Name) ->
Res = emit_fields(
begin
_pipe = Entity_definition,
lists:append(
_pipe,
[{<<""/utf8>>,
none,
{ok,
<<<<"DEFINE TABLE IF NOT EXISTS "/utf8,
Name/binary>>/binary,
" schemafull;"/utf8>>}}]
)
end,
Name
),
case begin
_pipe@1 = Res,
gleam@list:any(_pipe@1, fun gleam@result:is_error/1)
end of
true ->
{error, Res};
false ->
{ok, {table, Name, Entity_definition, Res}}
end.
-spec create_table_schemaless(
list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}),
binary()
) -> {ok, types:table_entity()} |
{error, list({ok, binary()} | {error, binary()})}.
create_table_schemaless(Entity_definition, Name) ->
Res = emit_fields(
begin
_pipe = Entity_definition,
lists:append(
_pipe,
[{<<""/utf8>>,
none,
{ok,
<<<<"DEFINE TABLE IF NOT EXISTS "/utf8,
Name/binary>>/binary,
" schemaless;"/utf8>>}}]
)
end,
Name
),
case begin
_pipe@1 = Res,
gleam@list:any(_pipe@1, fun gleam@result:is_error/1)
end of
true ->
{error, Res};
false ->
{ok, {table, Name, Entity_definition, Res}}
end.
-spec add_field(
list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}),
binary(),
types:field_type()
) -> list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}).
add_field(E, Field, Field_type) ->
[{Field, Field_type, {ok, <<""/utf8>>}} | E].
-spec add_default_field(
list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}),
binary(),
types:field_type(),
types:default_field_type()
) -> list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}).
add_default_field(E, Field, Field_type, D) ->
Res = case {Field_type, D} of
{string, {default_string, X}} ->
{ok, <<<<"\""/utf8, X/binary>>/binary, "\""/utf8>>};
{int, {default_int, X@1}} ->
{ok, gleam@int:to_string(X@1)};
{_, _} ->
{error,
<<<<"Field: "/utf8, Field/binary>>/binary,
" does not support the supplied default value for its type"/utf8>>}
end,
Fullfield = case Res of
{ok, X@2} ->
{Field, Field_type, {ok, <<"Default "/utf8, X@2/binary>>}};
{error, X@3} ->
{Field, Field_type, {error, X@3}}
end,
[Fullfield | E].
-spec generate(
list({binary(), types:field_type(), {ok, binary()} | {error, binary()}})
) -> list({binary(), types:field_type(), {ok, binary()} | {error, binary()}}).
generate(E) ->
gleam@io:debug(E).