Packages
gleam_mongo
0.18.0
0.18.1
retired
0.18.0
retired
0.17.0
retired
0.16.0
retired
0.15.1
retired
0.15.0
retired
0.14.0
retired
0.13.0
retired
0.12.0
retired
0.11.0
retired
0.10.0
retired
0.9.0
retired
0.8.0
retired
0.7.0
retired
0.6.0
retired
0.5.0
retired
0.4.0
retired
0.3.0
0.2.0
retired
0.1.3
retired
0.1.2
retired
0.1.1
retired
0.1.0
retired
A mongodb driver for gleam
Retired package: Renamed - Republished as mungo
Current section
Files
Jump to
Current section
Files
src/mongo@client.erl
-module(mongo@client).
-compile([no_auto_import, nowarn_unused_vars]).
-export([collection/2, execute/2, get_more/3, connect/1]).
-export_type([connection_info/0, database/0, collection/0]).
-opaque connection_info() :: {connection_info,
binary(),
integer(),
binary(),
gleam@option:option({binary(), binary()}),
gleam@option:option(binary())}.
-type database() :: {database, mongo@tcp:socket(), binary()}.
-type collection() :: {collection, database(), binary()}.
-spec collection(database(), binary()) -> collection().
collection(Db, Name) ->
{collection, Db, Name}.
-spec send_cmd(mongo@tcp:socket(), binary(), bson@value:value()) -> {ok,
list({binary(), bson@value:value()})} |
{error, nil}.
send_cmd(Socket, Db, Cmd) ->
{document, Cmd@1} = case Cmd of
{document, _} -> Cmd;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"mongo/client"/utf8>>,
function => <<"send_cmd"/utf8>>,
line => 122})
end,
Cmd@2 = gleam@list:key_set(Cmd@1, <<"$db"/utf8>>, {str, Db}),
Encoded = bson:encode(Cmd@2),
Size = gleam@bit_string:byte_size(Encoded) + 21,
Packet = begin
_pipe = [<<Size:32/little, 0:32, 0:32, 2013:32/little, 0:32, 0>>,
Encoded],
gleam@bit_string:concat(_pipe)
end,
case mongo@tcp:send(Socket, Packet) of
ok ->
case mongo@tcp:'receive'(Socket) of
{ok, Response} ->
<<_:168, Rest/bitstring>> = Response,
case bson:decode(Rest) of
{ok, Result} ->
{ok, Result};
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
_ ->
{error, nil}
end.
-spec execute(collection(), bson@value:value()) -> {ok,
list({binary(), bson@value:value()})} |
{error, {integer(), binary()}}.
execute(Collection, Cmd) ->
case erlang:element(2, Collection) of
{database, Socket, Name} ->
case send_cmd(Socket, Name, Cmd) of
{ok,
[{<<"ok"/utf8>>, {double, 0.0}},
{<<"errmsg"/utf8>>, {str, Msg}},
{<<"code"/utf8>>, {int32, Code}},
{<<"codeName"/utf8>>, _}]} ->
{error, {Code, Msg}};
{ok, Result} ->
{ok, Result};
{error, nil} ->
{error, {-2, <<""/utf8>>}}
end
end.
-spec get_more(collection(), integer(), integer()) -> {ok,
list({binary(), bson@value:value()})} |
{error, {integer(), binary()}}.
get_more(Collection, Id, Batch_size) ->
execute(
Collection,
{document,
[{<<"getMore"/utf8>>, {int64, Id}},
{<<"collection"/utf8>>, {str, erlang:element(3, Collection)}},
{<<"batchSize"/utf8>>, {int32, Batch_size}}]}
).
-spec authenticate(mongo@tcp:socket(), binary(), binary(), binary()) -> {ok,
nil} |
{error, nil}.
authenticate(Socket, Username, Password, Auth_source) ->
First_payload = mongo@scram:first_payload(Username),
First = mongo@scram:first_message(First_payload),
gleam@result:then(
send_cmd(Socket, Auth_source, First),
fun(Reply) ->
gleam@result:then(
mongo@scram:parse_first_reply(Reply),
fun(_use0) ->
{Server_params, Server_payload, Cid} = _use0,
gleam@result:then(
mongo@scram:second_message(
Server_params,
First_payload,
Server_payload,
Cid,
Password
),
fun(_use0@1) ->
{Second, Server_signature} = _use0@1,
gleam@result:then(
send_cmd(Socket, Auth_source, Second),
fun(Reply@1) -> case Reply@1 of
[{<<"ok"/utf8>>, {double, 0.0}} | _] ->
{error, nil};
Reply@2 ->
mongo@scram:parse_second_reply(
Reply@2,
Server_signature
)
end end
)
end
)
end
)
end
).
-spec parse_connection_string(binary()) -> {ok, connection_info()} |
{error, nil}.
parse_connection_string(Uri) ->
gleam@result:then(
gleam@uri:parse(Uri),
fun(Parsed) ->
gleam@bool:guard(
erlang:element(2, Parsed) /= {some, <<"mongodb"/utf8>>},
{error, nil},
fun() ->
gleam@bool:guard(
gleam@option:is_none(erlang:element(4, Parsed)) orelse (erlang:element(
4,
Parsed
)
=:= {some, <<""/utf8>>}),
{error, nil},
fun() ->
gleam@bool:guard(
gleam@list:contains(
[<<""/utf8>>, <<"/"/utf8>>],
erlang:element(6, Parsed)
),
{error, nil},
fun() ->
_assert_subject = erlang:element(4, Parsed),
{some, Host} = case _assert_subject of
{some, _} -> _assert_subject;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"mongo/client"/utf8>>,
function => <<"parse_connection_string"/utf8>>,
line => 155}
)
end,
Port = gleam@option:unwrap(
erlang:element(5, Parsed),
27017
),
Path = erlang:element(6, Parsed),
[_, Db] = gleam@string:split(
Path,
<<"/"/utf8>>
),
gleam@result:then(
gleam@uri:percent_decode(Db),
fun(Db@1) ->
gleam@bool:guard(
gleam@option:is_none(
erlang:element(3, Parsed)
),
{ok,
{connection_info,
Host,
Port,
Db@1,
none,
none}},
fun() ->
_assert_subject@1 = erlang:element(
3,
Parsed
),
{some, Userinfo} = case _assert_subject@1 of
{some, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"mongo/client"/utf8>>,
function => <<"parse_connection_string"/utf8>>,
line => 171}
)
end,
case gleam@string:split(
Userinfo,
<<":"/utf8>>
) of
[<<""/utf8>>, _] ->
{error, nil};
[_, <<""/utf8>>] ->
{error, nil};
[Username, Password] ->
case begin
_pipe = [Username,
Password],
gleam@list:map(
_pipe,
fun gleam@uri:percent_decode/1
)
end of
[{ok,
Username@1},
{ok,
Password@1}] ->
case erlang:element(
7,
Parsed
) of
{some,
Query} ->
gleam@result:then(
gleam@uri:parse_query(
Query
),
fun(
Opts
) ->
case gleam@list:key_find(
Opts,
<<"authSource"/utf8>>
) of
{ok,
Auth_source} ->
_pipe@1 = {connection_info,
Host,
Port,
Db@1,
{some,
{Username@1,
Password@1}},
{some,
Auth_source}},
{ok,
_pipe@1};
{error,
nil} ->
_pipe@2 = {connection_info,
Host,
Port,
Db@1,
{some,
{Username@1,
Password@1}},
none},
{ok,
_pipe@2}
end
end
);
none ->
_pipe@3 = {connection_info,
Host,
Port,
Db@1,
{some,
{Username@1,
Password@1}},
none},
{ok,
_pipe@3}
end;
_ ->
{error, nil}
end;
_ ->
{error, nil}
end
end
)
end
)
end
)
end
)
end
)
end
).
-spec connect(binary()) -> {ok, database()} | {error, nil}.
connect(Uri) ->
gleam@result:then(parse_connection_string(Uri), fun(Info) -> case Info of
{connection_info, Host, Port, Db, Auth, Auth_source} ->
gleam@result:then(
mongo@tcp:connect(Host, Port),
fun(Socket) -> case Auth of
none ->
{ok, {database, Socket, Db}};
{some, {Username, Password}} ->
gleam@result:then(case Auth_source of
none ->
authenticate(
Socket,
Username,
Password,
Db
);
{some, Source} ->
authenticate(
Socket,
Username,
Password,
Source
)
end, fun(_) ->
{ok, {database, Socket, Db}}
end)
end end
)
end end).