Packages
gleam_mongo
0.3.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
Current section
Files
Jump to
Current section
Files
src/mongo@client.erl
-module(mongo@client).
-compile(no_auto_import).
-export([connect/1, collection/2, execute/2]).
-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, tcp:socket(), binary()}.
-type collection() :: {collection, database(), binary()}.
-spec connect(binary()) -> {ok, database()} | {error, nil}.
connect(Uri) ->
case parse_connection_string(Uri) of
{error, _try} -> {error, _try};
{ok, Info} ->
case Info of
{connection_info, Host, Port, Db, Auth, Auth_source} ->
case tcp:connect(Host, Port) of
{error, _try@1} -> {error, _try@1};
{ok, Socket} ->
case Auth of
none ->
{ok, {database, Socket, Db}};
{some, {Username, Password}} ->
case case Auth_source of
none ->
_pipe = Socket,
authenticate(
_pipe,
Username,
Password,
Db
);
{some, Source} ->
_pipe@1 = Socket,
authenticate(
_pipe@1,
Username,
Password,
Source
)
end of
{error, _try@2} -> {error, _try@2};
{ok, _@1} ->
{ok, {database, Socket, Db}}
end
end
end
end
end.
-spec collection(database(), binary()) -> collection().
collection(Db, Name) ->
{collection, Db, Name}.
-spec execute(collection(), bson@types:value()) -> {ok,
list({binary(),
bson@types:value()})} |
{error, {integer(), binary()}}.
execute(Collection, Cmd) ->
case erlang:element(2, Collection) of
{database, Socket, Name} ->
case begin
_pipe = Socket,
send_cmd(_pipe, Name, Cmd)
end of
{ok,
[{<<"ok"/utf8>>, {double, 0.0}},
{<<"errmsg"/utf8>>, {str, Msg}},
{<<"code"/utf8>>, {integer, Code}},
{<<"codeName"/utf8>>, _@1}]} ->
{error, {Code, Msg}};
{ok, Result} ->
{ok, Result};
{error, nil} ->
{error, {-2, <<""/utf8>>}}
end
end.
-spec authenticate(tcp:socket(), binary(), binary(), binary()) -> {ok,
list({binary(),
bson@types:value()})} |
{error, nil}.
authenticate(Socket, Username, Password, Auth_source) ->
First_payload = mongo@scram:first_payload(Username),
First = mongo@scram:first_message(First_payload),
case begin
_pipe = Socket,
send_cmd(_pipe, Auth_source, First)
end of
{error, _try} -> {error, _try};
{ok, Reply} ->
case mongo@scram:parse_first_reply(Reply) of
{error, _try@1} -> {error, _try@1};
{ok, {Server_params, Server_payload, Cid}} ->
case mongo@scram:second_message(
Server_params,
First_payload,
Server_payload,
Cid,
Password
) of
{error, _try@2} -> {error, _try@2};
{ok, {Second, _@1}} ->
case begin
_pipe@1 = Socket,
send_cmd(_pipe@1, Auth_source, Second)
end of
{error, _try@3} -> {error, _try@3};
{ok, Reply@1} ->
case Reply@1 of
[{<<"ok"/utf8>>, {double, 0.0}} | _@2] ->
{error, nil};
Reply@2 ->
{ok, Reply@2}
end
end
end
end
end.
-spec send_cmd(tcp:socket(), binary(), bson@types:value()) -> {ok,
list({binary(),
bson@types:value()})} |
{error, nil}.
send_cmd(Socket, Db, Cmd) ->
{document, Cmd@2} = case Cmd of
{document, Cmd@1} -> {document, Cmd@1};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mongo/client"/utf8>>,
function => <<"send_cmd"/utf8>>,
line => 116})
end,
Cmd@3 = gleam@list:append(Cmd@2, [{<<"$db"/utf8>>, {str, Db}}]),
Encoded = bson:encode(Cmd@3),
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 begin
_pipe@1 = Socket,
tcp:send(_pipe@1, Packet)
end of
ok ->
case begin
_pipe@2 = Socket,
tcp:'receive'(_pipe@2)
end of
{ok, Response} ->
<<_@1:168, Rest/bitstring>> = Response,
Rest,
case bson:decode(Rest) of
{ok, Result} ->
{ok, Result};
{error, nil} ->
{error, nil}
end;
{error, nil} ->
{error, nil}
end;
_@2 ->
{error, nil}
end.
-spec parse_connection_string(binary()) -> {ok, connection_info()} |
{error, nil}.
parse_connection_string(Uri) ->
case gleam@uri:parse(Uri) of
{error, _try} -> {error, _try};
{ok, Parsed} ->
case erlang:element(2, Parsed) of
{some, <<"mongodb"/utf8>>} ->
case erlang:element(4, Parsed) of
{some, <<""/utf8>>} ->
{error, nil};
{some, Host} ->
Port = begin
_pipe = erlang:element(5, Parsed),
gleam@option:unwrap(_pipe, 27017)
end,
case erlang:element(6, Parsed) of
<<""/utf8>> ->
{error, nil};
<<"/"/utf8>> ->
{error, nil};
Path ->
[_@1, Db] = gleam@string:split(
Path,
<<"/"/utf8>>
),
case gleam@uri:percent_decode(Db) of
{error, _try@1} -> {error, _try@1};
{ok, Db@1} ->
case erlang:element(3, Parsed) of
{some, Userinfo} ->
case gleam@string:split(
Userinfo,
<<":"/utf8>>
) of
[<<""/utf8>>, _@2] ->
{error, nil};
[_@3, <<""/utf8>>] ->
{error, nil};
[Username, Password] ->
case begin
_pipe@1 = [Username,
Password],
gleam@list:map(
_pipe@1,
fun gleam@uri:percent_decode/1
)
end of
[{ok,
Username@1},
{ok,
Password@1}] ->
case erlang:element(
7,
Parsed
) of
{some,
Query} ->
case begin
_pipe@2 = Query,
gleam@uri:parse_query(
_pipe@2
)
end of
{error, _try@2} -> {error, _try@2};
{ok, Opts} ->
case gleam@list:key_find(
Opts,
<<"authSource"/utf8>>
) of
{ok,
Auth_source} ->
{ok,
{connection_info,
Host,
Port,
Db@1,
{some,
{Username@1,
Password@1}},
{some,
Auth_source}}};
{error,
nil} ->
{ok,
{connection_info,
Host,
Port,
Db@1,
{some,
{Username@1,
Password@1}},
none}}
end
end;
none ->
{ok,
{connection_info,
Host,
Port,
Db@1,
{some,
{Username@1,
Password@1}},
none}}
end;
_@4 ->
{error, nil}
end;
_@5 ->
{error, nil}
end;
none ->
{ok,
{connection_info,
Host,
Port,
Db@1,
none,
none}}
end
end
end;
none ->
{error, nil}
end;
{some, _@6} ->
{error, nil};
none ->
{error, nil}
end
end.